1 基本定义
在 SystemVerilog 中,事件是一种用于线程同步的机制。它就像是一个信号旗,不同的线程(如 initial 块、always 块等产生的进程)可以等待这个信号,当信号被触发(就像旗帜被升起)时,等待这个事件的线程就可以继续执行。
事件主要用于协调不同的并发进程之间的操作顺序,确保某些操作在其他操作完成之后才开始。
event是一个静态对象句柄,用于在两个或多个并发活动进程之间进行同步。一个进程将触发event,另一个thread的等待event。event
- 可以分配或其它event变量进行比较
- 可以分配给
null
- 当分配给另一个event时,两个变量都指向同一个同步对象
- 可以分配给
- 可以传递给队列、函数、任务
-
event over; // a new event is created called over event over_again = over; // over_again becomes an alias to over event empty = null; // event variable with no synchronization object
2 事件的声明和触发
-
声明:事件的声明非常简单,使用
触发:可以使用event
关键字。例如:event my_event;
就声明了一个名为my_event
的事件。->
操作符来触发一个事件。例如,在一个进程中:
initial begin#10;-> my_event;
}
3 等待事件
1 使用@
操作符可以实现阻塞式等待一个事件。例如:
initial begin$display("等待事件触发...");@my_event;$display("事件已触发,继续执行。");
}
2 可以使用wait(my_event.triggered)
来实现非阻塞式等待。例如:
initial beginforkbegin$display("非阻塞等待事件触发...");wait(my_event.triggered);$display("事件已触发,非阻塞等待完成。");endbegin#5;-> my_event;}join
}
4 使用示例
module tb;// Created an event variable that processes can use to trigger and waitevent event_a;// Thread1: Triggers the event using "->" operatorinitial begin#20 -> event_a;$display ("[%0t] Thread1:triggered event_a", $time);end// Thread2: Waits for the event using "@" operatorinitial begin$display ("[%0t] Thread2:waiting for trigger", $time);@(event_a);$display ("[%0t] Thread2:received event_a trigger", $time);end// Thread3: Waits for the event using ".triggered"initial begin$display ("[%0t] Thread3:waiting for trigger", $time);wait(event_a.triggered);$display ("[%0t] Thread2:received event_a trigger", $time);end
endmodule
//----------------------------------------------------------------//
// display log //
//----------------------------------------------------------------//ncsim> run
[0] Thread2: Waiting for trigger
[0] Thread3: Waiting for trigger
[20] Thread1: triggered event_a
[20] Thread2: received event_a trigger
[20] Thread3: received event_a trigger
ncsim: *W,RNQUIE: Simulation is complete.
4.1 wait(event_a.triggered)和@(event_a);
event的状态在整个事件步长中持续存在,直到模拟进行。因此,如果event和event的触发器同时发生,则将存在竞争条件,该属性有助于避免这种情况。
module tb;// Created an event variable that processes can use to trigger and waitevent event_a;// Thread1: Triggers the event using "->" operator at 20nsinitial begin#20 -> event_a;$display ("[%0t] Thread1:triggered event_a", $time);end// Thread2: Starts waiting for the event using "@" operator at 20nsinitial begin$display ("[%0t] Thread2:waiting for trigger", $time);#20 @(event_a);$display ("[%0t] Thread2:received event_a trigger", $time);end// Thread3: Starts waiting for the event using ".triggered" at 20nsinitial begin$display ("[%0t] Thread3:waiting for trigger", $time);#20 wait(event_a.triggered);$display ("[%0t] Thread2:received event_a trigger", $time);end
endmodule//----------------------------------------------------------------//
// display log //
//----------------------------------------------------------------//
请注意,由于@和->操作之间的争用条件,Thread2从未收到触发器。
ncsim> run
[0] Thread2: Waiting for trigger
[0] Thread3: Waiting for trigger
[20] Thread1: triggered event_a
[20] Thread3: received event_a trigger
ncsim: *W,RNQUIE: Simulation is complete.
4.2 wait order
等待按给定顺序触发事件,如果任何事件无序执行,则发出错误。
module tb;// Declare three events that can be triggered aeparatelyevent a, b, c;// This block triggers each event one by oneinitial begin#10 -> a;#10 -> b;#10 -> c;end// This block waits until each event is triggered in the given orderinitial beginwait_order (a,b,c)$display ("Events were executed in the correct order");else$display ("Events were NOT executed in the correct order !");end
endmodule//----------------------------------------------------------------//
// display log //
//----------------------------------------------------------------//
Compiler version J-2014.12-SP1-1: Runtime version J-2014.12-SP1-1
Events were executed in the correct order
4.4 Merging Events
当一个event变量分配给另一个event变量时,等待第一个event触发的所有threads都将等待第二个变量触发。
module tb;// Create event variabllesevent event_a, event_b;initial beginfork// Thread1: waits for event_a to be triggeredbeginwait(event_a.triggered);$display ("[%0t] Thread1: Wait for event_a is over", $time);end// Thread2: waits for event_b to be triggeredbeginwait(event_b.triggered);$display ("[%0t] Thread2: Wait for event_b is over", $time);end// Thread3: triggers event_a at 20ns#20 ->event_a;// Thread4: triggers event_b at 20ns#20 ->event_b;// Thread5: Assigns event_b to event_a at 10nsbegin// Comment code below and try again to see Thread2 finish later#10 event_b = event_a;endjoinend
endmodule
//----------------------------------------------------------------//
// display log //
//----------------------------------------------------------------//
ncsim> run
[20] Thread1: Wait for event_a is over
[20] Thread2: Wait for event_b is over
ncsim: *W,RNQUIE: Simulation is complete.
4.4 验证环境中的使用