UVM(二):factory机制——工厂的作用及本质、重载(override)

1.factory机制的作用

        在SystemVerilog中,我们知道,要创建一个类的实例,必须使用new()函数。而在UVM中,提供了factory机制:它可以根据类名创建这个类的一个实例;另外,还可以在创建类的实例时根据是否有重载类型来决定是创建原始的类,还是创建重载后的类的实例。

        从本质上来看,factory机制其实是对SystemVerilog中new函数的重载:原始的new函数功能太过简单。经过factory机制的改良后,进行实例化的方法多了很多。

2.使用factory机制进行重载

        factory机制最伟大的地方在于其具有重载(override)功能。当然,对于任何一种面向对象语言来说,都具有重载功能。在SystemVerilog中,当在父类中定义一个函数或任务时,如果将其设置为virtual类型,就可以在子类中重载这个函数或任务。

        重载方法可以将其原来所属的类型替换为另一个新的类型。在重载之后,原本用于创建(create)原属类型的请求,将由factory机制来创建新的替换类型:这样就可以在不修改原有代码的条件下,用子类替代其父类。这就是用factory机制进行重载的作用。

        在实例化时,UVM会通过factory机制在自己内部的一张表格中查看是否有相关的重载记录(在使用set_type_override() 或 set_inst_overide() 等重载方法后,就相当于在factory机制的表格中加入了一条重载记录):当查到有重载记录时,就会使用新的类来替代旧的类。

        使用factory机制的重载必须满足的条件:

        (1)首先,最重要的一点是:新的用于替换的类型,必须继承于原有类型

class comp2 extends comp1; 

comp2用于替换comp1,即用于重载的类必须是原有的类的子类。

        (2)无论是用于重载的类(comp2)还是被重载的类(comp1),都要在定义的时候注册到factory机制中

`uvm_component_utils(comp1) 
`uvm_component_utils(comp2)

        (3)被重载的类在实例化时,必须使用factory机制的实例化方式(create),而不能使用传统的 new 方式

c1 = comp1::type_id::create("c1", null);

        (4)在被重载的类中,需要重写的方法,必须定义为virtual类型,否则访问不到重载类中的这个被重写后的方法。

3.factory机制的使用步骤

        第一步,将类注册到factory中:使用 `uvm_component_utils() 宏或 `uvm_object_utils() 宏。取决于该类是继承于uvm_component还是uvm_object基类。uvm_component类中的组建构成了UVM验证环境的层次,而uvm_object类构成了验证环境的属性(如配置)和数据传输;

        第二步,在例化前设置重载对象和类型。此步只在需要进行重载时执行;

        第三步,创建对象:使用factory机制创建:create。

### UVM 工厂机制的工作原理与实现方式 UVM(Universal Verification Methodology)中的工厂机制是一种强大的工具,允许用户动态地替换对象类型而不改变其原始代码逻辑。这种灵活性使得测试平台更加通用和可扩展。 #### 1. **UVM Factory 的核心概念** UVM 工厂是一个全局存在的“机构”,负责管理所有已注册的类及其实例化过程。任何希望利用工厂机制的类都必须先完成注册操作[^3]。一旦某个类被成功注册到工厂中,它就可以通过 `create` 方法而非传统的 `new` 方法来实例化对象。这种方式不仅简化了对象创建流程,还支持运行时的对象类型重载Override),从而增强了设计的灵活性[^2]。 #### 2. **Factory Mechanism 实现的关键要素** ##### (a) 类注册 为了使某特定类可以参与工厂机制,开发者需将其显式注册至工厂数据库。通常情况下,在定义此类时会调用宏命令如 `uvm_object_utils()` 或者 `uvm_component_utils()` 来自动执行这一任务。这些宏内部实现了必要的元数据记录工作以便后续查找匹配合适的派生类实例。 ```cpp class my_class extends uvm_object; `uvm_object_utils(my_class) function new(string name="my_class"); super.new(name); endfunction : new endclass : my_class ``` 上述代码片段展示了如何声明并注册一个新的基于 `uvm_object` 的子类给 UVM framework 使用[^4]。 ##### (b) 对象创建 – Create vs New 当采用标准的新建语法 (`new`) 创建组件或事务项时,返回的具体类型始终固定不变;然而如果改用由工厂提供的接口(`create`) 则可能依据当前设置而获得完全不同的衍生版本作为结果[^5]: ```cpp // Traditional instantiation using 'new' my_base_class obj = new(); // Dynamic creation via the factory's 'create' method. my_base_class overridden_obj = my_base_class::type_id::create("overridden_instance_name", parent_comp); ``` 这里需要注意的是第个参数代表父级组件指针,对于顶层组件来说传入 null 即可。 ##### (c) Type Override 和 Name Override 两种主要形式可用于指定哪些基底类别应该替换成其他替代品: - **Type Override**: 配置整个模拟期间有效的一般性映射关系。 ```tcl set_type_override_by_type(base_t, derived_t) ``` - **Instance Override**: 局限于某些具体命名路径下的个别实体才生效 ```tcl set_inst_override_by_type(parent_path.base_t, inst_name, derived_t) ``` 这两种策略均依赖先前讨论过的预先登记步骤才能正常运作[^1]。 #### 3. **调试辅助功能** 除了基本的功能外,UVM 还提供了若干实用程序帮助我们确认预期行为是否达成目标状态之一便是打印出完整的环境树形图谱: ```cpp uvm_top.print_topology(); ``` 此指令将会输出当前加载好的全部层次结构连同各节点名称以及它们所属种类等细节信息便于排查潜在错误点或者验证设定准确性. --- ### 结论 综上所述,UVM Factories 提供了一种优雅的方法让工程师能够在不修改原有架构的前提下轻松调整实际部署的内容物; 它们背后隐藏着一套复杂却井然有序的操作规程涵盖了从初始准备到最后应用落地各个环节. ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值