一、多线程fork join/fork join_any/fork join_none的用法差异
fork…join:父进程会阻塞所有子线程结束。
fork…join_any:父进程会阻塞到任意一个线程结束。
fork…join_none:父进程会继续与所有子现成并发执行。
wait fork: 使父线程等待所有子线程执行完毕;一般用来确保所有子进程(调用进程产生的进程,也即一级子进程)执行都已经结束。
disable fork: 当执行disable fork时,会终止所有子线程的执行;
wait fork:
会引起调用进程阻塞直到它的所有子进程结束,
一般用来确保所有子进程(调用进程产生的进程)执行都已经结束
disable fork:
用来终止调用进程的所有活跃进程, 以及子进程的所有子进程
注意:wait fork作用的父进程下的子进程,而不包括子进程下的子进程,而disable fork则是作用于父进程下的所有进程,包括子进程的子进程
module tb_top;
initial begin// Fork off 3 sub-threads in parallel and the currently executing main thread// will finish when any of the 3 sub-threads have finished.fork// Thread1 : Will finish first at time 40ns#40 $display ("[%0t ns] Show #40 $display statement", $time); // Thread2 : Will finish at time 70nsbegin#20 $display ("[%0t ns] Show #20 $display statement", $time);#50 $display ("[%0t ns] Show #50 $display statement", $time);end// Thread3 : Will finish at time 60ns#60 $display ("[%0t ns] TIMEOUT", $time);join_any// Display as soon as the fork is done$display ("[%0t ns] Fork join is done, wait fork to end", $time);// Fork two more processesfork#10 $display ("[%0t ns] Wait for 10", $time);#20 $display ("[%0t ns] Wait for 20", $time);join_any// Wait until ALL forked processes are overwait fork;$display ("[%0t ns] Fork join is over", $time);end
endmodule
[20 ns] Show #20 $display statement
[40 ns] Show #40 $display statement
[40 ns] Fork join is done, wait fork to end
[50 ns] Wait for 10
[60 ns] TIMEOUT
[60 ns] Wait for 20
[70 ns] Show #50 $display statement
[70 ns] Fork join is over
首先需要知道的是,能够建立进程的只有initial块,always块,以及fork语句(也许还有其它的,我SV也没有了解透彻,欢迎指出问题)。 inital、always块、fork join创建静态进程, fork join_any 和 fork join_none创建动态进程。
了解这点之后我们就可以知道父进程是哪个范围,以及它有哪些子进程。在上述例子中, 调用进程就是initial挂起的一个begin块,它有哪些子进程?fork join_any的特点不在赘述,第一个fork join_any创建了三个进程(三条并行语句),第二个fork join_any创建了两个进程,一共五个。父进程调用的wait fork于是需要等待这五个进程全部结束之后才会打印后面的display,这五个进程结束得最晚的是Thread2, 花费70个仿真时间所以最后一个display打印时间是70 ns。
如果在wait fork之前打印一次时间,应该是50 ns,这个第一个和第二个fork join_any种的最短进程的花费时间之和。
在使用了fork… join_any或者fork… join_none以后,我们可以使用disable来指定需要停止的线程。
parameter TIME_OUT = 1000;
task check_trans{Transaction tr);
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