3. 使用UVM工厂创建组件
任务目标
本案例将实现一个最小UVM验证环境,演示两个核心点:一是通过uvm_component_utils宏注册组件并使用create()方法创建实例;二是利用UVM工厂的set_type_override_by_type()机制实现组件类型重载,验证重载后工厂实际创建的是新类型对象。
环境依赖
需要支持UVM-1.2或UVM-2020的仿真器(如VCS、QuestaSim、Xcelium)。以下代码基于UVM-1.2标准库编写,无需额外安装包。
完整实现代码
```systemverilog
// 文件: factory_demo.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 function void print_type();
$display("[%0t] %s: I am BASE driver", $time, get_full_name());
endfunction
endclass
// 派生类组件:扩展driver,重载print_type
class ext_driver extends base_driver;
`uvm_component_utils(ext_driver)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
virtual function void print_type();
$display("[%0t] %s: I am EXTENDED driver", $time, get_full_name());
endfunction
endclass
// 测试顶层:创建组件并演示工厂重载
class factory_test extends uvm_test;
`uvm_component_utils(factory_test)
base_driver drv1;
base_driver drv2;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
// 1. 正常创建:drv1为base_driver类型
drv1 = base_driver::type_id::create("drv1", this);
// 2. 注册类型重载:所有base_driver创建请求改为ext_driver
base_driver::type_id::set_type_override_by_type(
base_driver::get_type(),
ext_driver::get_type()
);
// 3. 重载后创建:drv2实际为ext_driver类型
drv2 = base_driver::type_id::create("drv2", this);
endfunction
virtual function void end_of_elaboration_phase(uvm_phase phase);
super.end_of_elaboration_phase(phase);
$display("=== 类型检查 ===");
drv1.print_type();
drv2.print_type();
// 使用uvm_is_a验证实际类型
if (drv2.uvm_is_a("ext_driver"))
$display("PASS: drv2 is ext_driver (factory override works)");
else
$display("FAIL: drv2 is not ext_driver");
endfunction
endclass
// 顶层模块:启动UVM测试
module top;
initial begin
run_test("factory_test");
end
endmodule
```
运行方式
```bash
# 使用QuestaSim/ModelSim示例(其他仿真器命令类似)
vlib work
vlog +incdir+$UVM_HOME/src $UVM_HOME/src/uvm_pkg.sv factory_demo.sv
vsim -c -do "run -all; quit" work.top
```
验证方法与判定标准
运行仿真后,观察终端输出。满足以下条件即判定通过:
drv1.print_type()打印I am BASE driver,证明普通创建得到基类对象;drv2.print_type()打印I am EXTENDED driver,且后续显示PASS: drv2 is ext_driver,证明工厂重载生效。
预期输出(与代码逻辑严格一致):
=== 类型检查 ===
[0] uvm_test_top.drv1: I am BASE driver
[0] uvm_test_top.drv2: I am EXTENDED driver
PASS: drv2 is ext_driver
```
关键点说明
- 组件必须用
`uvm_component_utils宏注册,工厂才能识别并创建该类型; set_type_override_by_type()必须在create()之前调用,且影响后续所有匹配类型的创建请求;- 重载要求新类型是原类型的派生类,否则仿真器会报类型不匹配错误。