【UVM源码学习】uvm_event

本文详细介绍了UVM框架中的uvm_event机制,包括uvm_event_base和uvm_event的使用方法,以及如何通过uvm_event_callback实现事件回调功能。


  uvm_event_callback.svh 实现了uvm_event_callback,uvm_event_callback直接从uvm_object扩展而来,是个参数化的类,该类用于uvm_event的callback。该类中,实现了两个function:pre_triggerpost_trigger,使用该类时需重载这两个函数。pre_trigger中默认返回0,如果如要在触发时间之前做判断,可以重载pre_trigger函数使其返回1,这样就不再触发event且不执行post_trigger。post_traigger在触发uvm_event之后自动执行,默认返回0,用户可重载该callback函数实现自定义功能。


  uvm_event.svh 中实现了uvm_event机制,实现了两个类:uvm_event_baseuvm_event

  uvm_event_base直接扩展自uvm_object,相当于在SystemVerilog event基础上包了层uvm的外衣。除了sv event支持的属性外,uvm_event_base还能保存waiter的数目且支持callback。uvm_event_base中实现的主要方法有:

序号方法描述
1wait_on等待事件on。事件触发函数trigger中会将on置一,若事件已经被触发直接返回,返回前可定义#0以避免进程竞争;若事件未触发,等待触发且num_waiters计数加一
2wait_off等待事件off。事件reset函数中会将on置零,若事件触发后已被reset则直接返回,返回前可定义#0以避免进程竞争;若事件触发后尚未reset,等待事件reset,且num_waiters计数加一
3wait_trigger等待事件触发。@m_event且num_waiters++。该函数不会判断此前事件是否已被触发,若事件早前已被触发,则等待下次触发
4wait_ptrigger等待事件触发,若此前事件已触发,则直接返回
5get_trigger_time返回事件的触发事件,在事件触发函数trigger中会记录该时间
6is_on判断事件是否on,事件触发之前on=0,事件触发后on=1,reset中on=0,即判断事件是否处于trigger后reset前
7is_off判断事件是否off,即判断事件是否处于reset后trigger前
8resetreset事件,num_waiters置零,trigger_time置零,on置零。用户还可以指定输入参数bit wakeup=1来触发事件释放所有阻塞住的进程,默认不触发
9cancelnum_waiters减一,多用于某进程被kill/disable之后
10get_num_waiters获取num_waiters值
11get_type_name返回type_name
12do_print钩子函数,把on/num_waiters/trigger_time变量注册进printer.print_field_int,在调用print进行打印的时候能够打印出来
13do_copy钩子函数,类型转换


  uvm_event派生自uvm_event_base,其中实现的方法有:

