☰
uvm factory机制学习二(注册宏)
2026/10/17 1:47:40 网站建设 项目流程

注册宏这部分代码,是uvm factory机制中最具有标志性的代码,当看到这部分代码,最直接的反应应该是,该类在声明时,已经将自己这个类型注册到了工厂中。

对于一个宏,要想真正理解它,必须将宏展开,分析其代表的代码。接下来对`uvm_object_utils()宏,`uvm_object_param_utils()宏,`uvm_component_utils()宏,`uvm_component_param_utils()宏进行拆解

一、uvm_object相关的注册宏

1.1 不带参数的object类的注册

当使用uvm_object_utils时,展开会发现调用了其他的宏。

当调用了`uvm_object_utils(T)时,发生了什么?

`uvm_object_utils(T) // 实际调用的是 `uvm_object_utils_begin(T) `uvm_object_utils_end `uvm_object_utils_begin(T) // 实际调用的是 `m_uvm_object_registory_internal(T) `m_uvm_object_create_func(T) `m_uvm_get_type_name_func(T) `uvm_field_utils_begin(T) 因此,uvm_object_utils实际调用的是 `m_uvm_object_registory_internal(T) `m_uvm_object_create_func(T) `m_uvm_get_type_name_func(T) `uvm_field_utils_begin(T) `uvm_object_utils_end ================================================================= // 当需要使用field automation机制时,`uvm_field_int这些宏要放在 // `uvm_field_utils_begin和`uvm_object_utils_end之间 // 所以就不能使用`uvm_object_utils宏,要使用拆开版本 `uvm_object_utils_begin(T) `uvm_field_int(aaa) `uvm_field_int(bbb) `uvm_object_utils_end
1.2 带参数的object类的注册

当调用了`uvm_object_param_utils(T)时,发生了什么?

注意,当使用uvm_object_param_utils_begin(T)时,结尾依旧是`uvm_object_utils_end。而不是`uvm_object_param_utils_end

`uvm_object_param_utils(T) // 实际调用的是 `uvm_object_param_utils_begin(T) `uvm_object_utils_end // 实际调用的是 `m_uvm_object_registory_param(T) `m_uvm_object_create_func(T) `uvm_field_utils_begin(T) `uvm_object_utils_end // 当需要使用field automation机制时,`uvm_field_int这些宏要放在 // `uvm_field_param_utils_begin和`uvm_object_utils_end之间 // 所以就不能使用`uvm_object_param_utils宏,要使用拆开版本 `uvm_object_param_utils_begin(T) `uvm_field_int(aaa) `uvm_field_int(bbb) `uvm_object_utils_end

当我们拆开uvm_obejct_utils时,会发现其内部调用了其他的宏,uvm_field_utils_begin和uvm_field_int相关的宏,是和field_automation机制相关的,不在本文讨论范围之内。

  • 除此之外,我们还可以发现一个规律,uvm_object_utils宏,用于对非参数化类的注册,其使用了`m_uvm_object_registory_internal(T) , `m_uvm_object_create_func(T) , `m_uvm_get_type_name_func(T) 这三个宏
  • 而uvm_object_param_utils宏,用于对参数化类的注册,其使用了`m_uvm_object_registory_param(T) , `m_uvm_object_create_func(T) ,不再使用`m_uvm_get_type_name_func(T)宏。只使用了两个宏,这是两种注册方式的一个显著差别。

而`m_uvm_object_registory_internal(T) , `m_uvm_object_create_func(T) , `m_uvm_get_type_name_func(T) , `m_uvm_object_registory_param(T) 这些宏将涉及到factory机制注册的核心。


