那曲檬骨新材料有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

一個簡單的pipeline是如何構建起來的?

Spinal FPGA ? 來源:Spinal FPGA ? 2023-08-12 11:18 ? 次閱讀

續接上文,這一次我們來詳細了解下一個簡單的pipeline是如何構建起來的

》最簡單的流水線

書接上文,一個最簡單的流水線例子,這里對data_in打兩拍做輸出:

b5c6ab92-38b3-11ee-9e74-dac502259ad0.png

我們逐行分析pipeline里每一行代碼都干了什么。

》Stage分析

在第八行我們聲明了一個Stageable變量,如前文所述,Stageable變量并不會立即產生電路對象。

代碼第9行,我們創建一個Stage,Stage中的下面的代碼會通過調用Pipeline中的addStage函數向Pipeline中的StageSet添加當前Stage:

if(_pip != null) {
_pip.addStage(this)
}

在stage0中,第11行用io.data_in.valid驅動stage0中的internals.input.valid。而在第12行,從左向右看,this(payload)函數會調用Stage的apply函數:

def apply[T <: Data](key : Stageable[T]) : T = {
????apply(StageableKey(key.asInstanceOf[Stageable[Data]], null)).asInstanceOf[T]
}

其進一步調用:

defapply(key : StageableKey):Data = {
internals.stageableToData.getOrElseUpdate(key, ContextSwapper.outsideCondScope{
key.stageable()//.setCompositeName(this, s"${key}")
})
}

可以看到,這里的主要作用是一StageableKey作為Key查詢internals.stageableToData中是否包含該key,如果有則返回其value,否則創建該key-value,并將value返回。

最終這里會返回一個UInt(8 bits)電路對象。并將io.data_in.payload賦值給該電路對象。此時,stage0中的internals.stageableToData中包含一個元素。

在第14行,我們創建了stage1,其例化時傳入了Connection,其會調用:

 if(_pip != null) {
_pip.addStage(this)
}

def chainConnect(connection: ConnectionLogic): Unit ={
_pip.connect(_pip.stagesSet.takeWhile(_ != this).last, this)(connection)
}

def this(connection: ConnectionLogic)(implicit_pip: Pipeline) {
this()
chainConnect(connection)
}

這里的的調用關系是:

當前Pipeline的StageSet添加當前Stage元素

通過調用pipeline的connect函數和StageSet中的最后一個元素建立連接關系:

defconnect(m : Stage, s : Stage)(logics : ConnectionLogic*) = {
val c = new ConnectionModel
connections += c
c.m = m
c.s = s
c.logics ++= logics
c
}

在connection里,創建了一個連接關系ConnectionModel,用于連接stage0中的output接口和stage1的input接口,采用M2S()方式進行連接。

同樣,15行同樣stage2的創建亦如此。

代碼第16行則是用stage2的output.valid驅動data_out的valid輸出。而代碼第17行通過同樣的方式創建了一個UInt(8 bits)電路對象,用來驅動data_out.payload。此時stage2中的internals.stageableToData中包含一個元素。

最后調用pipeline的build函數進行流水線的搭建。

》build分析

我們按片段來分析build中的代碼:

b6048a66-38b3-11ee-9e74-dac502259ad0.png

首先,上面第一行代碼將connection中的stage添加到stageSet。在執行該行之前,stageSet中包含了stage0、stage1、stage2三個元素,而connection按照描述進行map后得到兩個元素:(stage0,stage1),(stage1,stage2)。由于stageSet為LinkedHashSet,故執行完后依然是(stage0,stage1,stage2)。

第二行代碼則是獲取帶有slave驅動的stage,這里即stage0(驅動stage1)、stage1(驅動stage2)。

第三行則是獲取沒有slave驅動的stage,這里只有stage2。

第7~8行則是分別建立每個stage都是由誰驅動的映射存儲至stageMaster、而stage input的驅動邏輯則存儲至stageDriver。同時這里也限制了每個stage,最多只能由一個驅動邏輯。處理完后,stageMaster、stageDriver中存儲的元素分別為:

stageMaster:
stage0->ArrayBuffer()
stage1->ArrayBuffer(stage0)
stage2->ArrayBuffer(stage2)
stageDriver:
stage1->Connection(m=stage0,s=stage1,logic=M2S)
stage2->Connection(m=stage1,s=stage2,logic=M2S)