序号方法描述
1wait_trigger_data调用wait_trigger等待事件触发,调用get_trigger_data获取触发数据
2wait_ptrigger_data跟wait_trigger的唯一区别是调用了wait_ptigger而非wait_trigger
3trigger触发事件。用户可传递data进来,供pre_trigger和post_triger取用。pre_trigger和post_trigger在下文uvm_event_callback类中介绍。触发事件之后num_waiters清零,on=1,记录trigger_data及触发时间。
4get_trigger_data获取触发时间
5get_type_name返回type_name
6add_callback添加注册uvm_event_callback,若已注册则报warning并退出。用户可指定该callback是加到callback队列的队首或队尾
7delete_callback从uvm_event_callback队列中删除当前callback
8do_print在uvm_event_base do_print基础上添加了trigger_data
9do_copy在uvm_event_base do_copy基础上添加了trigger_data
<think>我们正在讨论UVM中的`uvm_analysis_imp_decl`宏。根据提供的引用,这个宏主要用于解决当同一个组件需要实现多个analysis imp端口时,每个端口都需要一个独立的write函数的问题。下面我将详细解释它的原理和使用方法。 ### 问题背景 在UVM中,`uvm_analysis_port`可以连接到多个`uvm_analysis_imp`,但是每个`uvm_analysis_imp`在组件内部都需要一个write方法。如果组件需要多个analysis imp端口(例如,接收来自多个来的数据),那么这些端口都会调用同一个write方法,这会导致冲突。 ### `uvm_analysis_imp_decl`宏的作用 这个宏通过为每个imp端口生成一个带有特定后缀的类来解决上述问题。这样,每个imp端口都有自己独立的write方法(方法名由write和指定的后缀组成)。 ### 使用方法 1. **声明后缀**:使用`uvm_analysis_imp_decl`宏声明一个或多个后缀。每个后缀将生成一个新的imp类。 2. **定义imp端口**:在组件中,使用生成的带有后缀的imp类来定义多个imp端口。 3. **实现write方法**:在组件中,为每个imp端口实现对应的write方法,方法名为`write_后缀`。 ### 示例代 假设我们有一个组件需要两个analysis imp端口,分别用于接收监视器(monitor)和模型(model)的数据。 ```systemverilog // 声明两个后缀:_monitor和_model `uvm_analysis_imp_decl(_monitor) `uvm_analysis_imp_decl(_model) class my_component extends uvm_component; // 定义两个imp端口 uvm_analysis_imp_monitor #(my_transaction, my_component) mon_imp; uvm_analysis_imp_model #(my_transaction, my_component) mdl_imp; function new(string name, uvm_component parent); super.new(name, parent); mon_imp = new("mon_imp", this); mdl_imp = new("mdl_imp", this); endfunction // 实现两个不同的write方法 function void write_monitor(my_transaction tr); // 处理来自monitor的数据 endfunction function void write_model(my_transaction tr); // 处理来自model的数据 endfunction endclass ``` ### 原理解析 宏`uvm_analysis_imp_decl`展开后会生成一个新的类,该类继承自`uvm_analysis_imp`,并重写了write方法,使其调用组件中对应后缀的write方法。 例如,`uvm_analysis_imp_decl(_monitor)`会生成类似如下的类: ```systemverilog class uvm_analysis_imp_monitor #(type T=int, type IMP=uvm_component) extends uvm_analysis_imp; `uvm_analysis_imp_utils(T) function void write(input T t); IMP imp; if (!$cast(imp, m_imp)) `uvm_fatal(...) imp.write_monitor(t); endfunction endclass ``` 这样,当端口`mon_imp`的write被调用时,实际上会调用组件中的`write_monitor`方法。 ### 注意事项 1. 每个后缀必须是唯一的,通常使用下划线开头。 2. 组件中实现的write方法必须与后缀完全匹配(包括大小写)。 3. 这种方法只适用于analysis imp端口,因为只有analysis端口支持一对多的连接。 ### 应用场景 - 当组件需要接收来自多个分析端口的数据,并且需要区分数据来时。 - 在scoreboard中可能需要接收多个agent的监测数据。 ### 总结 使用`uvm_analysis_imp_decl`宏可以优雅地解决同一个组件中多个analysis imp端口需要独立write方法的问题。通过为每个imp端口定义不同的后缀,并在组件中实现对应的write方法,可以清晰地处理不同来的数据[^3][^4]。 §§相关问题§§ 1. `uvm_analysis_imp`端口与普通`uvm_analysis_port`端口有何区别? 2. 如何在UVM中实现多个analysis_port的连接? 3. 除了`uvm_analysis_imp_decl`,还有哪些方法可以处理多个imp端口? </think>### UVM中`uvm_analysis_imp_decl`宏详解 `uvm_analysis_imp_decl`是UVM中用于解决TLM通信中端口冲突的关键宏,特别适用于需要处理多路分析端口(analysis port)的场景。 #### 核心问题与解决方案 1. **问题本质** 当组件需要接收多个analysis port数据时: - 标准`uvm_analysis_imp`端口强制使用`write()`方法名 - 多个端口会冲突调用同一个`write()`方法[^3][^4] 2. **宏的作用** ```systemverilog `uvm_analysis_imp_decl(SUFFIX) ``` - 创建带后缀的新端口类:`uvm_analysis_imp_SUFFIX` - 自动生成对应的`write_SUFFIX()`方法名[^2][^3] #### 工作原理解析 通过宏声明创建新的端口类结构: ```systemverilog // 宏展开后的伪代 class uvm_analysis_imp_SUFFIX #(type T=uvm_object) extends uvm_analysis_imp; virtual function void write(input T t); m_imp.write_SUFFIX(t); // 自动重定向到后缀方法 endfunction endclass ``` 当端口被调用时,自动路由到组件中的`write_SUFFIX()`方法[^1][^4]。 #### 完整使用示例 ```systemverilog // 1. 声明两个不同后缀 `uvm_analysis_imp_decl(_mon) `uvm_analysis_imp_decl(_ref) class my_scoreboard extends uvm_component; // 2. 实例化带后缀的端口 uvm_analysis_imp_mon #(trans_type, this_type) mon_imp; uvm_analysis_imp_ref #(trans_type, this_type) ref_imp; function void build_phase(uvm_phase phase); mon_imp = new("mon_imp", this); ref_imp = new("ref_imp", this); endfunction // 3. 实现后缀方法 function void write_mon(trans_type t); // 处理来自monitor的数据 endfunction function void write_ref(trans_type t); // 处理来自reference model的数据 endfunction endclass // 连接示例 env.monitor.ap.connect(scoreboard.mon_imp); env.ref_model.ap.connect(scoreboard.ref_imp); ``` #### 典型应用场景 1. **Scoreboard设计** - 同时连接DUT监测数据和参考模型数据 - 不同后缀区分数据:`_dut_mon`和`_ref_model` 2. **多协议处理** ```systemverilog `uvm_analysis_imp_decl(_eth) `uvm_analysis_imp_decl(_pcie) ``` 在同一个组件中处理以太网和PCIe协议事务 3. **多通道采集** 在图像处理验证中区分不同颜色通道: ```systemverilog `uvm_analysis_imp_decl(_red) `uvm_analysis_imp_decl(_green) `uvm_analysis_imp_decl(_blue) ``` #### 注意事项 1. **命名规范** - 后缀建议使用`_<功能>`格式(如`_packet`) - 避免使用数字后缀(`_imp1`不易维护) 2. **连接限制** - 仅适用于**analysis port**(广播式通信) - 不适用于阻塞/非阻塞端口[^4] 3. **实现要求** - 组件中必须实现`write_<suffix>()`方法 - 方法签名必须匹配:`function void write_<suffix>(T t)` > 该宏本质是通过元编程生成特定端口类,解决了UVM组件中多analysis端口的方法名冲突问题,是构建复杂验证环境的基础工具[^2][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MangoPapa

请作者喝瓶可乐吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值