十二 · 2023年11月28日

pipeline高端玩法(十一)—spawnIt

✎ 编 者 按 

英语学的不好,扒一扒pipeline中“spawn”的用法。

spawn

在Stage中,关于spawn,定义了下面的两个API:

def spawnIt()(implicit loc: Location) : Unit = spawnIt(ConditionalContext.isTrue)def spawnIt(cond : Bool)(implicit loc: Location) : Unit = internals.request.spawns += nameFromLocation(CombInit(cond), "spawnRequest")

spawn的调用,最终会把触发条件cond存储至internals.request.spawns中去。

而在Pipeline中,internal.request.spawns仅使用在了Internal Connection中:

//Internal connections    for(s <- stagesSet){      s.output.valid := s.input.valid      if(s.request.spawns.nonEmpty){        when(s.request.spawns.orR){          s.output.valid := True        }      }

可以看到,对于Stage内部,若果spawns非空,则spawns中只要有一个条件成立那么其output.valid即会设置为True,相当于对output.valid进行了扩展多个时钟周期。

值得注意的是,其仅对valid进行了扩展,而并没有处理input.ready信号。

看到这里,对于spawnIt的用法诸君应该能大体看明白,其就是为了对Stage中的output.valid进行延展。

example

由于spawnIt并没有对input.ready进行处理,故如果pipeline中如果有ready信号时使用需谨慎,这里给出一个pipeline中不使用ready的example:

case class SpawnTest() extends Component{
  val io=new Bundle{
    val data_in= slave (Flow(UInt(8 bits)))
    val data_out= master(Flow(UInt(8 bits)))
  }
  noIoPrefix()
  val cycle_num=Stageable(UInt(8 bits))
  val pip=new Pipeline{
    val stage0=new Stage{
      import internals._
      input.valid:=io.data_in.valid
      cycle_num:=io.data_in.payload
    }
    val stage1=new Stage(Connection.M2S()){}
    val stage2=new Stage(Connection.M2S()){
      io.data_out.valid:=internals.output.valid
      val cycle_cnt=Reg(UInt(8 bits)) init(0)
      when(internals.input.valid){
        cycle_cnt:=(cycle_num===1)?cycle_cnt|(cycle_num-1)
        io.data_out.payload:=cycle_num
      }otherwise{
        cycle_cnt:= (cycle_cnt.orR)? (cycle_cnt-1)|cycle_cnt
        io.data_out.payload:=cycle_cnt
      }
      spawnIt(cycle_cnt=/=0)
    }
  }
  pip.build()
}

这个例子中pipeline存在三个Stage,对于data_in,在stage2中会对根据data_in.payload的值展开相应的拍数(两个data_in有效数据确保有足够的间隔),示例波形如下:

image.png

可以看到,当data_in_payload为1时,data_out_payload输出一拍,数据为1.当data_in_payload为2时,data_out_payload输出两拍,数据分别为2,1.当data_in_payload为3时,data_out_payload输出三拍,数据分别为1,2,3.实现data_in.valid的扩展。

附上仿真代码:

import spinal.core.sim._
object SpawnTestSim extends App{
  SimConfig.withFstWave.compile(SpawnTest()).doSim{dut=>
    dut.io.data_in.valid#=false
    dut.clockDomain.forkStimulus(10)
    dut.clockDomain.waitSampling(10)
    dut.io.data_in.valid#=true
    dut.io.data_in.payload#=1
    dut.clockDomain.waitSampling()
    dut.io.data_in.valid#=false
    for(index<-0 until 10){
      dut.io.data_in.payload#=index
      dut.clockDomain.waitSampling()
    }
    dut.io.data_in.valid#=true
    dut.io.data_in.payload#=2
    dut.clockDomain.waitSampling()
    dut.io.data_in.valid#=false
    for(index<-0 until 10){
      dut.io.data_in.payload#=index
      dut.clockDomain.waitSampling()
    }
    dut.io.data_in.valid#=true
    dut.io.data_in.payload#=3
    dut.clockDomain.waitSampling()
    dut.io.data_in.valid#=false
    for(index<-0 until 10){
      dut.io.data_in.payload#=index
      dut.clockDomain.waitSampling()
    }

  }
}

☆ END ☆

作者:玉骐
原文链接:Spinal FPGA
微信公众号:
 title=

推荐阅读

更多SpinalHDL技术干货请关注[Spinal FPGA]欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。
推荐阅读
关注数
1581
内容数
133
用SpinalHDL提升生产力
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息