十二 · 2022年01月29日

仿真篇:时间管理大师—fork

本文来聊一聊如何在仿真中如何“多进程”时间管理。

绕不开的多进程仿真

忆往昔写Verilog与SystemVerilog时,在仿真过程中,不可避免的会出现多进程并发的情况,在构建仿真架构时,总是少不了这几个语法的出现:

  • fork-join:等待所有的进程执行完毕后退出
  • fork-join_none:所有的进程只要有一个执行结束即退出
  • fork-join_any: 不等待任何一个进程执行完毕即退出。

但凡熟悉Verilog、SystemVerilog的小伙伴,对于上面这三种语法的使用应该都了然于胸,这里不做过多的介绍。而在SpinalHDL的整个框架里,这点儿功能当然也要支持的。学会了使用SpinalHDL进行电路设计实现,那么基于Scala进行仿真测试的构建也是必不可少的。而在SpinalHDL的仿真框架中,同样,也会使用fork关键字来发起“多”进程访问。

不一样的fork

在SpinalHDL的仿真架构里,其基础是基于协程的(与cocotb思路相同,如果对于协程概念不甚了解也不必在意,SpinalHDL已经封装屏蔽了所有的底层实现细节)。在SpinalHDL中,通过fork会创建一个新的协程,这里的使用方式和Verilog中的fork略有不同。以Verilog中的fork-join为例:

initial
begin
  fork
    send(7);
    send(5);
    send(2);
  join
  $display("come out of fork-join @%t", $time);
  #100;
  $finish;
end

task automatic send(int j);
begin
    #(j);
    $display("driving port %0d @%t", j, $realtime);
end
endtask

这里通过fork来进行同时发起send(7),send(5),send(2)三个并行任务,而在SpinalHDL中,想要实现fork-join的使用效果,代码的构建形式如下:
image.png
在SpinalHDL仿真代码构建中,fork只负责发起一个协程,并返回该协程的句柄,而至于如果要阻塞等待协程执行完毕,则需调用该协程的join方法等待该协程执行完成。该协程的执行结果如下:

[Progress] Start joinTest test simulation with seed 1055571843
hello form threadA
hello form threadB
[Done] Simulation done in 58.286 ms

join_none

如前所述,是否要阻塞等待协程执行完毕取决于是否调用对应的join方法,那么如果想要实现不等待任何协程直接退出那么不调用join方法即可,如下所示:
image.png
此时,不会有任何打印信息:

[Progress] Start joinTest test simulation with seed 859904433
[Done] Simulation done in 8.890 ms

Process finished with exit code 0

join_any

SpinalHDL中针对join_any的场景,并未直接提供相应的API,但实现起来也并不复杂,这里给出一个example:

def joinAny(thread: SimThread*) = {
  while (!thread.map(_.done).reduce(_ | _)) {
    sleep(10)
  }
}
SimConfig.compile(joinTest()).doSim { dut =>
  dut.clockDomain.forkStimulus(10)
  dut.clockDomain.waitSampling(10)
  val threadA = fork {
    for (index <- 0 until 100) {
      dut.clockDomain.waitSampling()
    }
    println("hello form threadA")
  }
  val threadB = fork {
    for (index <- 0 until 1000) {
      dut.clockDomain.waitSampling()
    }
    println("hello form threadB")
  }
  joinAny(threadA, threadB)

此时,只有threadA中的内容会被打印显示:

[Progress] Start joinTest test simulation with seed 893248459
hello form threadA
[Done] Simulation done in 29.422 ms
作者:玉骐
原文链接:Spinal FPGA
微信公众号:
 title=

推荐阅读

更多SpinalHDL技术干货请关注Spinal FPGA专栏。
推荐阅读
关注数
1581
内容数
133
用SpinalHDL提升生产力
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息