systemverilog中进程管理-2-线程的停止

你需要在测试平台中创建线程,也会需要停止线程。
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

猜你喜欢

转载自blog.csdn.net/Michael177/article/details/121066168