4. UVM中的配置数据库使用
任务目标
在UVM测试平台中,使用uvm_config_db完成三类典型配置的传递:接口(virtual interface)、整型变量、类对象,并在组件中正确读取,最终通过UVM报告机制验证配置内容与预期一致。
环境依赖
本案例基于标准UVM库(UVM-1.2或更高),需要已安装支持UVM的仿真器(如VCS、QuestaSim、Xcelium)。无需额外IP或外部库。
实现方案
构建一个最小测试平台:顶层模块tb_top中实例化被测接口my_if,在initial块中通过uvm_config_db#(virtual my_if)::set传递接口;在测试类my_test的build_phase中通过uvm_config_db#(int)::set传递整型参数,通过uvm_config_db#(my_object)::set传递类对象。环境类my_env在build_phase中通过对应的get调用读取全部三项配置,并在end_of_elaboration_phase中打印读取结果,使用`uvm_info宏输出。测试类在run_phase中通过uvm_config_db#(int)::get再次读取整型参数,验证跨层级读取一致性。
关键完整代码
// 文件: config_db_demo.sv
`include "uvm_macros.svh"
import uvm_pkg::*;
// 被测接口
interface my_if(input logic clk);
logic rst_n;
logic [7:0] data;
endinterface
// 用于配置传递的简单类对象
class my_object extends uvm_object;
string name_str;
int value;
`uvm_object_utils_begin(my_object)
`uvm_field_string(name_str, UVM_ALL_ON)
`uvm_field_int(value, UVM_ALL_ON)
`uvm_object_utils_end
function new(string name = "my_object");
super.new(name);
endfunction
endclass
// 环境组件:读取全部三项配置
class my_env extends uvm_env;
`uvm_component_utils(my_env)
virtual my_if vif;
int cfg_int;
my_object cfg_obj;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
if (!uvm_config_db#(virtual my_if)::get(this, "", "vif", vif))
`uvm_fatal("NOVIF", "无法从config_db获取virtual interface")
if (!uvm_config_db#(int)::get(this, "", "cfg_int", cfg_int))
`uvm_fatal("NOINT", "无法从config_db获取整型配置")
if (!uvm_config_db#(my_object)::get(this, "", "cfg_obj", cfg_obj))
`uvm_fatal("NOOBJ", "无法从config_db获取对象配置")
endfunction
function void end_of_elaboration_phase(uvm_phase phase);
`uvm_info("CFG_CHECK", $sformatf("接口句柄有效: %0d, 整型配置: %0d, 对象名: %s, 对象值: %0d",
(vif != null), cfg_int, cfg_obj.name_str, cfg_obj.value), UVM_LOW)
endfunction
endclass
// 测试类:设置整型与对象配置,并在run_phase中验证读取
class my_test extends uvm_test;
`uvm_component_utils(my_test)
my_env env;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
env = my_env::type_id::create("env", this);
// 设置整型配置
uvm_config_db#(int)::set(this, "env", "cfg_int", 42);
// 设置对象配置
my_object obj = my_object::type_id::create("obj");
obj.name_str = "demo_obj";
obj.value = 100;
uvm_config_db#(my_object)::set(this, "env", "cfg_obj", obj);
endfunction
task run_phase(uvm_phase phase);
int readback_int;
phase.raise_objection(this);
#10ns;
// 从测试层级读取整型配置,验证跨层级可见性
if (uvm_config_db#(int)::get(this, "env", "cfg_int", readback_int))
`uvm_info("TEST_READ", $sformatf("测试层读取整型配置: %0d", readback_int), UVM_LOW)
else
`uvm_error("READFAIL", "测试层无法读取整型配置")
phase.drop_objection(this);
endtask
endclass
// 顶层模块
module tb_top;
logic clk = 0;
always #5 clk = ~clk;
my_if u_if(clk);
initial begin
// 设置接口配置
uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.env", "vif", u_if);
run_test("my_test");
end
initial begin
#200ns;
$finish;
end
endmodule
运行方式
# 使用QuestaSim示例(其他仿真器命令类似)
vlib work
vlog +incdir+$UVM_HOME/src $UVM_HOME/src/uvm_pkg.sv config_db_demo.sv
vsim -c -do "run -all; quit" work.tb_top
若使用VCS:vcs -sverilog +incdir+$UVM_HOME/src $UVM_HOME/src/uvm_pkg.sv config_db_demo.sv -R
验证方法与判定标准
仿真运行后,观察终端输出。判定通过的充分条件:
- 仿真器报告
UVM_ERROR : 0,UVM_FATAL : 0; - 出现来自
my_env的CFG_CHECK信息,内容为接口句柄有效: 1, 整型配置: 42, 对象名: demo_obj, 对象值: 100; - 出现来自
my_test的TEST_READ信息,内容为测试层读取整型配置: 42。
以上输出由代码逻辑直接唯一推出,为预期输出而非实测结果。若三项配置任一读取失败,仿真将以UVM_FATAL终止,据此可定位配置传递链路中的断点。
常见问题
- 接口获取失败:确认
set中第一个参数为null且第二个参数为"uvm_test_top.env",与UVM顶层实例路径严格一致; - 整型/对象获取失败:检查
set的第二个参数(相对路径)是否与get的第二个参数匹配,本案例中均为"env"; - 对象字段打印为空:确认对象已通过
create分配内存并完成字段赋值,且uvm_object_utils_begin宏已正确声明字段。