編 者 按
來看看Pipeline中的flush操作
flush
在Stage中,對(duì)于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ù),會(huì)牽涉到internals.request中的fulsh以及flushRoot兩個(gè)元素:
val flush = ArrayBuffer[Bool]() val flushRoot = ArrayBuffer[Bool]()
那么來分別看下這兩個(gè)元素在Pipeline的build函數(shù)中都起了什么作用。
在build函數(shù)中,對(duì)于處于pipeline中沒有驅(qū)動(dòng)其他Stage的Stage,會(huì)調(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非空,則會(huì)將flush中的所有信號(hào)進(jìn)行或操作得到一個(gè)flush信號(hào)。
(stage.internals.arbitration.isFlushed, flush) match { case(null, null) => case(x, null) =>stage.isFlushed := False case(_, x) =>stage.isFlushed := flush }
若flush非空,那么就會(huì)驅(qū)動(dòng)賦值給stage中的internals.arbitration.
isFlushed。
defisFlushed:Bool = { if(internals.arbitration.isFlushed == null) internals.arbitration.isFlushed = ContextSwapper.outsideCondScope(Bool()) internals.arbitration.isFlushed }
對(duì)于驅(qū)動(dòng)當(dāng)前stage的Connection Logic,也會(huì)對(duì)flush有進(jìn)行檢測(cè):
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)的邏輯。首先會(huì)講flush注冊(cè)到驅(qū)動(dòng)當(dāng)前Stage的Conntection Logic中的clFlush中:
clFlush(l) = flush
此處flushNext我們先不用管,為null。而flush為非空,故對(duì)于驅(qū)動(dòng)當(dāng)前Stage的master側(cè)Stage,會(huì)調(diào)用其flush函數(shù)以flush為變量為其注冊(cè)flush動(dòng)作(注意,root參數(shù)傳輸?shù)臑閒alse)。也就具備了前向傳播的特性:
c.m.flushIt(flush, false)
隨后通過遞歸,flush動(dòng)作也就回一直向前傳播:
for(m <- stageMasters(stage)){ ??if(stage.internals.arbitration.propagateReady) m.internals.arbitration.propagateReady = true ??propagateRequirements(m) }
在每一級(jí)的Stage關(guān)系里,默認(rèn)情況下:
s.output.valid := s.input.valid
而當(dāng)flushRoot非空時(shí),則會(huì):
if(s.internals.request.flushRoot.nonEmpty) s.output.validclearWhen(s.internals.arbitration.isFlushingRoot)
也就意味著output.valid會(huì)立即清空。
而在處理InterConnection時(shí),會(huì)用到上面的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將會(huì)在下一拍驅(qū)動(dòng)為0,即下一級(jí)的Stage的input.valid將會(huì)在下一拍清零。
功能總結(jié)
結(jié)合Pipeline中的源代碼,可以總結(jié)下flushIt的作用。
調(diào)用flushIt函數(shù),會(huì)想request.flush中添加cond,若root 為true,則會(huì)向request.flushRoot中同時(shí)添加cond。
request.flush作用:
對(duì)StageN調(diào)用flushIt,在pipeline.build函數(shù)中會(huì)向其所有的前級(jí)Stage中同樣添加調(diào)用相應(yīng)的flushIt函數(shù)(root為false)
request.flush主要在conntecion Logic中起作用,用于清除s.valid,即下一級(jí)的input.valid。
request.flushRoot的作用:
request.flushRoot用于清除當(dāng)前級(jí)的output.valid
默認(rèn)情況下,每一級(jí)的output.valid:=input.valid
當(dāng)flushRoot.orR為True時(shí),會(huì)立即清除當(dāng)前Stage的output.valid
flushRoot中的元素并不會(huì)向前級(jí)傳輸
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會(huì)驅(qū)動(dòng)下一級(jí)的input.valid為True(之所以前向傳輸調(diào)用flushIt時(shí)root=false,原因在于flush會(huì)作用于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è)流水線都將會(huì)清空。而由于root默認(rèn)為true,故io.cond為true時(shí),io.data_out.valid會(huì)立即為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文章
4346瀏覽量
63013 -
Pipeline
+關(guān)注
關(guān)注
0文章
28瀏覽量
9384 -
FLUSH
+關(guān)注
關(guān)注
0文章
4瀏覽量
5441
原文標(biāo)題:pipeline高端玩法(七)—flush
文章出處:【微信號(hào):Spinal FPGA,微信公眾號(hào):Spinal FPGA】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
求助,能否在一個(gè)pipeline中添加多個(gè)音頻輸入流?
Pipeline ADCs Come of Age
![<b class='flag-5'>Pipeline</b> ADCs Come of Age](https://file1.elecfans.com//web2/M00/A4/C3/wKgZomUMNZWAKYV1AAAppdqwwAY001.gif)
Pipeline ADCs Come of Age
![<b class='flag-5'>Pipeline</b> ADCs Come of Age](https://file1.elecfans.com//web2/M00/A4/CF/wKgZomUMNceAI4L8AAAppdqwwAY085.gif)
評(píng)論