线程控制 fork
线程控制
1. 线程控制
1.1. 并行线程
fork...join
需要所有的并行的线程都结束以后才会继续执行fork...join_any
则会等到任何一个线程结束以后就继续执行fork...join_none
则不会等待其他子线程而继续执行
fork
begin // thread-1
$display("First Block!\n");
# 20ns;
end
begin // thread-2
$display("Second Block!\n");
@eventA;
end
join
fork...join_any
和fork_join_none
继续执行后,其一些未完成的子程序仍将在后台运行- 如果要等待这些子程序全部完成,或者停止这些子程序可以使用
wait fork
或者disable fork
task mt_test;
fork
exce1();
exce2();
join_any
fork
exec3();
exec4();
join_none
wait fork; // block until exec1 ... exec4 complete
endtask
1.2. 一些代码示例
1.2.1. 多个initial并行执行
module tb;
task automatic exec(int id, int t);
$display("@%t exec[%0d entered]", $time, id);
#t;
$display("@%t exec[%0d exited]", $time, id);
endtask
initial begin exec(1, 10); end
initial begin exec(2, 20); end
initial begin exec(3, 30); end
initial begin exec(4, 40); end
endmodule
1.2.2. 单个initial内串行执行
module tb2;
task automatic exec(int id, int t);
$display("@%t exec[%0d entered]", $time, id);
#t;
$display("@%t exec[%0d exited]", $time, id);
endtask
initial begin
exec(1, 10);
exec(2, 20);
exec(3, 30);
exec(4, 40);
end
endmodule
1.2.3. fork…join内并行执行
module tb3;
task automatic exec(int id, int t);
$display("@%t exec[%0d entered]", $time, id);
#t;
$display("@%t exec[%0d exited]", $time, id);
endtask
initial begin
fork
exec(1, 10);
exec(2, 20);
exec(3, 30);
exec(4, 40);
join
end
endmodule
1.2.4. join_any和join_none
module tb4;
task automatic exec(int id, int t);
$display("@%t exec[%0d entered]", $time, id);
#t;
$display("@%t exec[%0d exited]", $time, id);
endtask
initial begin: ini_proc1
$display("@%t fork-join_any entered", $time);
fork
exec(1, 10);
exec(2, 20);
join_any
$display("@%t fork-join_any exited", $time);
$display("@%t fork-join_none entered", $time);
fork
exec(3, 30);
exec(4, 40);
join_none
$display("@%t fork-join_none exited", $time);
$display("@%t ini_proc1 exited", $time);
end
initial begin
#200;
end
endmodule
initial本该在10ns的时候退出,但是fork块内的线程还没有结束
1.2.5. wait fork
wait fork
可以让当前initial块等待前面的fork
执行完后再继续
module tb5;
task automatic exec(int id, int t);
$display("@%t exec[%0d entered]", $time, id);
#t;
$display("@%t exec[%0d exited]", $time, id);
endtask
initial begin: ini_proc1
$display("@%t fork-join_any entered", $time);
fork
exec(1, 10);
exec(2, 20);
join_any
$display("@%t fork-join_any exited", $time);
$display("@%t fork-join_none entered", $time);
fork
exec(3, 30);
exec(4, 40);
join_none
$display("@%t fork-join_none exited", $time);
wait fork;
$display("@%t ini_proc1 exited", $time);
end
initial begin
#200;
end
endmodule
1.2.6. disable fork
disable fork
可以让当前initial内没有执行完的fork线程结束
module tb6;
task automatic exec(int id, int t);
$display("@%t exec[%0d entered]", $time, id);
#t;
$display("@%t exec[%0d exited]", $time, id);
endtask
initial begin: ini_proc1
$display("@%t fork-join_any entered", $time);
fork
exec(1, 10);
exec(2, 20);
join_any
$display("@%t fork-join_any exited", $time);
$display("@%t fork-join_none entered", $time);
fork
exec(3, 30);
exec(4, 40);
join_none
$display("@%t fork-join_none exited", $time);
disable fork;
$display("@%t ini_proc1 exited", $time);
end
initial begin
#200;
end
endmodule
1.2. 时序控制
- SV可以通过延迟控制或者时间等待来对过程块完成时序控制
- 延迟控制即通过
#
来完成
#10 rega = regb; - 事件(event)控制即通过
@
来完成
@r rega = regb;
@(posedge clk) rega = regb; wait
语句也可以与事件或者表达式结合来完成
real AOR[];
initial wait(AOR.size() > 0) …;