1.3 和factory机制注册相关的核心宏
1.3.1 `m_uvm_object_registory_internal(T)

这个宏太关键了,m_uvm_object_registry_internal(T, S) 宏主要负责将当前类与 UVM 工厂(Factory)的代理注册机制进行底层绑定。它通过定义类型别名和静态/虚函数,为该类赋予了工厂创建与类型查询的能力。具体做了以下三件事:

1. 定义内部类型别名 type_id:

  • 通过 typedef uvm_object_registry#(T, "S") type_id;创建了一个快捷别名。其中 T 是类名,"S" 是该类的字符串形式。这个 uvm_object_registry 就是核心的代理(Wrapper)类,负责向全局工厂注册和创建对象。

2. 定义静态方法 get_type():

  • 提供了一个静态函数 get_type(),它会调用 type_id::get() 返回该类在工厂中的单例包装器实例。这允许用户直接通过类名(如 my_object::get_type())来获取类型标识,常用于重载(Override)等操作。

3. 实现虚方法 get_object_type():

  • 实现了 UVM 对象自带的虚方法 get_object_type(),同样返回 type_id::get()。这使得在多态场景下,即使面对基类指针或句柄,也能通过实例动态获取其对应的实际工厂类型包装器。
1.3.2 工厂核心注册类 uvm_object_registry#(T, S)

Registry 的本意是登记处、注册表、记录簿。这个类的核心作用就是进行注册。

当在一个object类objA中,使用m_uvm_object_registry_internal(T, S) 宏时,会使用typedef 将uvm_object_registry#(T,S)设置一个别名叫type_id, 于是type_id成为了objA中的一个静态成员。当在objA之外,去访问type_id时,需要使用objA::type_id

在factory机制中,创建,重载,都在使用type_id,也就是uvm_object_registry这个类内部的静态函数,所以这个uvm_object_registry是整个factory机制的核心

1.3.3 uvm_object_registry的父类——uvm_object_wrapper类

首先需要明确,uvm_object_wrapper继承自uvm_void这个空的类,而uvm_object也是继承自uvm_void这个空类,所以uvm_object_wrapper和uvm_object这两个类是并列关系,不存在继承关系,

而且uvm_object_wrapper类的存在是为factory机制设计的,这个类的定义本身就是放在uvm_factory.svh文件中的。

在 SystemVerilog 的参数化类中,参数可以分为两类:

类型参数(Type Parameter):使用 type 关键字声明,传进去的是一个具体的类或数据类型(例如 my_driver、int)。

值参数(Value Parameter):使用具体数据类型(如 string、int)声明,传进去的是一个具体的值或字面量(例如 "my_driver"、8)。

为什么需要传字符串参数?UVM 的 Factory 机制不仅支持通过类型本身(如

my_driver::get_type())来操作,还必须支持通过字符串名字来管理。例如:允许用户在命令行或配置文件中直接用字符串(如 "my_driver")来指定重载或查找类型。允许 Factory 在全局维护一个“字符串名字 $\rightarrow$ 类型注册器”的查找表(Map),实现类似动态语言的反射(Reflection)功能。

二、uvm_component类相关的注册宏

2.1. 不带参数的component类的注册

使用uvm_component_utils时,展开情况和uvm_object_utils类似。

`uvm_component_utils(T) // 实际调用的是 `m_uvm_component_registry_internal(T,T) \ `uvm_type_name_decl(`"T`") \ `uvm_component_utils_begin(T) // 实际调用的是 `uvm_component_utils(T) \ `uvm_field_utils_begin(T) // 当需要使用field automation机制时,`uvm_field_int这些宏要放在 // `uvm_field_utils_begin和`uvm_component_utils_end之间 // 所以就不能使用`uvm_component_utils宏,要使用拆开版本 `uvm_component_utils_begin(T) `uvm_field_int(aaa) `uvm_field_int(bbb) `uvm_component_utils_end
2.2. 带参数的component类的注册
`uvm_component_param_utils(T) // 实际调用的是 `m_uvm_component_registry_param(T,T) \ `uvm_component_utils_param_begin(T) // 实际调用的是 `uvm_component_param_utils(T) \ `uvm_field_utils_begin(T) // 当需要使用field automation机制时,`uvm_field_int这些宏要放在 // `uvm_field_utils_begin和`uvm_component_utils_end之间 // 所以就不能使用`uvm_component_utils宏,要使用拆开版本 `uvm_component_param_utils_begin(T) `uvm_field_int(aaa) `uvm_field_int(bbb) `uvm_component_utils_end

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询