【uvm源码】uvm_port_base

一、源代码中是什么?

uvm_port_base.svh
此文件中包含3个class,分别是uvm_port_component_base、uvm_port_component #(PORT)、uvm_port_base #(IF);

端口基类
uvm_port_component_base: 该类定义了一个接口,用于在 end_of_elaboration 阶段之后或期间获取端口的连接列表。
uvm_port_component #(PORT): 有关此类的信息,请参见 uvm_port_component_base 的描述
uvm_port_base #(IF): 组件之间的事务级通信通过其ports、exports和 imps 处理,所有这些都派生自此类。

uvm_port_component_base类:

类的介绍:

在这里插入图片描述

此类定义了一个接口,用于在 end_of_elaboration 阶段之后或期间获取端口的连接列表。 子类 uvm_port_component #(PORT) 实现了这个接口。

连接列表以此类对象的句柄形式返回。 这允许通过递归调用 get_connected_to 和 get_provided_to 遍历任何端口的扇出和扇入网络。 可以使用从 uvm_component 继承的 get_full_name 和 get_type_name 方法检索每个端口的全名和类型名称。

类的方法:

get_connected_to: 用于返回所有此port主动连接的端口的列表,如一个analysis_port可以连接到多个IMP类型的端口,那么此函数将会返回所有的这些端口的列表。PORT、EXPORT和IMP均可以使用此方法。
get_provided_to 用于返回所有的此port被动连接的端口的列表。如对于一个IMP来说,可能有多个port、export练接到此端口,此函数将会返回这些端口的列表。只有IMP、export才能使用此方法。此函数与get_connected_to的区别在于一个是被动连接的,一个是主动连接的。。
is_port、is_export、is_imp 这些函数确定端口的类型。

uvm_port_component #(PORT)类:

类的介绍:

在这里插入图片描述

类的方法:

uvm_port_component #(PORT)类的方法:
get_port 检索此代理引用的实际端口对象。

uvm_port_base #(IF)类:

类的介绍:

在这里插入图片描述

uvm_port_base 扩展了 IF,即派生port、export或implementation所实现的接口类型。 IF 也是 uvm_port_base 的类型参数。

IF 子类型对该基端口实现的接口类型
UVM 为 OSCI 标准 TLM 接口提供了一整套ports、exports和 imps。它们可以在 …/src/tlm/ 目录中找到。对于 TLM 接口,IF 参数始终为 uvm_tlm_if_base #(T1,T2)。

就在uvm_component::end_of_elaboration_phase 之前,会发生一个内部 uvm_component::resolve_bindings 进程,之后每个port和export都包含一个通过与其他ports和exports的分层连接与其连接的所有 imps 的列表。实际上,我们正在将port的扇出(它可以跨越组件层次结构的上下几个级别)折叠到端口本地的单个数组中。确定列表后,可以检查并强制执行port的最小和最大连接设置。

uvm_port_base 拥有组件的属性,因为它们具有分层的实例路径和父级。因为 SystemVerilog 不支持多重继承,所以 uvm_port_base 不能同时扩展它实现的接口和 uvm_component。因此,uvm_port_base 包含一个 uvm_component 的本地实例,它将 get_name、get_full_name 和 get_parent 等命令委托给该实例。

类的方法:

uvm_port_base #(IF)类的方法:
new 前两个参数是普通的 uvm_component 构造函数参数。
get_name 返回此端口的叶名称。
get_full_name 返回此端口的完整分层名称。
get_parent 返回此端口父级的句柄,如果没有父级,则返回 null。
get_comp 返回代表此端口的内部代理组件的句柄。
get_type_name 将类型名称返回到此端口。
min_size 返回在 end_of_elaboration 阶段必须连接到此端口的最小实现端口数。
max_size 返回在 end_of_elaboration 阶段必须连接到此端口的最大实现端口数。
is_unbounded 如果此端口在此端口可以连接的实现端口数上没有最大值,则返回 1。
is_portis_exportis_imp 如果此端口属于方法名称给定的类型,则返回 1,否则返回 0。
size 获取连接到该端口的实现端口数。
set_default_index 设置调用接口方法时使用的默认实现端口。
connect 将此端口连接到给定的提供程序端口。

