module test;
initial begin
main();
end
task main();
// fork join_any block1
fork
#5 $display("THREAD 1 %0t", $time);
#25 $display("THREAD 2 %0t", $time);
join_any
dev_state();
$display("After task call %0t", $time);
#100 $finish;
endtask
task dev_state();
// fork join_any block2
fork
#5 $display("THREAD 3 %0t", $time);
#10 $display("THREAD 4 %0t", $time);
join_any
disable fork;
endtask
initial begin
$display("debug point fork_1");
fork_1();
$display("debug point fork_2");
fork_2();
$display("debug point fork_3");
fork_3();
$display("debug point fork_4");
fork_4();
end
task fork_1();
for(int i = 0; i < 16; i++) begin
fork
// begin
automatic int index =i;
send(index);
// end
join_none
end
wait fork;
endtask
task fork_2();
for(int i = 0; i < 16; i++) begin
fork
// begin
automatic int index;
index = i;
send(index);
// end
join_none
end
wait fork;
endtask
task fork_3();
for(int i = 0; i < 16; i++) begin
fork
begin
automatic int index;
index = i;
send(index);
end
join_none
end
wait fork;
endtask
task fork_4();
for(int i = 0; i < 16; i++) begin
automatic int index;
index = i;
fork
begin
send(index);
end
join_none
end
wait fork;
endtask
task send(int j);
$display("driving port %0d" , j);
endtask
endmodule
all : clean comp run sim.log
clean:
\rm -rf simv* csrc *.key
comp:
vcs -full64 test.sv -sverilog
run:
simv -l sim.log
debug point fork_1
driving port 0
driving port 1
driving port 2
driving port 3
driving port 4
driving port 5
driving port 6
driving port 7
driving port 8
driving port 9
driving port 10
driving port 11
driving port 12
driving port 13
driving port 14
driving port 15
debug point fork_2
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
debug point fork_3
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
driving port 16
debug point fork_4
driving port 0
driving port 1
driving port 2
driving port 3
driving port 4
driving port 5
driving port 6
driving port 7
driving port 8
driving port 9
driving port 10
driving port 11
driving port 12
driving port 13
driving port 14
driving port 15
THREAD 1 5
THREAD 3 10
After task call 10
使用以上Makefile和test.sv文件,運行仿真,仿真結果如下
可以看到雖然都是fork join_none wait fork但是每一個fork_x task的打印結果是不同的。這是爲什麼呢?
不同之處在於變量index的生存週期,以及何時爲該變量分配變量i的值的時間。
意識到將有16個併發變量名爲index,只有一個名爲i。在情況1)和2)中,每次進入fork / join_none塊時都會創建index變量。在派生fork / join_none中的任何進程之前發生。在情況1)中,變量初始化也發生在fork / join_none中的任何進程之前。您需要記住的是,自動變量是在輸入時創建的,並在執行它們所在的塊中的任何過程語句之前被初始化。因此,在情況1)中,每個索引變量在每次循環迭代中都獲得i的當前值。
在情況2)中,您將初始化移到了單獨的過程分配語句中。 fork / join_none中的每個語句將成爲新的子進程,並且直到當前父線程掛起後,該子進程纔開始執行。現在,for循環會生成16個線程,然後在i的值爲16時在wait fork處掛起。(正如我之前說過的,如果send(index)看到單位值0或分配的值16,這是一個競賽。
在情況3)中,現在在一個begin / end塊內聲明index變量,這是fork / join_none的單個語句。因此,直到所有16個進程都已生成並且i的值爲16時,才創建索引變量。
任何自動變量的生命週期都將在其塊及其所有嵌套塊的生命週期結束時結束。