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控制进程的执行进度,提供了一个进程影响另一个的机制
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
由上面例子看出,即使是触发先发生,等待触发后发生。但是由于等待触发更晚一些,因此后面的语句将会呗堵塞,不会被执行。执行结果如下:
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
执行结果如下,可见当等待在触发前执行,或者同时出现,等待方是可以察觉触发的
对上面的例子进行修改,将进程2的wait换成@
执行结果,可见使用@操作符,等待方检测不到触发
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后面的语句是可以被执行的。其输出结果如下:
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的顺序,因此是乱序的,其输出结果如下所示:
event regions
简要谈谈sv元素之间的交互和行为,类似verilog仿真事件队列。IEEE1800-2015标准,将sv的时间戳time slot分成17个有序区域。9个区域用于执行sv的语句,8个区域用于执行PLI(programming language interface,编程语言接口)代码。规定这些,是为了design和testbench在预料中交互