代碼13~16行由于我們并沒有使用到stageableResultingToData,這里可以暫時忽略,等后續章節再進行討論。

val clFlush = mutable.LinkedHashMap[ConnectionLogic, Bool]()
val clFlushNext = mutable.LinkedHashMap[ConnectionLogic, Bool]()
val clFlushNextHit = mutable.LinkedHashMap[ConnectionLogic, Bool]()
val clThrowOne = mutable.LinkedHashMap[ConnectionLogic, Bool]()
val clThrowOneHit = mutable.LinkedHashMap[ConnectionLogic, Bool]()

這里聲明的變量我們這里都是用不上,可以暫時先不進行關注。

def propagateData(key : StageableKey, stage : Stage): Boolean ={
if(stage.internals.stageableTerminal.contains(key)) returnfalse
stage.stageableToData.get(key) match {
caseNone => {
val hits = ArrayBuffer[Stage]()
for(m <- stageMasters(stage)){
????????if(propagateData(key, m)){
??????????stage.apply(key) //Force creation
??????????hits += m
????????}
??????}
??????hits.size match {
????????case?0?=> false
case1=> true
case2=> PendingError(s"$key at $stage has multiple drivers : ${hits.mkString(",")}"); false
}
}
caseSome(x) => true
}
}

for(stage <- stagesSet){
??for(key <- stage.stageableToData.keys){
????for(m <- stageMasters(stage)) {
??????propagateData(key, m);
????}
??}
}

這里就有點兒意思了對于StageSet中的每個stage中stageableToData中的每個元素,都會調用propgateData函數進行處理。我們不妨先來看看此時各stage中的stageableToData中的元素:

stage0:
StageableKey(payload,null)->UInt(8)
stage1:
null
stage2:
StageableKey(payload,null)->UInt(8)

由于stage0沒有master,無需考慮,stage1中stageableToData為空,也可以跳過。那么來看stage2,此時調用propagateData傳入的參數為:

key=StageableKey(payload,null)->UInt(8)
m=stage1

進入propagateData函數,由于stageableTerminal我們并未使用,繼續往下看,由于stage1中的stageableToData為空,故這里match匹配為None,此時會看stage1的master端口,此時嵌套調用propagateData,傳入參數為:

key=StageableKey(payload,null)->UInt(8)
m=stage0

由于stage0中的stageableToData包含該key,那么此時返回true退出,再次回到頭次調用的處理上。

由于嵌套返回true,那么此時會在stage1上調用apply函數,為stage1插入一個stageableKey。最終,各stage中stageableToData的結果為:

stage0:
StageableKey(payload,null)->UInt(8)
stage1:
StageableKey(payload,null)->UInt(8)
stage2:
StageableKey(payload,null)->UInt(8)

看到這里,是不是明白了一些門道了呢?pipeline自動幫我們補齊了stage1中所依賴的元素,完成了payload從stage0到stage2中的傳輸元素補齊。

對于propagateRequirements函數,這里我們并用不上,這里我們先無需關注。

接下來看時internal connections:

b6457df0-38b3-11ee-9e74-dac502259ad0.png

這里我們近會用到s.output.valid:=s.input.valid,即將每個stage中的internal.output.valid由internal.input.valid進行驅動。

剩下的就是stage之間的連接了:

for(c<- connections){
??val stageables = (c.m.stageableToData.keys).filter(key => c.s.stageableToData.contains(key) && !c.m.stageableTerminal.contains(key))
var m= ConnectionPoint(c.m.output.valid, c.m.output.ready, stageables.map(c.m.outputOf(_)).toList)
for((l, id) <- c.logics.zipWithIndex){
????val s = if(l?== c.logics.last)
??????ConnectionPoint(c.s.input.valid, c.s.input.ready, stageables.map(c.s.stageableToData(_)).toList)
????else?{
??????ConnectionPoint(Bool(), (m.ready != null) generate Bool(), stageables.map(_.stageable.craft()).toList)
????}
????val area = l.on(m, s, clFlush(l), clFlushNext(l), clFlushNextHit(l), clThrowOne(l), clThrowOneHit(l))
????if(c.logics.size != 1)
??????area.setCompositeName(c, s"level_$id", true)
????else
??????area.setCompositeName(c, true)
????m?= s
??}
}

對于每個connection,首先是將master端和slave端stage共有的stageableToData給篩選到stageables中去,這里對應的為:

