目录
7. config机制
- 目的:为了验证环境的复用性,配置更细致的环境调节中的变量,在仿真时通过变量设置来修改环境。
- 方法:uvm_config_db配置类,几种方便的变量设置方法
- 使用方式1:传递virtual interface到环境中,连接软件和硬件世界
- 使用方式2:设置单一变量值
- 使用方式3:传递配置对象config object到环境
uvm_config_db#(T)::set(uvm_component cntxt, string inst_name, string field_name, T value);
// 传递一个实例句柄进来 实例名称 实例中的变量名 值
uvm_config_db#(T)::get(uvm_component cntxt, string inst_name, string field_name, inout T value);
- 使接口的传递和获取彻底分离开
接口的传递
- 接口传递应该发生在run_test()之前,保证在进入build phase之前,virtual interface已经被传递到uvm_config_db
- 把interface和virtual interface的声明区分开来,传递过程中的类型应该是virtual interface,即实际接口的句柄
interface intf1;
logic enable=0;
endinterface
class comp1 extends uvm_component;
`uvm_componnet_utils(comp1)
virtual intf1 vif;//拿到intf1的指针
......
function void build_phase (uvm_phase phase);
if(!uvm_config_db#(virtual intf1)::get(this, "", "vif", vif)) begin
//this表示当前的comp1(uvm_top.root.test.c1.vif),没有实例,变量是vif字符串要加“”,
`uvm_error("GETVIF", "no virtual interface is assigned")
end
`uvm_info("SETVAL", $sformatf("vif.enable is %b befor set", vif.enable), UVM_LOW)
vif.enable=1;
`uvm_info("SETVAL", $sformatf("vif.enable is %b after set", vif.enable), UVM_LOW )
endfunction
endclass
class test1 extends uvm_test;
`uvm_component_utils(test1)
comp1 c1;
...
endclass
intf1 intf();
initial begin
uvm_config_db#(virtual intf1)::set(uvm_root::get(), "uvm_test_top.c1", "vif", intf);
//先set进intf1中,等下就get出来
run_test("test1");//root->test->c1->vif,分别对应set中的4个参数
end
变量设置
- 各个test中可以在build phase对底层组件的变量加以配置,进而在环境例化之前完成配置,使环境可以如期运行
class comp1 extends uvm_component;
`uvm_component_utils(comp1)
int val1 = 1;
string str1 = "null";
......
function void build_phase (uvm_phase phase);
`uvm_info("SETVAL", $sformatf("val1 is %d before get", val1), UVM_LOW)
`uvm_info("SETVAL", $sformatf("str1 is %s before get", str1), UVM_LOW)
uvm_config_db#(int)::get(this, "", "val1", val1);
uvm_config_db#(string)::get(this, "", "str1", str1);
`uvm_info("SETVAL", $sformatf("val1 is %d after get", val1), UVM_LOW)
`uvm_info("SETVAL", $sformatf("str1 is %s after get", str1), UVM_LOW)
endfunction
endclass
class test1 extends uvm_test;
`uvm_component_utils(test1)
comp1 c1;
......
function void build_phase (uvm_phase phase);
uvm_config_db#(int)::set(this, "c1", "val1", 100);//先set再例化
uvm_config_db#(string)::set(this, "c1", "str1", "comp1");
c1=comp1::type_id::create("c1", this);
endfunction
endclass
object传递
- 多个变量需要配置的时候就很麻烦,可以将需要配置的变量封装成一个类,放到一个uvm_object,再对中心化的配置对象进行传递
class config1 extends uvm_object;
int val1=1;
int str1="null";
`uvm_object_utils(config1)
......
endclass
class comp1 extends uvm_component;
`uvm_component_utils(comp1)
config1 cfg;
......
function void build_phase(uvm_phase phase)
uvm_object tmp;
uvm_config_db#(uvm_object)::get(this, "", "cfg", tmp);//得到的tmp是父类句柄
void'($cast(cfg, tmp));//传递的类型要保持一致
`uvm_info("SETVAL", $sformatf("cfg.val1 is %d after get", cfg.val1), UVM_LOW)
`uvm_info("SETVAL", $sformatf("cfg.str1 is %s after get", cfg.str1), UVM_LOW)
endfunction
endclass
class test1 extends uvm_test;
`uvm_component_utils(test1)
comp1 c1,c2;
config cg1, cfg2;
......
function void build_phase(uvm_phase phase);
cfg1= config1::type_id::create("cfg1");
cfg2= config2::type_id::create("cfg2");
cfg1.val1=30;
cfg1.str1="c1";
cfg2.val1=50;
cfg2.str1="c2";
uvm_config_db#(uvm_object)::set(this, "c1", "cfg", cfg1);//类型从int换成object
uvm_config_db#(uvm_object)::set(this, "c2", "cfg", cfg2);
c1=comp1::type_id::create("c1", this);
c2=comp2::type_id::create("c2", this);
endfunction
endclass
- uvm_config_db#(?)::set()时
- uvm_config_db#(?)::set()通过层次和变量名,将这些信息放置到uvm_pkg唯一的全局变量uvm_pkg::uvm_resources
- uvm_pkg::uvm_resources用来存储和释放配置资源信息(resource information)
- uvm_pkg::uvm_resources是uvm_resource_pool类的全局唯一实例,该实例中有两个resource数组用来存放配置信息,这两个数组中一个由层次名字索引,一个由类型索引。通过这两个关联数组可以存放通过层次配置的信息。同时底层的组件也可以通过层次或者类型取得来自高层的配置信息。
- 这样,信息的配置和获取得到剥离,便于调试和复用
- 使用uvm_config_db::get()时,通过传递的参数构成索引层次,在uvm_resource已有的配置信息池中索引该配置,索引到返回1
- 一些注意的点
- 使用set和get时,传递的参数类型应该上下一致,如果对uvm_object实例的传递set和get类型不一样,要用$cast()完成类型转换再操作!!!!!!!!!!!!
- set和get的参数可以用*表示任意层次
- **.*comp1和comp1的区别:
- 前者表示在目前层次以下所有名称comp1的组件,后者表示包括当前层次及其以下层次的comp1
- 在module中使用uvm_config_db::set(),第一个参数uvm_componnet cntxt一般用来表示当前的层次,如果是最高层,可以设置为null,也可以设置为uvm_root::get()来表示uvm_root的全局顶层实例
- 先set,再例化创建对象
- 多个层次组件进行设置时,较高层次组件的配置有更高的优先级来配置
- 同一层次多次配置,后面的会覆盖前面的配置
- 使用get时,添加便于调试语句,多打印