event

event 类

event时systemverilog内建的一个类,我们可以用event声明一个句柄,该句柄称为named event。event是一个静态对象,用于进程之间的同步。event操作一般分为两个阶段的操作组成,一个进程用来触发event,另一个进程用来等待event。
正是由于句柄的存在,它不同于如时钟上升沿事件,named event需要我们显示指定何时触发和等待。提供如下操作符处理event的触发和等待:

  • -> 触发named event,触发事件之后会解锁所有等待该事件的进程
  • ->> 触发非阻塞事件,使用该操作符语句执行不会阻塞即等待,会创建一个非阻塞赋值更新事件
  • @ 该操作符会阻塞进程,知道给定的event触发。若要实现不阻塞进程的触发,就先需要执行@statement,然后触发进程在执行->
  • wait 如果同时发生事件触发和等待,使用@操作符可能会错过检测事件的触发,而使用wait则可以检测事件的触发。
  • wait_order 这个方法会阻塞进程直到所有指定的事件在给定的顺序(从左到右)触发,如果顺序不对,同样不会解锁进程。
  • 当一个event变量赋值给另一个,两个event就会合并,执行->,任一事件变量都会影响进程执行。

例子

module event_ex;

    event ev_1;         //declaring event ev_1

    initial begin
        fork
            //process-1,triggers the event
            begin
                #40;
                $display($time, "\t Triggering The event");
                ->ev_1;
            end

            //process-2,wait for the event to trigger
            begin
                $display($time, "\t Waiting for the event to trigger");
                @(ev_1.triggered);
                $display($time, "\t Event triggered");
            end
        join
    end

endmodule

示例中,fork-join有两个进程,第一个begin-end块经过40个时间单位触发事件ev_1,第二个begin-end块等待ev_1触发,然后打印输出.执行结果,可见,实质上是通过event控制进程的执行进度,提供了一个进程影响另一个的机制

system verilog中的队列能重复赋值吗 system verilog event_学习

module event_ex;

    event ev_1;                 //delaring event ev_1

    initial begin
        fork
            //process-1,triggers the event
            begin
                #40;
                $display($time, "\t Triggering The event");
                ->ev_1;
            end
            //process-2,wait for the event to trigger
            begin
                $display($time, "\t Waiting for the event to trigger");
                #60;
                @(ev_1.triggered);
                $display($time, "\t Event triggered");
            end
        join
    end

    initial begin
        #100;
        $display($time, "\t Ending the simulation");
        $finish;
    end

endmodule

由上面例子看出,即使是触发先发生,等待触发后发生。但是由于等待触发更晚一些,因此后面的语句将会呗堵塞,不会被执行。执行结果如下:

system verilog中的队列能重复赋值吗 system verilog event_学习_02

module events_ex;
  event ev_1; //declaring event ev_1

  initial begin
    fork
      //process-1, triggers the event
      begin
         $display($time,"\tTriggering The Event");
        ->ev_1;
      end
   
      //process-2, wait for the event to trigger
      begin
        $display($time,"\tWaiting for the Event to trigger");
        wait(ev_1.triggered);
        $display($time,"\tEvent triggered");
      end
    join
  end
endmodule

执行结果如下,可见当等待在触发前执行,或者同时出现,等待方是可以察觉触发的

system verilog中的队列能重复赋值吗 system verilog event_句柄_03


对上面的例子进行修改,将进程2的wait换成@

system verilog中的队列能重复赋值吗 system verilog event_学习_04


执行结果,可见使用@操作符,等待方检测不到触发

system verilog中的队列能重复赋值吗 system verilog event_句柄_05

module events_ex;
  event ev_1; //declaring event ev_1
  event ev_2; //declaring event ev_2
  event ev_3; //declaring event ev_3
  
  initial begin
    fork
      //process-1, triggers the event ev_1
      begin
        #6;
        $display($time,"\tTriggering The Event ev_1");
        ->ev_1;
      end
      //process-2, triggers the event ev_2
      begin
        #2;
        $display($time,"\tTriggering The Event ev_2");
        ->ev_2;
      end
      //process-3, triggers the event ev_3
      begin
        #8;
        $display($time,"\tTriggering The Event ev_3");
        ->ev_3;
      end
      //process-4, wait for the events to trigger in order of ev_2,ev_1 and ev_3
      begin
        $display($time,"\tWaiting for the Event's to trigger");
        wait_order(ev_2,ev_1,ev_3)
          $display($time,"\tEvent's triggered Inorder");
        else
          $display($time,"\tEvent's triggered Out-Of-Order");
      end
    join
  end
endmodule

由上面例子可以看出,是先触发事件2,再触发事件1,最后触发事件3.再wait_order是按照顺序触发的,因此wait_order后面的语句是可以被执行的。其输出结果如下:

system verilog中的队列能重复赋值吗 system verilog event_操作符_06

module event_ex;

    event ev_1;             //declaring event ev_1
    event ev_2;             //declaring event ev_2
    event ev_3;             //declaring event ev_3

    initial begin
        fork
            //process-1,triggers the event ev_1
            begin
                #6;
                $display($time, "\t Triggering the event ev_1");
                ->ev_1;
            end

            //process-2,triggers the event ev_2
            begin
                #2;
                $display($time, "\t Triggering the event ev_2");
                ->ev_2;
            end

            //process-3,triggers the event ev_3
            begin
                #1;
                $display($time, "\t Triggering the event ev_3");
                ->ev_3;
            end

            //process-4.wait for the events to trigger in order of ev_2,ev_2,ev_3
            begin
                $display($time, "\t Waiting for the event to trigger");
                wait_order(ev_2,ev_1,ev_3);
                    $display($time, "\t Event's triggered Inorder");
                else
                    $display($time, "\t Event's triggered out-of-order");
            end
        join
    end

endmodule

上面例子中的触发顺序是先触发ev_3随着是ev_2,ev_1。进程4的等待顺序却是等待ev_2,ev_1,ev_3的顺序,因此是乱序的,其输出结果如下所示:

system verilog中的队列能重复赋值吗 system verilog event_赋值_07

event regions

简要谈谈sv元素之间的交互和行为,类似verilog仿真事件队列。IEEE1800-2015标准,将sv的时间戳time slot分成17个有序区域。9个区域用于执行sv的语句,8个区域用于执行PLI(programming language interface,编程语言接口)代码。规定这些,是为了design和testbench在预料中交互

system verilog中的队列能重复赋值吗 system verilog event_句柄_08