Connection(m=stage0,s=stage1,logic=M2S):
StageableKey(payload,null)
Connection(m=stage1,s=stage2,logic=M2S):
StageableKey(payload,null)

接著創建ConnectionPoint,對應的paylaod即為StageabelKey所對應的電路對象,也就意味著:

Connection(m=stage0,s=stage1,logic=M2S): 
m=ConenctionPoint(stage0.out.valid,stage0.out.ready,stage0.stageableToData(StageableKey(payload,null)))
s=ConenctionPoint(stage1.in.valid,stage1.in.ready,stage1.stageableToData(StageableKey(payload,null)))
Connection(m=stage1,s=stage2,logic=M2S):
m=ConenctionPoint(stage1.out.valid,stage1.out.ready,stage1.stageableToData(StageableKey(payload,null)))
s=ConenctionPoint(stage2.in.valid,stage2.in.ready,stage2.stageableToData(StageableKey(payload,null)))

最終,調用M2S.on創建stage之間的連接關系:

b6a44b0a-38b3-11ee-9e74-dac502259ad0.png

這里我們只用到6~7行,建立起各stage之間的連接關系。

至此!完成整個流水線的創建。

》寫在最后

通過本篇,分析了一個簡單的流水線在Pipeline中的創建實現,后續將陸續進行更加復雜流水線的Demo及其背后自動實現原理。






審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 處理器
    +關注

    關注

    68

    文章

    19409

    瀏覽量

    231207
  • 驅動器
    +關注

    關注

    53

    文章

    8272

    瀏覽量

    147075
  • 存儲器
    +關注

    關注

    38

    文章

    7528

    瀏覽量

    164351
  • 連接器
    +關注

    關注

    98

    文章

    14669

    瀏覽量

    137248
  • Pipeline
    +關注

    關注

    0

    文章

    28

    瀏覽量

    9384

原文標題:pipeline高端玩法(三)——一個pipeline是如何建立起來的

