SystemVerilog - Mailbox

2023-07-06
SystemVerilog

mailbox可以用來讓不同的process溝通。類似真實的一個郵箱,可以把信放到郵箱裡,然後可以從郵箱取出這些信件。
mailbox可以宣告成有限制空間或無限制空間,他也跟queue類似,只是mailbox只能是FIFO的順序取資料,並且mailbox有用semaphore來control push和pop資料不會遇到race condition。

下面的範例是mailbox只能放一筆資料的case,可以看到第一個initial block要put()資料進去mailbox,在資料還沒被get()拿走之前,是沒辦法塞進去的。

Example - bound=1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
module tb();
mailbox mbx = new(1);

initial begin
for( int i = 0; i < 5; i++) begin
#3 mbx.put(i);
$display("t:%0d put %0d", $time(), i);
end
end

initial begin
forever begin
automatic int i;
#5 mbx.get(i);
$display("t:%0d get %0d", $time(), i);
end
end
endmodule

Output

# run 10000
# t:3 put 0
# t:5 get 0
# t:6 put 1
# t:10 get 1
# t:10 put 2
# t:15 get 2
# t:15 put 3
# t:20 get 3
# t:20 put 4
# t:25 get 4
#  quit -f

下面的範例是mailbox的bound是3的例子,一開始還沒到bound上限之前,第一個initial block都可以塞資料進去,但到了bound上限之後就要等第二個initial block把資料取走之後才能再塞資料。

Example - bound=3:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
module tb();
mailbox mbx = new(3);

initial begin
for( int i = 0; i < 5; i++) begin
#3 mbx.put(i);
$display("t:%0d put %0d", $time(), i);
end
end

initial begin
forever begin
automatic int i;
#5 mbx.get(i);
$display("t:%0d get %0d", $time(), i);
end
end
endmodule

Output

# run 10000
# t:3 put 0
# t:5 get 0
# t:6 put 1
# t:9 put 2
# t:10 get 1
# t:12 put 3
# t:15 get 2
# t:15 put 4
# t:20 get 3
# t:25 get 4
#  quit -f

以上兩個範例是比較簡單的mailbox用法,下面的例子是不同object之間用mailbox來溝通的範例,sender class的send task會put訊息到mailbox裡面,receiver class的receive task會從mailbox get訊息。tb這個module負責產生出mailbox/sender/receiver這些class的object,然後在initial block裡面把task執行起來。

Example:

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
27
28
29
30
31
32
33
34
35
36
class sender;
mailbox mbx;

task send();
for( int i = 0; i < 5; i++) begin
#3 mbx.put(i);
$display("t:%0d sender put %0d", $time(), i);
end
endtask
endclass

class receiver;
mailbox mbx;

task receive();
forever begin
automatic int i;
#5 mbx.get(i);
$display("t:%0d receiver get %0d", $time(), i);
end
endtask
endclass

module tb();
mailbox mbx = new();
sender sender = new();
receiver receiver = new();

initial begin
sender.mbx = mbx;
receiver.mbx = mbx;
sender.send();
receiver.receive();
end
endmodule

Output

# run 10000
# t:3 sender put 0
# t:6 sender put 1
# t:9 sender put 2
# t:12 sender put 3
# t:15 sender put 4
# t:20 receiver get 0
# t:25 receiver get 1
# t:30 receiver get 2
# t:35 receiver get 3
# t:40 receiver get 4
#  quit -f