even机制提供进程之间的同步。与System Verilo event相比,UVM event提供了额外的灵活性,如保持事件等待器/event waiters的数量和设置回调。
uvm_event类声明:
virtual class uvm_event_base extends uvm_object
class uvm_event#(type T=uvm_object) extends uvm_event_base;
对于UVM 1.2,uvm_event_base类是System Verilog event构造上的抽象包装类,uvm_event类是uvm_event_base类的扩展。
对于UVM1.1d,抽象的uvm_event_base类不存在。uvm_event类直接派生自uvm_object类。
event通过从一个进程触发事件并等待另一个进程中的事件触发来提供进程之间的同步。UVM事件也可以在触发时传递数据,这使其与SV event不同。
例如,有两个进程A和B。process_A任务用于触发事件e1,process_B任务用于等待事件。
process_A任务有10ns的延迟,确保在等待事件触发后触发事件e1。使用wait_trigger方法调用等待事件触发,一旦触发e1事件,该方法调用将被解除阻止。
`include "uvm_macros.svh"
import uvm_pkg::*;
module event_example();
uvm_event e1;
task process_A();
#10;
$display("@%0t: Before triggering event e1", $time);
e1.trigger;
$display("@%0t: After triggering event e1", $time);
endtask
task process_B();
$display("@%0t: waiting for the event e1", $time);
e1.wait_trigger;
$display("@%0t: event e1 is triggered", $time);
endtask
initial begin
e1 = new();
fork
process_A();
process_B();
join
end
endmodule
Output:
@0: waiting for the event e1
@10: Before triggering event e1
@10: After triggering event e1
@10: event e1 is triggered
process_B任务有10ns的延迟,确保在等待事件触发之前触发事件e1。由于之前触发了e1事件,因此不会解除对事件触发的等待。因此,等待触发器后的语句将不会执行。
`include "uvm_macros.svh"
import uvm_pkg::*;
module event_example();
uvm_event e1;
task process_A();
$display("@%0t: Before triggering event e1", $time);
e1.trigger;
$display("@%0t: After triggering event e1", $time);
endtask
task process_B();
#10;
$display("@%0t: waiting for the event e1", $time);
e1.wait_trigger;
$display("@%0t: event e1 is triggered", $time);
endtask
initial begin
e1 = new();
fork
process_A();
process_B();
join
end
endmodule
Output:
@0: Before triggering event e1
@0: After triggering event e1
@10: waiting for the event e1
process_A和process_B没有延迟,以确保触发事件并等待事件触发同时发生。由于这两个进程是同时触发的,因此wait_trigger方法不会检测到事件触发。uvm_event提供了一个wait_ptrigger方法来解决这个race-around问题.
`include "uvm_macros.svh"
import uvm_pkg::*;
module event_example();
uvm_event e1;
task process_A();
$display("@%0t: Before triggering event e1", $time);
e1.trigger;
$display("@%0t: After triggering event e1", $time);
endtask
task process_B();
$display("@%0t: waiting for the event e1", $time);
e1.wait_trigger;
$display("@%0t: event e1 is triggered", $time);
endtask
initial begin
e1 = new();
fork
process_A();
process_B();
join
end
endmodule
Output:
@0: Before triggering event e1
@0: After triggering event e1
@0: waiting for the event e1
例如,有两个进程A和B。process_A任务用于触发事件e1,process_B任务用于使用wait_ptrigger等待事件。
process_A任务有10ns的延迟,确保在等待事件触发后触发事件e1。一旦e1事件被触发,通过wait_ptrigger()方法触发事件的等待将被解除阻止。
`include "uvm_macros.svh"
import uvm_pkg::*;
module event_example();
uvm_event e1;
task process_A();
#10;
$display("@%0t: Before triggering event e1", $time);
e1.trigger;
$display("@%0t: After triggering event e1", $time);
endtask
task process_B();
$display("@%0t: waiting for the event e1", $time);
e1.wait_ptrigger;
$display("@%0t: event e1 is triggered", $time);
endtask
initial begin
e1 = new();
fork
process_A();
process_B();
join
end
endmodule
Output:
@0: waiting for the event e1
@10: Before triggering event e1
@10: After triggering event e1
@10: event e1 is triggered
process_B任务有10ns的延迟,确保在等待事件触发之前触发事件e1。由于之前触发了e1事件,因此通过wait()构造触发事件的等待不会被解除阻止。因此,等待触发器(使用@operator)后的语句将不会执行。
`include "uvm_macros.svh"
import uvm_pkg::*;
module event_example();
uvm_event e1;
task process_A();
$display("@%0t: Before triggering event e1", $time);
e1.trigger;
$display("@%0t: After triggering event e1", $time);
endtask
task process_B();
#10;
$display("@%0t: waiting for the event e1", $time);
e1.wait_ptrigger;
$display("@%0t: event e1 is triggered", $time);
endtask
initial begin
e1 = new();
fork
process_A();
process_B();
join
end
endmodule
Output:
@0: Before triggering event e1
@0: After triggering event e1
@10: waiting for the event e1
`include "uvm_macros.svh"
import uvm_pkg::*;
module event_example();
uvm_event e1;
task process_A();
$display("@%0t: Before triggering event e1", $time);
e1.trigger;
$display("@%0t: After triggering event e1", $time);
endtask
task process_B();
$display("@%0t: waiting for the event e1", $time);
e1.wait_ptrigger;
$display("@%0t: event e1 is triggered", $time);
endtask
initial begin
e1 = new();
fork
process_A();
process_B();
join
end
endmodule
Output:
@0: Before triggering event e1
@0: After triggering event e1
@0: waiting for the event e1
@0: event e1 is triggered
例如,有两个进程A和B。process_A任务用于触发事件e1,将事务对象作为数据发送,process_B任务用于等待事件和检索数据。
process_A任务具有10ns的延迟,确保在等待事件触发后触发事件e1。使用wait_on方法调用等待事件触发,一旦触发e1事件,就会取消阻止该方法调用。get_trigger_data用于检索上次调用触发器方法提供的数据。
`include "uvm_macros.svh"
import uvm_pkg::*;
class transaction extends uvm_object;
rand bit [7:0] addr;
rand bit [7:0] data;
function new(string name = "transaction");
super.new(name);
endfunction
`uvm_object_utils_begin(transaction)
`uvm_field_int(addr, UVM_PRINT);
`uvm_field_int(data, UVM_PRINT);
`uvm_object_utils_end
endclass
module event_example();
uvm_event e1;
task process_A();
transaction tr_A = new();
#10;
$display("@%0t: Before triggering event e1", $time);
assert(tr_A.randomize);
tr_A.print();
e1.trigger(tr_A);
$display("@%0t: After triggering event e1", $time);
endtask
task process_B();
uvm_object event_data;
transaction tr_B;
$display("@%0t: waiting for the event e1", $time);
e1.wait_on();
event_data = e1.get_trigger_data();
$cast(tr_B, event_data);
$display("@%0t: event e1 is triggered and data received = \n%s", $time, tr_B.sprint());
endtask
initial begin
e1 = new();
fork
process_A();
process_B();
join
end
endmodule
output:
@0: waiting for the event e1
@10: Before triggering event e1
-------------------------------------
Name Type Size Value
-------------------------------------
transaction transaction - @336
addr integral 8 'ha3
data integral 8 'h8f
-------------------------------------
@10: After triggering event e1
@10: event e1 is triggered and data received =
-------------------------------------
Name Type Size Value
-------------------------------------
transaction transaction - @336
addr integral 8 'ha3
data integral 8 'h8f
-------------------------------------
相似的,也可以用wait_on和get_ptrigger_data。
process_A任务具有10ns的延迟,确保在等待事件触发后触发事件e1。使用wait_trigger_data方法调用等待事件被触发,一旦e1事件被触发,该方法调用将被取消阻止。
wait_trigger_data = wait_trigger + get_trigger_data.
// wait_trigger_data definition
virtual task wait_trigger_data (output T data);
wait_trigger();
data = get_trigger_data();
endtask
Example:
`include "uvm_macros.svh"
import uvm_pkg::*;
class transaction extends uvm_object;
rand bit [7:0] addr;
rand bit [7:0] data;
function new(string name = "transaction");
super.new(name);
endfunction
`uvm_object_utils_begin(transaction)
`uvm_field_int(addr, UVM_PRINT);
`uvm_field_int(data, UVM_PRINT);
`uvm_object_utils_end
endclass
module event_example();
uvm_event e1;
task process_A();
transaction tr_A = new();
#10;
$display("@%0t: Before triggering event e1", $time);
assert(tr_A.randomize);
tr_A.print();
e1.trigger(tr_A);
$display("@%0t: After triggering event e1", $time);
endtask
task process_B();
uvm_object event_data;
transaction tr_B;
$display("@%0t: waiting for the event e1", $time);
e1.wait_trigger_data(event_data);
$cast(tr_B, event_data);
$display("@%0t: event e1 is triggered and data received = \n%s", $time, tr_B.sprint());
endtask
initial begin
e1 = new();
fork
process_A();
process_B();
join
end
endmodule
output:
@0: waiting for the event e1
@10: Before triggering event e1
-------------------------------------
Name Type Size Value
-------------------------------------
transaction transaction - @1798
addr integral 8 'h2f
data integral 8 'hb3
-------------------------------------
@10: After triggering event e1
@10: event e1 is triggered and data received =
-------------------------------------
Name Type Size Value
-------------------------------------
transaction transaction - @1798
addr integral 8 'h2f
data integral 8 'hb3
-------------------------------------
类似的,可以用wait_ptrigger_data。