(4)UVM 覆盖方法(override)

本文详细介绍了UVM的覆盖方法,包括覆盖的概述、如何使用覆盖相关函数、覆盖实例以及确保正确覆盖的代码要求。覆盖机制允许在不修改原始代码的情况下,通过工厂创建新类型的对象,实现灵活性和配置的便捷性。文章强调了类型覆盖和实例覆盖的区别,并提供了具体的代码示例。此外,还给出了关于正确使用覆盖的一些建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

UVM 覆盖方法

一、概述

工厂提供的便利—覆盖
覆盖机制可以将其原来所属的类型替换为另外一个新的类型。
在覆盖之后,原本用来创建原属类型的请求,将由工厂来创建新的替换类型。
覆盖带来的便利:
1.无需再修改原始代码,继而保持了原有代码的封装性;
2. 新的替换类型必须与被替换类型相兼容,否则稍后的句柄赋值将失败,所以使用继承。//新定义的类型必须继承于原有的类型。
做顶层修改时,非常方便!
1.允许灵活的配置,例如可使用子类来覆盖原本的父类;
2.可使用不同的对象来修改其代码行为。
要想实现覆盖特性,原有类型和新类型均需要注册。
当使用create()来创建对象时:
1.工厂会检查,是否原有类型被覆盖
2.如果是,那么它会创建一个新类型的对象
3.如果不是,那么它会创建一个原有类型的对象
覆盖发生时,可以使用“类型覆盖”或者"实例覆盖"
1.类型覆盖指,UVM层次结构下的所有原有类型都被覆盖类型所替换。
2.实例覆盖指,在某些位置中的原有类型会被覆盖类型所替换。

二、覆盖方法

set_type_override()

static function void set_type_override(uvm_object_wrapper override_type,bit replace=1);
  • uvm_object_wrapper override_type
    它并不是某一个具体实例的句柄,实际上是注册过后的某一个类在工厂中注册时的句柄。怎么找到它呢?就使用new_type::get_type()。
  • bit replace
    1:如果已经有覆盖存在,那么新的覆盖会替代旧的覆盖。
    2:如果已经有覆盖存在,那么该覆盖将不会生效。
  • set_type_override是一个静态函数
    orig_type::type_id::set_type_override(new_type::get_type())
    orig_type是原有的类型,new_type是新的类型

set_inst_override()

static function void set_inst_override(uvm_object_wrapper override_type,string inst_path,uvm_component parent=null);
  • string inst_path指向的是组件结构的路径字符串
  • uvm_component parent=null
    如果缺省,表示使用inst_path内容为绝对路径
    如果有值传递,则使用{parent.get_full_name(),"",inst_path}来作为目标路径。
  • orig_type::type_id::set_inst_override(new_type::get_type(),“orig_inst
### UVM Override 优先级规则 在 UVM 中,`type override` 和 `instance override` 是两种主要的覆盖机制。它们用于动态替换类实例或对象的行为。以下是关于这两种覆盖方式及其优先级的具体说明: #### Type Override Type override 使用的是静态绑定的方式,在编译阶段完成绑定操作。它会将指定类型的对象替换成另一个派生类型的对象。 - **语法**: ```verilog set_type_override_by_name("original_class", "derived_class"); ``` 或者: ```verilog set_type_override_by_type(original_class::get_type(), derived_class::get_type()); ``` - **特点**: - 对于所有的组件实例生效。 - 如果未定义 instance override,则 type override 将被应用。 - 可以通过命令行参数 `-uvm_set_type_override original_class derived_class` 进行动态配置[^4]。 #### Instance Override Instance override 则是在运行时对特定路径下的实例进行覆盖。它的作用范围更具体,仅限于指定路径中的某些实例。 - **语法**: ```verilog set_inst_override_by_name("original_class", "derived_class", "path_to_instance"); ``` 或者: ```verilog set_inst_override_by_type(original_class::get_type(), derived_class::get_type(), "path_to_instance"); ``` - **特点**: - 覆盖只适用于指定路径下的实例。 - 若存在多个匹配路径,则按照路径长度从短到长逐一尝试匹配并覆盖。 - 当前路径下如果有更高优先级的覆盖(如 context 设置),则忽略低优先级的覆盖[^2]。 #### Priority Rules (优先级规则) 1. **Context-Specific Overrides**: Context-specific overrides 的优先级高于全局级别的 overrides。如果设置了 `cntxt` 参数来限定资源的作用域,则该范围内具有更高的优先权。 2. **Instance vs Type**: 在相同条件下,instance override 总是优于 type override。这是因为 instance override 更加精确地指定了目标位置和对象。 3. **Path Length Matching**: 对于多条可能满足条件的路径而言,越具体的路径(即更深嵌套层次)会被赋予更大的权重来进行最终的选择处理过程。 4. **Command Line Options**: 命令行传递过来的相关设置通常也会被认为是最新的更改需求从而获得最高的执行权限级别;不过实际效果取决于工具本身支持情况以及内部实现逻辑差异等因素影响. #### 示例代码展示 以下是一个简单的例子展示了如何利用上述提到的各种方法去改变默认创建出来的 transaction 类型: ```verilog class my_transaction extends uvm_sequence_item; `uvm_object_utils(my_transaction) rand bit[7:0] data; function new(string name="my_transaction"); super.new(name); endfunction :new endclass :my_transaction // Derived Transaction Class class modified_my_transaction extends my_transaction ; `uvm_object_utils(modified_my_transaction ) constraint c_data {data !=8'hFF;} // Add a Constraint to avoid FF value. function new(string name="modified_my_transaction "); super.new(name); endfunction:new endclass :modified_my_transaction class env extends uvm_env; `uvm_component_utils(env) function new(string name,uvm_component parent=null ); super.new(name,parent); endfunction:new virtual function void build_phase(uvm_phase phase); super.build_phase(phase); // Set Type Override Globally. this.set_type_override_by_type(my_transaction ::get_type(), modified_my_transaction ::get_type()); // Alternatively you can use command line option as well like below one- /* * +UVM_SET_TYPE_OVERRIDE=my_transaction ,modified_my_transaction */ // Now Let's try setting an Instance Level Override too... string inst_path = {"env.agent.driver"}; this.set_inst_override_by_type(my_transaction ::get_type(), another_modified_version_of_trans ::get_type(), inst_path ); endfunction :build_phase endclass :env ``` 在这个例子中我们首先定义了一个基础事务包(`my_transaction`)接着又基于此扩展出了两个不同的版本分别叫做 (`modified_my_transaction`, `another_modified_version_of_trans`). 接着我们在环境中实现了两层不同粒度上的替代策略——首先是整个项目内的通用替换方案(type-level),其次是针对某一部分特殊区域单独定制化的解决方案(instance-level).
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

数字IC小白的日常修炼

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值