在测试平台的环境里,大多数语句块被模拟成事务处理器,并运行在各自的线程thread(进程process)里。
- 线程:SV的调度器就像交通警察,总是不停地选择下一个要运行的线程。
- 线程之间通信:解决环境类知道发生器什么时候完成任务,以便及时终止测试平台中还在运行的线程。线程间通信由标准的Verilog事件、事件控制、wait语句、信箱和旗语。
Verilog里面执行方式:顺序执行(begin…end)和并发方式(fork…join)
SV里面新加入两种创建线程方式:fork…join_none和fork…join_any
开始都是平行发送,同时执行
线程间的通信(event,mailbox,semaphore):
1.event事件
testbench.sv
module t;
tb a=new();
event event0;
initial begin
fork
a.wait_for_trigger (event0);
#5 -> event0;
join
end
endmodule
class tb;
task wait_for_trigger (event event0);
$display("[%0t] wait for event0 to be triggered", $time);
wait (event0.triggered);
$display("[%0t] event0 has to be triggered", $time);
endtask
endclass
Makefile文件
TB_FILE_LIST = filelist.list
all: clean comp run
COMP = vcs -full64 -sverilog +v2k -debug_all -fsdb
SIMV = ./simv
comp:
$(COMP) testbench.sv
run:
$(SIMV) -l simv.log
clean:
rm -rf AN.DB DVEfiles csrc *.simv *.simv.daidir ucli.key 64
rm -rf *.log* *.vpd *.fsdb *.vdb novas* *verdi*
rm -rf simv*
编译、仿真结果
[0] wait for event0 to be triggered
[5] event0 has to be triggered
2.mailbox
testbench.sv文件
program tb;
mailbox mbx;
my_gen gen;
my_drv drv;
initial begin
mbx = new();
gen = new(mbx);
drv = new(mbx);
fork
#10;
gen.gen_data();
drv.drv_data();
join_none
end
endprogram
my_gen文件
class my_gen;
mailbox mbx;
function new(mailbox mbx);
this.mbx = mbx;
endfunction
task gen_data();
my_trans put_trans;
put_trans = new();
put_trans.randomize();
put_trans.display();
$display("[%0t] put trans into mailbox", $time);
mbx.put(put_trans);
endtask
endclass
my_drv文件
class my_drv;
mailbox mbx;
function new(mailbox mbx);
this.mbx=mbx;
endfunction
task drv_data();
my_trans get_trans;
get_trans = new();
$display("[%0t] get trans into mailbox", $time);
mbx.get(get_trans);
get_trans.display();
endtask
endclass
my_trans文件
class my_trans;
randc bit [7:0] data;
function display ();
$display ("[%0t] Data = 0x%0h", $time, data);
endfunction
endclass
编译、仿真结果
[0] Data = 0x3f
[0] put trans into mailbox
[0] get trans into mailbox
[0] Data = 0x3f
3.semaphore
module tb;
semaphore flag;
initial begin
flag = new(1);
fork
boy();
girl();
#25 boy();
join_none
end
task get_task(bit [1:0] id);
$display("[%0t] try to get for id[%0d]", $time, id);
flag.get(1);
$display("[%0t] already get for id[%0d]", $time, id);
endtask
task put_task(bit [1:0] id);
$display("[%0t] try to put for id[%0d]", $time, id);
flag.put(1);
$display("[%0t] already put for id[%0d]", $time, id);
endtask
task boy();
get_task(1);
#20 put_task(1);
endtask
task girl();
#5 get_task(2);
#10 put_task(2);
endtask
endmodule
编译,仿真结果
[0] try to get for id[1]
[0] already get for id[1]
[5] try to get for id[2]
[20] try to put for id[1]
[20] already put for id[1]
[20] already get for id[2]
[25] try to get for id[1]
[30] try to put for id[2]
[30] already put for id[2]
[30] already get for id[1]
[50] try to put for id[1]
[50] already put for id[1]