debug_connected_to debug_connected_to 方法输出此端口连接到的端口/导出/imp 网络的可视文本显示(即端口的扇出)。
debug_provided_to debug_provided_to 方法输出最终连接到该端口的端口/出口网络的可视化显示(即端口的扇入)。
resolve_bindings 这个回调在进入 end_of_elaboration 阶段之前被调用。
get_if 从此端口连接到的 imps 数组中返回给定索引处的实现 (imp) 端口。

在这里插入图片描述

connect
将此端口连接到给定的provider端口。端口必须通过以下方式兼容:

 它们的类型参数必须匹配;
 provider的接口类型(阻塞、非阻塞、analysis等)必须兼容。每个端口都有一个interface mask,对它支持的接口进行编码。如果这些掩码的按位与等于此端口的掩码,则满足要求并且端口兼容。例如,uvm_blocking_put_port #(T) 与 uvm_put_export #(T) 和 uvm_blocking_put_imp #(T) 兼容,因为 export 和 imp 提供了 uvm_blocking_put_port 所需的接口。
 UVM_EXPORT 类型的端口只能连接到其他exports或imps。
 UVM_IMPLEMENTATION 类型的端口无法连接其他端口,因为它们在构造时绑定到实现接口的组件。

除了类型兼容性检查之外,如果设置了端口的 check_connection_relationships 配置,还将检查此端口与provider端口之间的关系。 (有关更多信息,请参阅新的。)

当enabled时,Relationships检查如下:
 如果此端口是 UVM_PORT 类型,则提供程序可以是父端口,也可以是同级export或Imp端口。
 如果此端口是 UVM_EXPORT 类型,则提供程序可以是子export或Imp端口。
如果违反任何关系检查,则会发出警告。

注意 - uvm_component::connect_phase 方法与此方法相关但不相同。组件的 connect方法是一个phase回调,其中执行端口的connect方法。

二、uvm中的原理是怎么样的

在env的connect_phase中经常见到的A.connect(B)到底执行了个什么呢?

根据phase执行顺序,执行完build_phase后,就开始执行connect_phase,在connect_phase中,就会去执行A.connect(B)这样的代码行,这里执行的就是uvm_port_base.svh中的connect()方法,即下图中的connect方法。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
connect_phase执行完后,意味着这些端口连接就OK了吗?其实并不是的,执行完connect_phase只是每个端口中的m_provided_by和m_provided_to存放了对应的端口指针。

我们也经常见到如下的使用方法,这个具体调用了源码中的那段代码呢?而且此时又需要在接收端口所在的组件中实现一个put方法,这又是为什么呢?
在这里插入图片描述
接下来我们就针对这些疑惑,看看源码。
我们以uvm_blocking_put_port为例,这个端口的源代码如下:
在这里插入图片描述
可以看到uvm_blocking_put_port扩展自uvm_port_base,uvm_port_base的参量是uvm_tlm_if_base类型的。uvm_blocking_put_port里面通过2个宏来实现,具体代码如下:
在这里插入图片描述
在这里插入图片描述
在UVM_BLOCKING_PUT_IMP宏中定义的是一个put方法,这个put方法又调用了imp里面的put方法,传入参量arg。至此我们可以明白blocking_put_port.put(tr)调用的就是这个宏所表示的put方法。
那问题又来了,这个imp又是个什么东西呢?为啥要用imp呢?这个imp其实是uvm_blocking_put_port中的this.m_if,那这个m_if到底代表的含义是什么呢?我们接下来就看看uvm_phase机制的的执行过程,看看过程中都做了什么。
在这里插入图片描述
根据uvm_phase执行机制,执行完uvn_connect phase后,在执行end_of_elaboration_ph phase时,因为end_of_elaboration_ph phase是自顶向下执行的,故会调用uvm_bottomup_phase中的traverse方法,即下面代码所示。
在这里插入图片描述

