本文来聊一聊如何在仿真中如何“多进程”时间管理。
绕不开的多进程仿真
忆往昔写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的使用效果,代码的构建形式如下:
在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方法即可,如下所示:
此时,不会有任何打印信息:
[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
微信公众号:
推荐阅读
更多SpinalHDL技术干货请关注Spinal FPGA专栏。