Overview
fork...join结构提供了创建并行进程的能力。在Systemverilog里主要有三种版本:
- fork...join (join all)
- fork...join_none
- fork...join_any
fork-join同verilog里面的功能是一样。
fork-join_none不会等创建的进程完成,直接执行后面的语句。
fork-join_any会等待至少一个进程完成,然后再执行后继的语句。
Example
Basic
SV code
//
// Created by : Harris Zhu
// Filename : test.sv
// Author : harriszhHarris
// Created On : 2017-11-09 07:54
// Last Modified :
// Update Count : 2017-11-09 07:54
// Tags : fork join
// Description :
// Conclusion :
//=======================================================================
//
`timescale 1ns/1ns
module test;
string testname;
initial
begin
$timeformat(-9, 0, "ns", 4);
if($value$plusargs("TEST=%s", testname))
begin
$display("TESTNAME=%s", testname);
end
if(testname=="ALL")
begin
fork
send(7);
send(5);
send(2);
join
$display("come out of fork-join @%t", $time);
#100;
$finish;
end
if(testname=="NONE")
begin
fork
send(7);
send(5);
send(2);
join_none
$display("come out of fork-join_none @%t", $time);
wait fork;
$display("wait fork returned @%t", $time);
#100;
$finish;
end
if(testname=="ANY")
begin
fork
send(7);
send(5);
send(2);
join_any
$display("come of of fork-join_any @%t", $time);
wait fork;
$display("wait fork returned @%t", $time);
#100;
$finish;
end
end
task automatic send(int j);
begin
#(j);
$display("driving port %0d @%t", j, $realtime);
end
endtask // send
endmodule
makefile
SIM=irun
SIMOPTS=-sv
SRC=test.sv
run: all
all:
${SIM} ${SIMOPTS} ${SRC} +TEST=ALL -log $@.log
none:
${SIM} ${SIMOPTS} ${SRC} +TEST=NONE -log $@.log
any:
${SIM} ${SIMOPTS} ${SRC} +TEST=ANY -log $@.log
Run
- make all
TESTNAME=ALL
driving port 2 @ 2ns
driving port 5 @ 5ns
driving port 7 @ 7ns
come out of fork-join @ 7ns
Simulation complete via $finish(1) at time 107 NS + 0
./test.sv:40 $finish;
fork-join等到最后一个进程退出才返回
- make any
TESTNAME=ANY
driving port 2 @ 2ns
come of of fork-join_any @ 2ns
driving port 5 @ 5ns
driving port 7 @ 7ns
wait fork returned @ 7ns
Simulation complete via $finish(1) at time 107 NS + 0
./test.sv:66 $finish;
fork-join_any在第一个进程完成后就返回了
- make none
TESTNAME=NONE
come out of fork-join_none @ 0ns
driving port 2 @ 2ns
driving port 5 @ 5ns
driving port 7 @ 7ns
wait fork returned @ 7ns
Simulation complete via $finish(1) at time 107 NS + 0
./test.sv:53 $finish;
fork-join_none直接返回,没有等任何进程完成
Advance
在使用fork...jone的时候,我们往往还会和for loop一起使用,因为语言的问题,其实大部分人都会范错误,主要集中在对for循环里的index使用上,另外就是在wait使用上,具体见下文。
SV code
/
// Created by : Harris Zhu
// Filename : test.sv
// Author : harriszhHarris
// Created On : 2017-11-09 07:54
// Last Modified :
// Update Count : 2017-11-09 07:54
// Tags : fork join
// Description :
// Conclusion :
//=======================================================================
//
module test;
string testname;
initial
begin
$timeformat(-9, 0, "ns", 4);
if($value$plusargs("TEST=%s", testname))
begin
$display("TESTNAME=%s", testname);
end
end
initial
begin
if(testname=="ALL")
begin
for(int i = 0; i < 16; i++)
begin
fork
automatic int index =i;
send(index);
join
end
$display("fork-join return @%t", $time);
#100;
$finish;
end
if(testname=="NONE")
begin
for(int i = 0; i < 16; i++)
begin
fork
automatic int index =i;
send(index);
join_none
end
$display("fork-join_none returned @%t", $time);
wait fork;
$display("wait-fork returned @%t", $time);
#100;
$finish;
end
if(testname=="ANY")
begin
for(int i = 0; i < 16; i++)
begin
fork
begin
automatic int index =i;
send(index);
end
join_any
end
$display("fork-join_any returned @%t", $time);
wait fork;
$display("wait-fork returned @%t", $time);
#100;
$finish;
end
end
task automatic send(int j);
begin
#(j);
$display("driving port %0d %t", j, $realtime);
end
endtask // send
endmodule
makefile
SIM=irun
SIMOPTS=-sv
SRC=test.sv
run: all
all:
${SIM} ${SIMOPTS} ${SRC} +TEST=ALL -log $@.log
none:
${SIM} ${SIMOPTS} ${SRC} +TEST=NONE -log $@.log
any:
${SIM} ${SIMOPTS} ${SRC} +TEST=ANY -log $@.log
Run
- make all
TESTNAME=ALL
driving port 0 0
driving port 1 1
driving port 2 3
driving port 3 6
driving port 4 10
driving port 5 15
driving port 6 21
driving port 7 28
driving port 8 36
driving port 9 45
driving port 10 55
driving port 11 66
driving port 12 78
driving port 13 91
driving port 14 105
driving port 15 120
fork-join return @ 120
Simulation complete via $finish(1) at time 220 NS + 0
./test.sv:41 $finish;
- make any
TESTNAME=ANY
driving port 0 0
driving port 1 1
driving port 2 3
driving port 3 6
driving port 4 10
driving port 5 15
driving port 6 21
driving port 7 28
driving port 8 36
driving port 9 45
driving port 10 55
driving port 11 66
driving port 12 78
driving port 13 91
driving port 14 105
driving port 15 120
fork-join_any returned @ 120
wait-fork returned @ 120
Simulation complete via $finish(1) at time 220 NS + 0
./test.sv:73 $finish;
- make none
TESTNAME=NONE
fork-join_none returned @ 0
driving port 0 0
driving port 1 1
driving port 2 2
driving port 3 3
driving port 4 4
driving port 5 5
driving port 6 6
driving port 7 7
driving port 8 8
driving port 9 9
driving port 10 10
driving port 11 11
driving port 12 12
driving port 13 13
driving port 14 14
driving port 15 15
wait-fork returned @ 15
Simulation complete via $finish(1) at time 115 NS + 0
./test.sv:56 $finish;
从上面结果看, 只有join_none实现了并行
原因是顺序的fork...join块还是顺序执行的
同时要注意在fork..join里不要有begin...end
for(int i = 0; i < 16; i++)
begin
fork
automatic int index =i;
send(index);
join_none
end
自动变量的创建和初始化是在执行和它们位于同一block内的任何过程语句之前
对于wait fork的使用要注意,它是等待当前进程的所有子线程。
所以为了避免有副作用,要像如下这样写
fork
some_other_process;
join_none
fork
begin : isolation_process
for(int j=1; j <=3; ++j) begin : for_loop
fork
automatic int k = j;
begin
.... # use k here
end
join_none
end : for_loop
wait fork; // will not wait for some other process
end :isolation_thread
join
summary
总体来说,三种形式各有用处,但在绝大多数情况下又可以用其中一种实现其他两种。 但在fork-join_none的应用范畴更广一些,在并行进程数不定的情况下需要用它才能实行并行。
有任何问题和建议,欢迎发信给作者一起探讨
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。