你需要在测试平台中创建线程,也会需要停止线程。
verilog中的disable语句可以用于停止systemverilog中的线程。
SystemVerilog提供了两大类process的控制方式,分别为wait和disable。
disable语句常用的多种方式包括:disable block_name、disable task_name和disable fork等,调用disable语句将会终止指定的进程。
1.利用disable block_name停止一个线程
initial begin
begin : block_0
$display("block_0 start");
disable block_0;
$display("block_0 finish");
end
$display("initial finish");
end
//打印结果
block_0 start
initial finish
2.利用disable task_name停止一个线程
如果你在某个任务内部禁止该任务,这就像是任务的返回语句,但是这也会停止所有由该任务启动的线程。如果该任务已经被多个线程调用,禁止其中的一个将导致他们全部被禁止。
task wait_for_time_out(int id);
if(id == 0)
fork
begin
#2;
$display("@%0t:disable wait_for_time_out", $time);
disable wait_for_time_out;
end
join_none
fork:just_a_little
begin
$display(@%0t:%m: %0d entering thread",$time,id);
#TIME_OUT;
$display("@%0t:%m: %0d done",$time, id);
end
join
endtask
initial begin
wait_for_time_out(0); //衍生线程0
wait_for_time_out(1); //衍生线程1
wait_for_time_out(2); //衍生线程2
end
任务wait_for_time_out被调用了三次,从而衍生了三个线程。线程0在#2延时以后禁止了该任务。只要运行这段代码,就可以看到三个线程都启动了。但是因为线程0里的disable语句,这些线程最终都没有完成。
3.停止多个线程:disable fork
systemveilog引入了disable fork语句使能够停止从当前线程中衍生出来的所有子线程。
initial begin
check_trans(tr0); //线程0
fork //线程1
begin
check_trans(tr1); //线程2
fork
check_trans(tr2); //线程3
join
#(TIME_OUT/2) disable fork; //停止线程1-4,单独保留线程0
end
join
end
wait中包含了三小类:wait、wait_order、wait fork。
4.wait线程
其中,wait相对简单,不在介绍。
5.wait_order线程
wait_order会阻塞等待多个事件的触发,并且要求这几个事件间发生的顺序和设置的一致。
initial begin
event event_1, event_2, event_3;
fork
begin
#50 -> event_1;
end
begin
#30 -> event_2;
end
begin
#100 -> event_3;
end
join_any
wait_order(event_2, event_1, event_3);
$display("all evnet finish, current time is %0t", $realtime);
end
//运行结果
all event finish, current time is 10000
wait_order需要阻塞到3个事件依次按照event_2、event_1、event_3的顺序进行触发后才能往下执行。这就是wait_order的用法。
6.wait_fork线程
1)wait fork会引起调用进程阻塞,直到它的所有子进程结束;
2)wait fork的目的是用来确保所有子进程执行结束;
3)wait fork作用父进程下的子进程,而不包括子进程下的子进程。
7.进程内建类
SystemVerilog中内建了一种class,可以对进程进行访问和控制,此种class就是process,我们先来看下process类的原型:
进程是一个内置类,允许一个进程在启动后访问和控制另一个进程。用户可以声明类型为process的变量,并安全地通过任务传递它们,或将它们合并到其他对象中。流程类的原型如下:
class process;
typedef enum { FINISHED, RUNNING, WAITING, SUSPENDED, KILLED } state;
static function process self();
function state status();
function void kill();
task await();
function void suspend();
function void resume();
function void srandom( int seed );
function string get_randstate();
function void set_randstate( string state );
endclass
下面我们详细介绍process类中的几个任务和函数:
self()-获取当前进程的句柄,process类不能主动的通过new来创建。只能通过initial begin…end、final begin…end、4个always块、3个fork块和动态进程来创建。
status()-获取当前进程的状态。finish-进程结束了、running-该进程正在进行、waiting-该进程等待阻塞条件、suspended-该进程停止了,等待resume,当前状态只能通过resume来解除、killed-该进程被强制中止了。
kill()-中止该进程以及该进程的子进程。
await()-等待其他进程结束,不能在该进程中调用该方法。只能是别的进程调用本进程await()来阻塞本进程。
suspend()-挂起该进程。
resume()-恢复该进程。
srandom(int seed)-设置进程的随机种子。
module top_tb;
process process_1;
process process_2;
initial begin
process_1 = process::self();
#100;
$display("process_1 finish, current time is %0t", $realtime());
end
initial begin
process_2 = process::self();
#1000;
$display("process_2 finish, current time is %0t", $realtime());
end
intial begin
#100;
$display("process_1 status is %0s, current time is %0t", process_1.status, $realtime());
$display("process_2 status is %0s, current time is %0t", process_2.status, $realtime());
#100;
process_2.kill();
$display("process_2 status is %0s, current time is %0t", process_2.status, $realtime());
end
endmodule
//运行结果
process_1 finish, current time is 100000
process_1 status is FINISHED, current time is 100000
process_2 status is WAITING, current time is 100000
process_2 status is KILLED, current time is 200000