看完了前面的系列,對于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在當前stage的stageableTerminal中包含,那么其將會不再向前級搜索,也就意味著這個信號的傳遞在當前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)的信號將不會進行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驅(qū)動,而不是stage0中的C驅(qū)動。
審核編輯:劉清
-
處理器
+關(guān)注
關(guān)注
68文章
20248瀏覽量
252143 -
驅(qū)動器
+關(guān)注
關(guān)注
54文章
9078瀏覽量
155446 -
連接器
+關(guān)注
關(guān)注
104文章
16135瀏覽量
146985 -
Pipeline
+關(guān)注
關(guān)注
0文章
29瀏覽量
9960
原文標題:pipeline高端玩法(五)——Terminal
文章出處:【微信號:Spinal FPGA,微信公眾號:Spinal FPGA】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
鴻蒙Stage模型--概述
Stage 模型深入解讀
RTThread中關(guān)于buildlib選項的作用應(yīng)該怎么使用
RTThread中關(guān)于buildlib選項的作用應(yīng)該怎么使用?
Windows Terminal Services
軟件使用SMMUv3的stage1還是stage2地址轉(zhuǎn)換
看下Stage中關(guān)于terminal的作用
評論