文章出處:【微信號:Spinal FPGA,微信公眾號:Spinal FPGA】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    如何構建簡單的對講電路

    在這個電路中,我們將構建非常簡單的對講電路,您可以使用該電路在房屋或學校內以兩種方式進行本地通信。這個項目帶來了童年的記憶,即使用火柴盒和線來制作
    的頭像 發表于 11-21 17:26 ?1740次閱讀
    如何<b class='flag-5'>構建</b><b class='flag-5'>一</b><b class='flag-5'>個</b><b class='flag-5'>簡單</b>的對講電路

    如何構建簡單而強大的MP3播放器

    在本教程中,我們將學習如何構建簡單而強大的 MP3 播放器,可以播放任何 MP3 歌曲,音量和曲目也可以借助按鈕進行調整。通過些額外的
    的頭像 發表于 01-25 17:32 ?5288次閱讀
    如何<b class='flag-5'>構建</b><b class='flag-5'>一</b><b class='flag-5'>個</b><b class='flag-5'>簡單</b>而強大的MP3播放器

    分享51上寫的簡單的操作系統,包含完整全部程序

    外圍電路和程序都寫得很熟練了,要想成為單片機真正應用,必須懂時間片輪度法,狀態機,最后達到單片機系統的境界,網上有很多RTOS,uc/os2,等系統,但那些都太專業,需要本書專門學,這里分享圈圈寫的小系統,大家可以在里面專
    發表于 07-15 13:30

    電子時鐘

    `在knewmaker上看見這么篇文章,感覺還行,轉了數字電子時鐘可是電子DIY入門第課,對于了解電路知識和提高動手能力有著很大的幫助。今天小編帶來的是通過純數字模塊搭
    發表于 05-31 10:22

    針對ARM產品系列的Linux

    Linux是類似Unix的電腦操作系統,利用免費和開源的軟件開發以及分銷模式構建起來。專有嵌入式操作系統的優勢包括,擁有不受單軟件公司限制的員工作支持基礎,能夠修改和重新發布源代
    發表于 02-09 14:32

    微波濾波器應用選擇需要注意哪些事項?

    微波濾波器搭建起來簡單,但理解起來比較復雜。它們在系統中完成基本的功能:阻止某些信號,通過其它信號。但可以用許多不同的方式實現這種功能
    發表于 08-19 06:35

    如何構建簡單的傳感器?

    您可以自己構建簡單的傳感器。 我的博客上有 PNP 和
    發表于 04-28 08:23

    元宇宙概念是什么意思

    元宇宙般指通過多種科技所構建起來種虛擬的宇宙形式,平行于現實世界的虛擬世界,旨在元宇宙中實現在現實中人們可以做到的事。
    的頭像 發表于 11-01 09:47 ?1.4w次閱讀

    如何構建簡單的基于紅外的車門遙控器

    在這篇文章中,我們將學習如何構建簡單但萬無失的基于紅外的遙控器,該遙控器可用于通過個人遙控手機鎖定和解鎖任何車門。
    的頭像 發表于 04-02 10:37 ?1377次閱讀
    如何<b class='flag-5'>構建</b><b class='flag-5'>一</b><b class='flag-5'>個</b><b class='flag-5'>簡單</b>的基于紅外的車門遙控器

    文解析新型電力系統與智能裝備技術

    新型電力系統是指基于智能電網、清潔能源、能源互聯網等技術和理念,構建起來的高效、安全、可靠、可持續的電力系統。
    發表于 04-24 11:50 ?3575次閱讀
    <b class='flag-5'>一</b>文解析新型電力系統與智能裝備技術

    構建簡單的機械臂

    電子發燒友網站提供《構建簡單的機械臂.zip》資料免費下載
    發表于 06-14 14:55 ?0次下載
    <b class='flag-5'>構建</b><b class='flag-5'>一</b><b class='flag-5'>個</b><b class='flag-5'>簡單</b>的機械臂

    構建簡單的提醒報警電路

    一個工作狂可能聽起來有點酷。但研究表明,傾向于長時間坐在電腦前工作的人患糖尿病、心臟病等疾病的風險很高。所以我想設計簡單的電路,可以幫
    的頭像 發表于 06-18 10:14 ?892次閱讀
    <b class='flag-5'>構建</b><b class='flag-5'>一</b><b class='flag-5'>個</b><b class='flag-5'>簡單</b>的提醒報警電路

    如何構建簡單的家庭自動化

    電子發燒友網站提供《如何構建簡單的家庭自動化.zip》資料免費下載
    發表于 07-05 11:41 ?0次下載
    如何<b class='flag-5'>構建</b><b class='flag-5'>一</b><b class='flag-5'>個</b><b class='flag-5'>簡單</b>的家庭自動化

    什么是pipeline?Go中構建流數據pipeline的技術

    本文介紹了在 Go 中構建流數據pipeline的技術。 處理此類pipeline中的故障很棘手,因為pipeline中的每個階段可能會阻止嘗試向下游發送值,并且下游階段可能不再關心傳
    的頭像 發表于 03-11 10:16 ?668次閱讀

    為THS3001構建簡單的SPICE模型

    電子發燒友網站提供《為THS3001構建簡單的SPICE模型.pdf》資料免費下載
    發表于 10-29 10:11 ?1次下載
    為THS3001<b class='flag-5'>構建</b><b class='flag-5'>一</b><b class='flag-5'>個</b><b class='flag-5'>簡單</b>的SPICE模型
    博盈开户| 大玩家百家乐现金网| 百家乐官网必胜绝| 做生意带什么招财| 巴宝莉百家乐的玩法技巧和规则 | 百家乐平注常赢打法| 百家乐和怎么算输赢| 大发888hanpa| 易发娱乐| 银泰百家乐官网龙虎斗| 新锦江百家乐官网娱乐网| 火箭百家乐官网的玩法技巧和规则 | 全讯网12580a.com| 百家乐的视频百家乐| 现场百家乐的玩法技巧和规则| bet365娱乐在线| 百家乐官网单跳| CEO百家乐官网娱乐城| 24楼风水化解| 盛世国际娱乐| 宝马会网上娱乐| 百家乐官网博送彩金18| 百家乐现金网平台排名| 威尼斯人娱乐城 2013十一月九问好| 获嘉县| 百家乐赌博机原理| 棋牌游戏平台哪个好| 澳门百家乐官网规则| 百家乐博娱乐平台赌百家乐| 梁平县| 澳门百家乐开户投注| 在线娱乐场| 银泰百家乐龙虎斗| 百家乐官网半圆桌| 捷豹百家乐娱乐城| 百家乐官网网络赌场| 大发888提款速度快吗| 金百亿百家乐娱乐城| 百家乐官网街机游戏下载| 幸运水果机小游戏| 家百家乐破解软件|