看完了前面的系列,對于Stageable、StageableKey是如何起作用的應(yīng)該有一定的了解。今天再來看下Stage中關(guān)于terminal的作用
》terminal
在Stage中,有關(guān)terminal的定義牽涉到兩個terminal函數(shù)和一個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]()
可以看到,對一個stageable、stageableKey調(diào)用terminal,其會將數(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填充其前級有,后級stage中也有,但本級沒有的stageable/stageableKey至stageableToData,可以看到,這里的處理一旦發(fā)現(xiàn)stageableKey在當(dāng)前stage的stageableTerminal中包含,那么其將會不再向前級搜索,也就意味著這個信號的傳遞在當(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時,是將stageableTerminal中的信號給過濾掉了,也就意味著在stageableTerminal對應(yīng)的信號將不會進(jìn)行Connection連接。也就意味著在進(jìn)行Stage之間的連接時,會將相鄰兩級的stageableToData中共有的信號進(jìn)行連接,如果該信號也同時被注冊到了stageableTerminal中,那么該信號將會排除在外,即terminal提供了一個能夠終止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 } } }
我們在stage0中為C注冊了termianl,此時對于stage0中的stageableToData包含三個元素A,B,C,而stageableTerminal中則包含了C。而對于Stage1,其stageableToData包含了A,B,C三個元素,那么也就意味著stage0中的C將不會傳遞到stage1中,僅有A、B兩個元素會在stage之間連接。所有stage1中的C將會由stage1中的A+B驅(qū)動,而不是stage0中的C驅(qū)動。
審核編輯:劉清
-
處理器
+關(guān)注
關(guān)注
68文章
19896瀏覽量
235292 -
驅(qū)動器
+關(guān)注
關(guān)注
54文章
8697瀏覽量
149983 -
連接器
+關(guān)注
關(guān)注
99文章
15390瀏覽量
140568 -
Pipeline
+關(guān)注
關(guān)注
0文章
29瀏覽量
9695
原文標(biāo)題:pipeline高端玩法(五)——Terminal
文章出處:【微信號:Spinal FPGA,微信公眾號:Spinal FPGA】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
鴻蒙Stage模型--概述

從FA模型切換到Stage模型時:module的切換說明
RTThread中關(guān)于buildlib選項(xiàng)的作用應(yīng)該怎么使用
RTThread中關(guān)于buildlib選項(xiàng)的作用應(yīng)該怎么使用?
Windows Terminal Services
軟件使用SMMUv3的stage1還是stage2地址轉(zhuǎn)換

評論