2. 覆盖默认组件类型

任务目标

在UVM验证环境中,默认情况下uvm_component工厂根据类型名创建基类对象。本案例通过set_type_override_by_type将基类driver替换为派生类driver,并验证工厂实际创建的是派生类对象。

实现方案

定义基类base_driver和派生类ext_driver,在测试类中注册override,通过create方法创建组件并检查其类型。核心验证逻辑:使用UVM内置的get_type_name()和$cast确认对象类型。

关键完整代码

```systemverilog
// 文件: factory_override_test.sv
`include "uvm_macros.svh"
import uvm_pkg::*;

// 基类driver
class base_driver extends uvm_component;
    `uvm_component_utils(base_driver)
    function new(string name, uvm_component parent);
        super.new(name, parent);
    endfunction
    virtual task run_phase(uvm_phase phase);
        `uvm_info("BASE", "base_driver run_phase", UVM_LOW)
    endtask
endclass

// 派生类driver
class ext_driver extends base_driver;
    `uvm_component_utils(ext_driver)
    function new(string name, uvm_component parent);
        super.new(name, parent);
    endfunction
    virtual task run_phase(uvm_phase phase);
        `uvm_info("EXT", "ext_driver run_phase", UVM_LOW)
    endtask
endclass

// 测试类:注册override并验证
class factory_override_test extends uvm_test;
    `uvm_component_utils(factory_override_test)
    
    function new(string name, uvm_component parent);
        super.new(name, parent);
    endfunction
    
    virtual function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        // 注册override:将base_driver替换为ext_driver
        set_type_override_by_type(base_driver::get_type(), 
                                  ext_driver::get_type());
        // 通过工厂创建组件(应返回ext_driver实例)
        base_driver drv;
        drv = base_driver::type_id::create("drv", this);
        
        // 验证1:类型名检查
        if (drv.get_type_name() == "ext_driver")
            `uvm_info("PASS", "类型名验证通过: ext_driver", UVM_LOW)
        else
            `uvm_error("FAIL", $sformatf("类型名错误: %s", drv.get_type_name()))
        
        // 验证2:$cast检查(动态类型是否为ext_driver)
        ext_driver ext_drv;
        if ($cast(ext_drv, drv))
            `uvm_info("PASS", "$cast验证通过: 对象是ext_driver类型", UVM_LOW)
        else
            `uvm_error("FAIL", "$cast失败: 对象不是ext_driver类型")
    endfunction
    
    virtual function void end_of_elaboration_phase(uvm_phase phase);
        super.end_of_elaboration_phase(phase);
        // 打印工厂注册信息(可选调试)
        uvm_factory::get().print();
    endfunction
endclass

// 顶层模块
module top;
    initial begin
        run_test("factory_override_test");
    end
endmodule
```

运行方式

```bash
# 使用任意支持UVM-1.2或IEEE 1800.2的仿真器
# VCS示例:
vcs -sverilog +incdir+$UVM_HOME/src $UVM_HOME/src/uvm.sv \
    factory_override_test.sv -R -l run.log

# Questa/ModelSim示例:
vlog -sv +incdir+$UVM_HOME/src $UVM_HOME/src/uvm.sv factory_override_test.sv
vsim -c -do "run -all; quit" work.top
```

验证方法与判定标准

  • 通过条件:仿真日志中出现两条PASS信息,且无FAIL或UVM_ERROR。
  • 预期输出(由代码逻辑唯一确定):
UVM_INFO @ 0: ... [PASS] 类型名验证通过: ext_driver
UVM_INFO @ 0: ... [PASS] $cast验证通过: 对象是ext_driver类型
  • 附加观察:run_phase中打印的EXT信息(而非BASE)进一步确认执行的是派生类方法。

关键点说明

  • set_type_override_by_type必须在create之前调用,本案例在build_phase中完成。
  • 两个类都必须注册到工厂(`uvm_component_utils),否则override不生效。
  • 验证使用两种互补方式:get_type_name()检查静态注册名,$cast检查实际动态类型。