uvm_event
uvm_event类似于SV中的event,只不过uvm_event的功能更强大,不仅能够实现不同组件进程之间的同步,还能传递数据。
uvm_event的常用方法
方法 | 描述 |
---|---|
trigger | 触发事件,复位所有等待进程。类似于SV中的-> |
wait_trigger | 等待触发事件,当等待触发和触发事件同时发生会产生竞争。**如果在触发事件前等待则该方法将会返回,若在事件触发后等待该方法则不会返回直到下一次触发事件发生。**类似于SV中的@ev |
wait_ptrigger | 等待触发事件,与wait_trigger不同,当等待触发和触发事件同时发生时不会产生竞争,即在相同的时间片内等待触发发生在触发事件后,该方法会立即返回,而不是等到下一次触发事件发生。类似于SV中的wait(ev.triggered()) |
get_trigger_data | 获取触发数据 |
wait_trigger_data | 等待事件触发并返回数据。wait_trigger+get_trigger_data |
wait_ptrigger_data | wait_ptrigger+get_trigger_data |
get_num_waiters | 获取num_waiters值(等待进程的个数) |
uvm_event与event的区别
- (1)event被->触发后,会触发使用@或wait来等待该事件的对象;uvm_event通过trigger来触发,会触发使用wait_trigger或wait_ptrigger等到事件的对象。如果要再次等待事件触发,event只需要再次使用->来触发,而uvm_event需要先通过reset方法重置初始状态,再使用trigger来触发。
- (2)event无法携带信息,而uvm_event可以通过
trigger(uvm_object data=null)
的可选参数将所要伴随触发的信息放入该触发事件中,而等待该事件的对象可以通过方法wait_trigger_data (output uvm_object data)
来获取事件触发时写入的数据。可以注意到,触发事件和等待事件触发传递的实际上是一个uvm_object类型的的句柄,换句话说传递的数据必须是uvm_object类型的对象句柄。当然也可以是uvm_object类型的子类,不过当传递的是uvm_object类型的子类时,在wait_trigger_data (output uvm_object data)
的参数还得是uvm_object类型,这时在等待触发一端可以通过$cast
对数据类型进行转换。
- (3)event无法直接获取等待它的进程数据,而uvm_event可以通过
get_num_waiters
来获取等待它的进程数目。
- (4)event不能使用callback机制,uvm_event可以使用。
注:实际上,uvm_event与event最大的不同就在于携带数据,这也是uvm_event的最大优势。
uvm_pool
uvm_pool常用的方法
方法 | 描述 |
---|---|
get_global_pool | 返回或创建全局单例实例 |
T get (KEY key) | 根据key返回一个T实例,若key不存在则创建一个T实例并返回 |
T get_global (KEY key) | 相当于get_global_pool+get |
uvm_event_pool
- uvm_event_pool是一个参数为uvm_event类型的uvm_object_string_pool,而uvm_object_string_pool又是继承于uvm_pool。
uvm_event、uvm_event_pool的实际应用
class my_component extends uvm_comopnent;
...
// 先声明一个uvm_event
uvm_event my_event ;
`uvm_component_utils(my_component)
function void build_phase(uvm_phase phase);
super.build_phase(phase);
// 使用uvm_event_pool的get_global方法将my_event注册到uvm_event_pool中
// 并返回该实例
my_event = uvm_event_pool::get_global("my_event");
endfunction
task main_phase(uvm_phase phase);
...
set_trigger();
...
endtask
task set_trigger();
my_transaction tr;
// 触发事件并传入uvm_object的子类
my_event.trigger(tr);
endtask
endclass
class get_component extends uvm_comopnent;
...
// 声明同样的uvm_event
uvm_event get_my_event ;
`uvm_component_utils(get_component)
function void build_phase(uvm_phase phase);
super.build_phase(phase);
// 获取之前在uvm_event_pool中创建的uvm_event
// 只有首次调用get_gobal并传入一个新的uvm_event才会创建,再次调用会获取
get_my_event = uvm_event_pool::get_global("my_event");
endfunction
task main_phase(uvm_phase phase);
...
set_trigger();
...
endtask
task set_trigger();
...
uvm_object tmp;
my_transaction tr;
// 等待触发,并获取触发时传入的数据
get_my_event.wait_trigger(tmp);
// 使用$cast进行类型转换
void'($cast(tr,tmp));
...
endtask
endclass