1、fork.. join, join_any以及join_none的用法进行总结
1.1、 fork..join
fork..join: 必须等到statement1,statement2,statement3全部执行完之后,statement4才可以执行。fork…join内的所有语句都是并发执行(对于begin…end内部是顺序执行)
示例:
//---------fork...join-------------
initial begin
$display("@ %0t: start fork...join example", $time);
#10 $display("@ %0t: sequential after # 10", $time);
fork
$display("@ %0t: parallel start", $time);
#50 $display("@ %0t: parallel start # 50", $time);
#10 $display("@ %0t: parallel after #10", $time);
begin
#30 $display("@ %0t: sequential after # 30", $time);
#10 $display("@ %0t: sequential after # 10", $time);
end
join
$display("@ %0t: after join", $time);
#80 $display("@ %0t: finish after # 80", $time);
end
程序运行结果:
@ 0: start fork...join_any example
@ 10: sequential after # 10
@ 10: parallel start
@ 10: after join_any
@ 20: parallel after #10
@ 40: sequential after # 30
@ 50: sequential after # 10
@ 60: parallel start # 50
@ 90: finish after # 80
1.2、fork..join_any
fork..join_any: 等到statement1,statement2,statement3之中任何一个执行完毕之后,statement4才可以执行。一旦fork…join_any内任何一个线程完成,父线程就会继续运行。fork…join_none块在调度其块语句时,父线程继续执行。
//---------fork...join_any-------------
initial begin
$display("@ %0t: start fork...join_any example", $time);
#10 $display("@ %0t: sequential after # 10", $time);
fork
$display("@ %0t: parallel start", $time);
#50 $display("@ %0t: parallel start # 50", $time);
#10 $display("@ %0t: parallel after #10", $time);
begin
#30 $display("@ %0t: sequential after # 30", $time);
#10 $display("@ %0t: sequential after # 10", $time);
end
join_any
$display("@ %0t: after join_any", $time);
#80 $display("@ %0t: finish after # 80", $time);
end
程序运行结果:
1.3、fork..join_none
fork..join_none: statement4的执行与否不依赖于statement1,statement2和statement3,他们可以同步执行。子线程和父线程会同时执行。
//---------fork...join_none-------------
initial begin
$display("@ %0t: start fork...join_none example", $time);
#10 $display("@ %0t: sequential after # 10", $time);
fork
$display("@ %0t: parallel start", $time);
#50 $display("@ %0t: parallel start # 50", $time);
#10 $display("@ %0t: parallel after #10", $time);
begin
#30 $display("@ %0t: sequential after # 30", $time);
#10 $display("@ %0t: sequential after # 10", $time);
end
join_none
$display("@ %0t: after join_none", $time);
#80 $display("@ %0t: finish after # 80", $time);
end
运行结果如下:
@ 0: start fork...join_none example
@ 10: sequential after # 10
@ 10: after join_none
@ 10: parallel start
@ 20: parallel after #10
@ 40: sequential after # 30
@ 50: sequential after # 10
@ 60: parallel start # 50
@ 90: finish after # 80
在使用过程中经常需要多线程操作,多线程的正确写法为:
for(int i=0;i<3;i++)begin
fork
automatic idx = i
begin
`uvm_do(do[i]);
end
join_none
end
这样就完成了一个简单的多线程,这里为什么要用automatic关键字定义idx,可以参考下面的详细解释。
2、局部数据存储 automatic作用
Verilog中由于任务中局部变量会使静态存储区,当在多个地方调用同一个任务时,不同线程之间会窜用这些局部变量。
Systemverilog中,module和program块中,缺省使用静态存储;如果想使用自动存储,需加入automatic关键词。