編 者 按
來看看Pipeline中的flush操作
flush
在Stage中,對于Flush有提供這兩個(gè)函數(shù):
defflushIt(): Unit = flushIt(ConditionalContext.isTrue) defflushIt(cond : Bool, root : Boolean = true): Unit = { internals.request.flush += cond if(root) internals.request.flushRoot += cond }
可以看出,調(diào)用flush函數(shù),會牽涉到internals.request中的fulsh以及flushRoot兩個(gè)元素:
val flush = ArrayBuffer[Bool]() val flushRoot = ArrayBuffer[Bool]()
那么來分別看下這兩個(gè)元素在Pipeline的build函數(shù)中都起了什么作用。
在build函數(shù)中,對于處于pipeline中沒有驅(qū)動其他Stage的Stage,會調(diào)用propagateRequirements函數(shù):
for(end<- connectionsWithoutSinks){ ??propagateRequirements(end) }
同時(shí),build函數(shù)中有定義:
val clFlush = mutable.LinkedHashMap[ConnectionLogic, Bool]()
在函數(shù)propagateRequirements中:
var flush= stage.internals.request.flush.nonEmpty generate orR(stage.internals.request.flush)
也就意味著如果當(dāng)前stage中若flush非空,則會將flush中的所有信號進(jìn)行或操作得到一個(gè)flush信號。
(stage.internals.arbitration.isFlushed, flush) match { case(null, null) => case(x, null) =>stage.isFlushed := False case(_, x) =>stage.isFlushed := flush }
若flush非空,那么就會驅(qū)動賦值給stage中的internals.arbitration.
isFlushed。
defisFlushed:Bool = { if(internals.arbitration.isFlushed == null) internals.arbitration.isFlushed = ContextSwapper.outsideCondScope(Bool()) internals.arbitration.isFlushed }
對于驅(qū)動當(dāng)前stage的Connection Logic,也會對flush有進(jìn)行檢測:
c.logics.reverseIterator.foreach{ l => clFlush(l) = flush clFlushNext(l) = flushNext clFlushNextHit(l) = null if(flushNext != null){ clFlushNextHit(l) = Bool() flush = flush match { casenull=> clFlushNext(l) && clFlushNextHit(l) case_ => flush || clFlushNext(l) && clFlushNextHit(l) } flushNext = l.alwasContainsSlaveToken match { casetrue=> null casefalse=> clFlushNext(l) && !clFlushNextHit(l) } } if(flush != null) c.m.flushIt(flush, false) if(flushNext != null) c.m.flushNext(flushNext) clThrowOne(l) = throwOne clThrowOneHit(l) = null if(throwOne != null){ clThrowOneHit(l) = Bool() throwOne = l.alwasContainsSlaveToken match { casetrue=> null casefalse=> clThrowOne(l) && !clThrowOneHit(l) } } }
我們著重關(guān)注和flush相關(guān)的邏輯。首先會講flush注冊到驅(qū)動當(dāng)前Stage的Conntection Logic中的clFlush中:
clFlush(l) = flush
此處flushNext我們先不用管,為null。而flush為非空,故對于驅(qū)動當(dāng)前Stage的master側(cè)Stage,會調(diào)用其flush函數(shù)以flush為變量為其注冊flush動作(注意,root參數(shù)傳輸?shù)臑閒alse)。也就具備了前向傳播的特性:
c.m.flushIt(flush, false)
隨后通過遞歸,flush動作也就回一直向前傳播:
for(m <- stageMasters(stage)){ ??if(stage.internals.arbitration.propagateReady) m.internals.arbitration.propagateReady = true ??propagateRequirements(m) }
在每一級的Stage關(guān)系里,默認(rèn)情況下:
s.output.valid := s.input.valid
而當(dāng)flushRoot非空時(shí),則會:
if(s.internals.request.flushRoot.nonEmpty) s.output.validclearWhen(s.internals.arbitration.isFlushingRoot)
也就意味著output.valid會立即清空。
而在處理InterConnection時(shí),會用到上面的clFlush:
valarea = l.on(m, s, clFlush(l), clFlushNext(l), clFlushNextHit(l), clThrowOne(l), clThrowOneHit(l))
我們以M2S為例,其中定義了:
if (flush!= null&& !flushPreserveInput) s.valid clearWhen(flush)
s.valid為寄存器,也就意味著當(dāng)flush為true時(shí),s.valid將會在下一拍驅(qū)動為0,即下一級的Stage的input.valid將會在下一拍清零。
功能總結(jié)
結(jié)合Pipeline中的源代碼,可以總結(jié)下flushIt的作用。
調(diào)用flushIt函數(shù),會想request.flush中添加cond,若root 為true,則會向request.flushRoot中同時(shí)添加cond。
request.flush作用:
對StageN調(diào)用flushIt,在pipeline.build函數(shù)中會向其所有的前級Stage中同樣添加調(diào)用相應(yīng)的flushIt函數(shù)(root為false)
request.flush主要在conntecion Logic中起作用,用于清除s.valid,即下一級的input.valid。
request.flushRoot的作用:
request.flushRoot用于清除當(dāng)前級的output.valid
默認(rèn)情況下,每一級的output.valid:=input.valid
當(dāng)flushRoot.orR為True時(shí),會立即清除當(dāng)前Stage的output.valid
flushRoot中的元素并不會向前級傳輸
flushRoot的作用區(qū)分:
當(dāng)在StageN調(diào)用flushIt時(shí)如果希望cond為true時(shí)下一拍不希望Stage(N+1)input.valid拉起,則需將root設(shè)置為true。否則因?yàn)閛utput.valid:=input.valid,stageN的output.valid會驅(qū)動下一級的input.valid為True(之所以前向傳輸調(diào)用flushIt時(shí)root=false,原因在于flush會作用于Connection Logic確保下一拍valid清零)。
example
給一個(gè)簡單的example:
caseclassTest5() extendsComponent{ val io=newBundle{ val data_in=slave(Flow(UInt(8bits))) val data_out=master(Flow(UInt(8bits))) val cond=inBool() } noIoPrefix() val A=Stageable(UInt(8bits)) val pip=newPipeline{ val stage0=newStage{ internals.input.valid:=io.data_in.valid A:=io.data_in.payload } val stage1=newStage(Connection.M2S()){} val stage2=newStage(Connection.M2S()){ io.data_out.valid:=internals.output.valid io.data_out.payload:=A this.flushIt(io.cond) } } }
這里在stage2調(diào)用flushIt函數(shù),當(dāng)io.cond為true時(shí),整個(gè)流水線都將會清空。而由于root默認(rèn)為true,故io.cond為true時(shí),io.data_out.valid會立即為0,即等效于:
io.data_out.valid:=internals.output.valid&(~io.cond)
如果root設(shè)置為false,那么io.cond為true時(shí)io.data_out.valid仍可能為True。
審核編輯:湯梓紅
-
函數(shù)
+關(guān)注
關(guān)注
3文章
4337瀏覽量
62730 -
Pipeline
+關(guān)注
關(guān)注
0文章
28瀏覽量
9370 -
FLUSH
+關(guān)注
關(guān)注
0文章
4瀏覽量
5435
原文標(biāo)題:pipeline高端玩法(七)—flush
文章出處:【微信號:Spinal FPGA,微信公眾號:Spinal FPGA】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論