1 什么是SystemVerilog线程?
一个线程是指一段被当作独立的实体执行的代码。在Verilog中,每一个initial或always块在在时间0刻触发一个并发运行的线程。一个fork join 可以创建并发运行的多个线程。
2 有哪些不同形式的fork join?
SystemVerilog中主要有三种不同形式的fork join:
fork join | 所有子线程都结束后才结束 |
fork join_any | 任一子线程结束后就结束 |
fork join_none | 子线程一触发就结束 |
注意:在 fork join块内的语句都是并发执行的。若在fork join块内使用begin end块,begin end块内的语句是顺序执行的。
3 如何停止线程?
停止单个线程
可以使用典型的Verilog语句disable来停止一个署名块中的所有线程。
parameter TIME_OUT=1000;
task check_trans(Transaction te);
fork
begin
//等待回应,或者达到某个最大延时
fork:timeout_block
begin
wait(bus.cb.addr==tr.addr);
$display("@%0t:Addr match%d",$time,tr.addr);
end
#TIME_OUT $display("@%0t:Error:timeout",$time);
join_any
disable timeout_block;
end
join_none
endtask
停止多个线程
SystemVerilog引入disable fork语句来停止从当前线程中衍生出来的所有子线程。
initial begin
check_trans(tr0); //线程0
//创建一个线程来限制disable fork的作用范围
fork //线程1
begin
check_trans(tr1); //线程2
fork //线程3
check_trans(tr2); //线程4
join
//停止线程1-4,单独保留线程0
#(TIME_OUT/2) disable fork;
end
join
end
4 等待所有衍生线程
在SystemVerilog中,当程序中的initial块全部执行完毕,仿真器就退出了。有些线程运行时间比较长,可以使用wait fork语句来等待所有子线程结束。
task run_threads;
... //创建一些事务
fork
check_trans(tr1); //产生第一个线程
check_trans(tr2); //产生第二个线程
check_trans(tr3); //产生第三个线程
join_none
... //完成其他工作
//在这里等待上述线程结束
wait fork;
endtask
5 动态线程
在Verilog中,线程是可预知的。你可以通过统计源代码中initial、always和fork..join块的数量来确定一个模块中有多少线程。而在SystemVerilog中,可以动态地创建线程,而且不用等到它们都执行完毕。
//动态线程的创建
program automatic test
...
task check_trans(Transaction tr);
fork
...
end
endtask
...
endprogram
6 线程中的自动变量
如果没有使用自带存储的程序(program)或模块(module),在并发的线程中务必使用自动变量来保存数值。否则,任务使用的是静态存储,每个线程将会共享相同的变量,这会导致后面的调用将覆盖前面调用的值。