✎ 编 者 按
来看下Pipeline中HaltIt的用法
HaltIt
看名字,就基本能猜到这个函数的大体功能是流水线暂停。
在Stage中,流水线暂停提供了这么几个API:
def haltIt()(implicit loc: Location) : Unit = haltIt(ConditionalContext.isTrue)def haltIt(cond : Bool)(implicit loc: Location) : Unit = internals.request.halts += nameFromLocation(CombInit(cond), "haltRequest")def haltWhen(cond : Bool)(implicit loc: Location) : Unit = haltIt(cond)
三个API最终所实现的都是往internals.request.halts中添加cond条件。那么就看下request.halts在Pipeline构建时所起的作用。
首先,在进行 connectionsWithoutSinks(没有驱动其他级Stage)往前遍历的函数propagateRequirements中:
if(stage.request.halts.nonEmpty){ stage.arbitration.propagateReady = true stage.isReady //Force creation}
可以看到,如果stage中的internals.request.halts非空,这里做了两件事:
- stage.arbitration.propagateReady设置为true,即需向前级Stage传递Ready信号
- 为本级创建input.ready信号
随后在propagateRequirements中的代码片段:
stageDriver.get(stage) match { case Some(c : ConnectionModel) => { if(c.s.arbitration.propagateReady && c.m.output.ready == null){ c.m.output.ready = Bool() if(c.m.input.ready == null){ c.m.input.ready = Bool() } }
这里在处理当前Stage中的ConnectionLogic时,因为当前stage.arbitration.propagateReady为true,如果驱动当前Stage的Master Stage的output.ready为空,那么这里就会确保Master Stage中具备input.ready以及output.ready,确保上级Stage具备这种握手机制。
而后在该函数中的递归调用:
for(m <- stageMasters(stage)){ if(stage.internals.arbitration.propagateReady) m.internals.arbitration.propagateReady = true propagateRequirements(m)}
这里如果当前stage如果存在stage.arbitration.propagateReady为true,那么也会设置其Master Stage的.arbitration.propagateReady为true,通过递归调用,确保整个链路上ready信号一直向前传播,即确保反压一路到底。
最后,在处理Stage Internal Connection阶段时:
if(s.request.halts.nonEmpty){ val doHalt = s.request.halts.orR when(doHalt){ s.input.ready := False s.output.valid := False }}
如果当前Stage中request.halts中条件满足,那么当前stage中的output.valid,input.ready信号将会统一拉低,从而暂停向下级传输。
Example
case class Test8() extends Component{ val io=new Bundle{ val data_in=slave(Stream(UInt(8 bits))) val data_out=master(Stream(UInt(8 bits))) val cond=in Bool() } noIoPrefix() val A=Stageable(UInt(8 bits)) val pip=new Pipeline{ val stage0=new Stage{ this.driveFrom(io.data_in) A:=io.data_in.payload } val stage1=new Stage(Connection.M2S()){ } val stage2=new Stage(Connection.M2S()){ io.data_out.valid:=this.internals.output.valid io.data_out.payload:=A internals.output.ready=Bool() this.haltIt(io.cond) internals.output.ready:=io.data_out.ready this.internals.arbitration.propagateReady=true } } pip.build()}
这里给出了一个haltIt的example。在staeg2阶段,如果cond为true,那么则流水线暂停。
这里需注意的是这里将stage2的output.ready由io.data_out.ready信号进行驱动,但output.ready信号是默认不会创建的,故这里显示创建internals.output.ready为Bool类型电路对象。
☆ END ☆
作者:玉骐
原文链接:Spinal FPGA
微信公众号:
推荐阅读
更多SpinalHDL技术干货请关注[Spinal FPGA]欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。