看完了前面的系列,對(duì)于Stageable、StageableKey是如何起作用的應(yīng)該有一定的了解。今天再來看下Stage中關(guān)于terminal的作用
》terminal
在Stage中,有關(guān)terminal的定義牽涉到兩個(gè)terminal函數(shù)和一個(gè)LinkedHashSet:
def terminal(key : StageableKey) : StageableKey = { internals.stageableTerminal += key key } def terminal[T <: Data](key : Stageable[T], key2 : Any) : StageableKey = { ????terminal(StageableKey(key.asInstanceOf[Stageable[Data]], key2)) ??} val stageableTerminal = mutable.LinkedHashSet[StageableKey]()
可以看到,對(duì)一個(gè)stageable、stageableKey調(diào)用terminal,其會(huì)將數(shù)據(jù)壓到stageableTerminal中。
我們之前說過,pipeline的構(gòu)建核心在Pipeline中的build函數(shù)上。那么來看下在pipeline的build函數(shù)中stageableTerminal都起了什么作用。
stageableTerminal在build函數(shù)中出現(xiàn)了兩次。第一次是pipeline的payload填充:
//Fill payload holes in the pipeline 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 } }
我們前面提過,propagatedData用于向stage填充其前級(jí)有,后級(jí)stage中也有,但本級(jí)沒有的stageable/stageableKey至stageableToData,可以看到,這里的處理一旦發(fā)現(xiàn)stageableKey在當(dāng)前stage的stageableTerminal中包含,那么其將會(huì)不再向前級(jí)搜索,也就意味著這個(gè)信號(hào)的傳遞在當(dāng)前Stage中止。
另一處出現(xiàn)的地方則是Interconnect stages:
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 ??????} ????}
可以看到,這里在選擇master stage要傳遞到slave stage中的stageables時(shí),是將stageableTerminal中的信號(hào)給過濾掉了,也就意味著在stageableTerminal對(duì)應(yīng)的信號(hào)將不會(huì)進(jìn)行Connection連接。也就意味著在進(jìn)行Stage之間的連接時(shí),會(huì)將相鄰兩級(jí)的stageableToData中共有的信號(hào)進(jìn)行連接,如果該信號(hào)也同時(shí)被注冊(cè)到了stageableTerminal中,那么該信號(hào)將會(huì)排除在外,即terminal提供了一個(gè)能夠終止stageable在Stage之間傳播連接的途徑。
》Demo
來看下下面的例子:
caseclassTest2() extendsComponent{ val io=newBundle{ val data_in=slave(Flow(Vec(UInt(8bits),4))) val data_out=master(Flow(UInt(8bits))) } noIoPrefix() val A,B,C=Stageable(UInt(8bits)) val pip=newPipeline{ val staeg0=newStage{ this.internals.input.valid:=io.data_in.valid A:=io.data_in.payload(0)+io.data_in.payload(1) B:=io.data_in.payload(2)+io.data_in.payload(3) C:=io.data_in.payload(1)+io.data_in.payload(3) this.terminal(C,null) } val stage1=newStage(Connection.M2S()){ C:=A+B io.data_out.payload:=C io.data_out.valid:=this.internals.output.valid } } }
我們?cè)趕tage0中為C注冊(cè)了termianl,此時(shí)對(duì)于stage0中的stageableToData包含三個(gè)元素A,B,C,而stageableTerminal中則包含了C。而對(duì)于Stage1,其stageableToData包含了A,B,C三個(gè)元素,那么也就意味著stage0中的C將不會(huì)傳遞到stage1中,僅有A、B兩個(gè)元素會(huì)在stage之間連接。所有stage1中的C將會(huì)由stage1中的A+B驅(qū)動(dòng),而不是stage0中的C驅(qū)動(dòng)。
審核編輯:劉清
-
處理器
+關(guān)注
關(guān)注
68文章
19293瀏覽量
229966 -
驅(qū)動(dòng)器
+關(guān)注
關(guān)注
52文章
8242瀏覽量
146430 -
連接器
+關(guān)注
關(guān)注
98文章
14535瀏覽量
136606 -
Pipeline
+關(guān)注
關(guān)注
0文章
28瀏覽量
9370
原文標(biāo)題:pipeline高端玩法(五)——Terminal
文章出處:【微信號(hào):Spinal FPGA,微信公眾號(hào):Spinal FPGA】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論