何为Systemverilo的线程或进程?
线程或进程是作为独立实体执行的任何一段代码。在verilog中,每个初始块和always块都派生为独立的线程,从0点开始并行运行。fork连接块还创建并行运行的不同线程。
不同的fork-join之间的区别?
下图为不同fork join的区别
fork join | Finishes when all child threads are over |
fork join_any | Finishes when any child thread gets over |
fork join_none | Finishes soon after child threads are spawned |
线程或进程应该用在测试平台的什么地方?
验证环境中的组件可能需要能够并发运行多个任务。例如,一个进程可能等待一些事情发生,而另一个进程则继续执行一些其他任务。它们都是通过fork…join语句作为单独的线程衍生出来的。例如,scoreboard可以并行生成不同的任务,以获取和验证来自测试台不同部分的数据。
Verilog fork join的局限?
只有当fork-join中派生的所有线程都完成时,fork…join之后的代码才执行。因此,scb必须等到fork-join中生成的所有线程都完成后才能继续。
fork join示例
Systemverilog 的fork…join会等待所有任务结束在执行后面的代码。
module tb_top;
initial begin
#1 $display ("[%0t ns] Start fork ...", $time);
// Main Process: Fork these processes in parallel and wait untill all
// of them finish
fork
// Thread1 : Print this statement after 5ns from start of fork
#5 $display ("[%0t ns] Thread1: Orange is named after orange", $time);
// Thread2 : Print these two statements after the given delay from start of fork
begin
#2 $display ("[%0t ns] Thread2: Apple keeps the doctor away", $time);
#4 $display ("[%0t ns] Thread2: But not anymore", $time);
end
// Thread3 : Print this statement after 10ns from start of fork
#10 $display ("[%0t ns] Thread3: Banana is a good fruit", $time);
join
// Main Process: Continue with rest of statements once fork-join is over
$display ("[%0t ns] After Fork-Join", $time);
end
endmodule
Simulation Log
ncsim> run
[1 ns] Start fork ...
[3 ns] Thread2: Apple keeps the doctor away
[6 ns] Thread1: Orange is named after orange
[7 ns] Thread2: But not anymore
[11 ns] Thread3: Banana is a good fruit
[11 ns] After Fork-Join
ncsim: *W,RNQUIE: Simulation is complete.
fork join_any示例
SystemVerilog fork join_any 会等到任何一个分支进程完成。
module tb_top;
initial begin
#1 $display ("[%0t ns] Start fork ...", $time);
// Main Process: Fork these processes in parallel and wait until
// any one of them finish
fork
// Thread1 : Print this statement after 5ns from start of fork
#5 $display ("[%0t ns] Thread1: Orange is named after orange", $time);
// Thread2 : Print these two statements after the given delay from start of fork
begin
#2 $display ("[%0t ns] Thread2: Apple keeps the doctor away", $time);
#4 $display ("[%0t ns] Thread2: But not anymore", $time);
end
// Thread3 : Print this statement after 10ns from start of fork
#10 $display ("[%0t ns] Thread3: Banana is a good fruit", $time);
join_any
// Main Process: Continue with rest of statements once fork-join is exited
$display ("[%0t ns] After Fork-Join", $time);
end
endmodule
Simulation Log
ncsim> run
[1 ns] Start fork ...
[3 ns] Thread2: Apple keeps the doctor away
[6 ns] Thread1: Orange is named after orange
[6 ns] After Fork-Join
[7 ns] Thread2: But not anymore
[11 ns] Thread3: Banana is a good fruit
ncsim: *W,RNQUIE: Simulation is complete.
fork join_none示例
SystemVerilog fork join_none 不会等待并立即退出块,允许分叉进程在后台运行。主线程恢复执行在 fork join_none 块之后的语句。
module tb_top;
initial begin
#1 $display ("[%0t ns] Start fork ...", $time);
// Main Process: Fork these processes in parallel and exits immediately
fork
// Thread1 : Print this statement after 5ns from start of fork
#5 $display ("[%0t ns] Thread1: Orange is named after orange", $time);
// Thread2 : Print these two statements after the given delay from start of fork
begin
#2 $display ("[%0t ns] Thread2: Apple keeps the doctor away", $time);
#4 $display ("[%0t ns] Thread2: But not anymore", $time);
end
// Thread3 : Print this statement after 10ns from start of fork
#10 $display ("[%0t ns] Thread3: Banana is a good fruit", $time);
join_none
// Main Process: Continue with rest of statements once fork-join is exited
$display ("[%0t ns] After Fork-Join", $time);
end
endmodule
Simulation Log
ncsim> run
[1 ns] Start fork ...
[1 ns] After Fork-Join
[3 ns] Thread2: Apple keeps the doctor away
[6 ns] Thread1: Orange is named after orange
[7 ns] Thread2: But not anymore
[11 ns] Thread3: Banana is a good fruit
ncsim: *W,RNQUIE: Simulation is complete.
SystemVerilog disable fork join
在前文中,讨论了启动并行线程的不同方法。现在我们将看到如何禁用分叉线程。所有从fork…join启动的活动线程都可以通过调用disable fork来终止。
为何需要禁用一个fork?
对于给定的例子,在仿真开始时会发生以下事情:
- 主线程执行初始块并找到一个fork join_any块
- 它将并行启动三个线程,并等待其中任何一个线程完成
- 线程首先完成,因为延迟最少
- 恢复执行主线程
Threadz和Thread3仍然在运行,即使主线程已经脱离了fork join_any块。
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 70ns
begin
#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 ("[%0tns] Fork join is done", $time);
end
endmodule
Simulation Log
ncsim> run
[20 ns] Show #20 $display statement
[40 ns] Show #40 $display statement
[40ns] Fork join is done
[60 ns] TIMEOUT
[70 ns] Show #50 $display statement
ncsim: *W,RNQUIE: Simulation is complete.
ncsim> exit
当fork被禁用时会发生什么?
上面的例子是相同的,最后添加了disable fork。由于禁用了fork, Thread2和Thread3被杀死了
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 70ns
begin
#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 ("[%0tns] Fork join is done, let's disable fork", $time);
disable fork;
end
endmodule
Simulation Log
ncsim> run
[20 ns] Show #20 $display statement
[40 ns] Show #40 $display statement
[40ns] Fork join is done, let's disable fork
ncsim: *W,RNQUIE: Simulation is complete.
ncsim> exit