SystemVerilog - Thread

2023-07-02
SystemVerilog

Verilog如果同時存在多個initial/always block,他們會同時平行的開始執行。
SystemVerilog可以用 fork join block來達到平行行的效果,如同C/C++的thread。

有三種join方式
fork join所有子Thread結束後完成
fork join_any任何一個Thread結束後完成
fork join_none所有子Thread生成後完成


Example - fork join:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
module tb;
initial begin
#5 $display("t:%0d started", $time);

fork
#20 $display("t:%0d thread1-step1", $time);

begin
#5 $display("t:%0d thread2-step1", $time);
#10 $display("t:%0d thread2-step2", $time);
end
#5 $display("t:%0d thread3-step1", $time);

join

$display("t:%0d finished", $time);
end
endmodule

Output:

1
2
3
4
5
6
7
8
# run 10000
# t:5 started
# t:10 thread2-step1
# t:10 thread3-step1
# t:20 thread2-step2
# t:25 thread1-step1
# **t:25 finished**
# quit -f

fork join要等到三個thread都執行完畢之後才會往下執行


Example - fork join_any:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
module tb;
initial begin
#5 $display("t:%0d started", $time);

fork
#20 $display("t:%0d thread1-step1", $time);

begin
#5 $display("t:%0d thread2-step1", $time);
#10 $display("t:%0d thread2-step2", $time);
end
#5 $display("t:%0d thread3-step1", $time);

join_any

$display("t:%0d finished", $time);
end
endmodule

fork join_any只要有一個thread執行完畢之後就會往下執行

Output:

1
2
3
4
5
6
7
8
# run 10000
# t:5 started
# t:10 thread2-step1
# t:10 thread3-step1
# **t:10 finished**
# t:20 thread2-step2
# t:25 thread1-step1
# quit -f

Example - fork join_none:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
module tb;
initial begin
$display("t:%0d started", $time);

fork
#20 $display("t:%0d thread1-step1", $time);

begin
#5 $display("t:%0d thread2-step1", $time);
#10 $display("t:%0d thread2-step2", $time);
end
#5 $display("t:%0d thread3-step1", $time);

join_none

$display("t:%0d finished", $time);
end
endmodule

Output:

1
2
3
4
5
6
7
8
# run 10000
# t:0 started
# **t:0 finished**
# t:5 thread2-step1
# t:5 thread3-step1
# t:15 thread2-step2
# t:20 thread1-step1
# quit -f

fork join_none只要thread開好之後就會往下執行


Example - disable join:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
module tb;
initial begin
#5 $display("t:%0d started", $time);

fork
#20 $display("t:%0d thread1-step1", $time);

begin
#5 $display("t:%0d thread2-step1", $time);
#10 $display("t:%0d thread2-step2", $time);
end
#5 $display("t:%0d thread3-step1", $time);

join_any

$display("t:%0d finished", $time);

disable fork;
end
endmodule

Output:

1
2
3
4
5
# run 10000
# t:5 started
# t:10 thread2-step1
# t:10 thread3-step1
# **t:10 finished**

disable fork可以把前面fork出來的thread停掉


Example - wait fork:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
module tb;
initial begin
#5 $display("t:%0d started", $time);

fork
#20 $display("t:%0d thread1-step1", $time);

begin
#5 $display("t:%0d thread2-step1", $time);
#10 $display("t:%0d thread2-step2", $time);
end
#5 $display("t:%0d thread3-step1", $time);

join_any

fork
#20 $display("t:%0d thread4", $time);
#100 $display("t:%0d thread5", $time);
join_any

$display("t:%0d wait join", $time);
wait fork;

$display("t:%0d finished", $time);
end
endmodule

Output:

1
2
3
4
5
6
7
8
9
10
11
# run 10000
# t:5 started
# t:10 thread2-step1
# t:10 thread3-step1
# t:20 thread2-step2
# t:25 thread1-step1
# t:30 thread4
# t:30 wait join
# t:110 thread5
# **t:110 finished**
# quit -f

wait fork可以用來等待前面的thread都執行完成後,才會往下執行。