看完了前面的系列,對于Stageable、StageableKey是如何起作用的應該有一定的了解。今天再來看下Stage中關于terminal的作用
》terminal
在Stage中,有關terminal的定義牽涉到兩個terminal函數和一個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調用terminal,其會將數據壓到stageableTerminal中。
我們之前說過,pipeline的構建核心在Pipeline中的build函數上。那么來看下在pipeline的build函數中stageableTerminal都起了什么作用。
stageableTerminal在build函數中出現了兩次。第一次是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,可以看到,這里的處理一旦發現stageableKey在當前stage的stageableTerminal中包含,那么其將會不再向前級搜索,也就意味著這個信號的傳遞在當前Stage中止。
另一處出現的地方則是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對應的信號將不會進行Connection連接。也就意味著在進行Stage之間的連接時,會將相鄰兩級的stageableToData中共有的信號進行連接,如果該信號也同時被注冊到了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驅動,而不是stage0中的C驅動。
審核編輯:劉清
-
處理器
+關注
關注
68文章
19259瀏覽量
229653 -
驅動器
+關注
關注
52文章
8226瀏覽量
146253 -
連接器
+關注
關注
98文章
14476瀏覽量
136430 -
Pipeline
+關注
關注
0文章
28瀏覽量
9361
原文標題:pipeline高端玩法(五)——Terminal
文章出處:【微信號:Spinal FPGA,微信公眾號:Spinal FPGA】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論