在这个traverse函数中会调用comp.phase_started(),这个phase_started()是uvm_component的一个方法,这个方法在uvm_root类中被重载,重载的内容是判断执行的phase是否是end_of_elaboration_ph,如果是则执行do_resolve_binding方法,如下面代码所示。
在这里插入图片描述

uvm_component定义了do_resolve_binding方法,这个方法采用递归的方式调用resolve_binding方法;uvm_component中定义的resolve_bindings方法是个空函数,但每一个port继承自uvm_port_base,uvm_port_base中uvm_port_component对resolve_bindings进行了重载,此时就调用了resolve_bindings方法。具体代码如下:
在这里插入图片描述
在这里插入图片描述
也就是每个port都会执行这个resolve_bindings方法;张强的《UVM1.1应用指南与源代码分析》中对这一块有清晰的说明,具体如下。下图中所谓的716到726行对于上面截图的734-744行。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

再次看看m_if是怎么被得到的

uvm_port_base中定义了m_if变量,这个变量在set_if函数中被使用,set_if函数中调用了get_if函数,get_if返回的是m_imp_list[string]联合数组,这里面存放的是port或者export对应的IMP指针,通过m_add_list这个方法来填充这个m_imp_list数组;m_add_list是在resolve_bindings函数中被调用;具体如下面代码所示。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

这个m_if指针的作用是什么呢?也就是它干嘛用呢?

我们以uvm_blocking_put_port为例来说明,uvm_blocking_put_port的定义中有`UVM_BLOCKING_PUT_IMP宏,这个宏定义了一个任务put,这个task中就调用了传的参this.m_if,即imp类型,在put这个task中,调用了this.m_if的put函数。也就是说这个this.m_if是连接到此port的imp所在component的指针。(纠错一下,原先写的是连接到此port的imp所在component的指针,正确的应该是连接到此port的imp的指针)
在这里插入图片描述
在这里插入图片描述
再回到blocking_put_port.put(tr)这个方法上面:
上面有说过,最终会调用imp的put方法;
那imp的put方法具体是什么呢?我们一起看看源代码;

imp的源码定义如下图所示,可以看出在一个comp中实例化一个imp端口时,会传递此imp所在的comp指针给到imp,就是m_imp。上面刚说的调用imp的put方法,imp的put方法如下图中第97行所示,实际上由调用了m_imp的put的方法,也就是调用了imp所在的comp的put方法,因此我们如果这样使用imp就需要在comp里面实现put方法
在这里插入图片描述

export与imp连接的场景:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

致谢
本文参考张强白皮书和网上部分资料,以表感谢。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
UVM(Universal Verification Methodology)中,UVM Driver是验证环境中的一个组件,用于将生成的数据驱动到设计被测对象(DUT,Design Under Test)的输入端口。而UVM Analysis PortUVM中的一种机制,用于实现组件之间的消息传递和数据分析。 UVM Driver和UVM Analysis Port之间的关系是通过数据传递和消息分析来实现的。具体来说,UVM Driver可以通过UVM Analysis Port向其他组件发送数据或消息,以实现对验证环境中其他组件的相关操作和分析。 一种常见的应用场景是,在驱动过程中,如果需要将某些数据或事件通知到其他组件进行分析或记录,可以使用UVM Analysis Port。Driver可以将需要传递的数据或消息通过连接到UVM Analysis Port实例的方式发送出去。其他组件(如Scoreboard、Coverage Collector等)可以通过监听相同的UVM Analysis Port来接收这些数据或消息,并进行相应的处理和分析。 通过使用UVM Analysis Port,Driver可以方便地与其他验证环境中的组件进行数据传递和消息通信,实现各个组件之间的协作和信息交流。这种机制可以帮助验证工程师进行更全面、准确的数据分析和结果验证。 总结起来,UVM Driver是驱动被测对象的组件,而UVM Analysis Port是一种机制,用于实现组件之间的数据传递和消息分析。通过将UVM Analysis PortUVM Driver连接,可以方便地向其他组件发送数据或消息,实现验证环境的协作和数据分析。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值