1.用途
config_db机制用于在UVM验证平台间传递参数,通常成对出现,其中set相当于寄信,get相当于收信。UVM提供的config_db机制可在组件实例化前就设定好配置信息,这样就可在tb的initial块中就进行设定了。真正将这些配置信息落实在各component,是在testbench运行过程build_phase中。
2.config_db参数
用法很简单,先使用uvm_config_db::set()将配置信息写好,相应的component使用uvm_config_db::get()获取配置信息,整个过程类似寄信"和“收信”。例如:
class uvm_config_db#(type T=int) extends uvm_resource_db#(T);
...
static function bit get(uvm_component cntxt,
string inst_name,
string field_name,
inout T value);
...
static function void set(uvm_component cntxt,
string inst_name,
string field_name,
T value);
static function bit exists(uvm_component cntxt, string inst_name,
string field_name, bit spell_chk=0);
...
endclass
那么它的几个参数具体指的是什么呢?
Type T:要配置的成员类型,默认为int;
uvm_component cntxt : set或get方法的发起者component,必须是一个component实例的指针;
string inst_name:从发起者component到要配置的目标component,在UVM树中的索引路径,这和上面一个参数联合构成了目标路径;
string field_name:域名称,一种标记,但一般为要配置的成员变量名;
T value: set方法中,表示将要为field_name成员设定的值。在get方法中,表示要赋值的成员。
来看一个例子:
function void my_test::build_phase(uvm_phase phase);
super.build_phase(phase);
env = my_env::type_id_create("env",this);
uvm_config_db#(int)::set(this,"env.i_agt.drv","pre_num",100);
//以下均是为目标drv的pre_num配置100
//uvm_config_db#(int)::set(this.env,"i_agt_drv","pre_num",100);
//uvm_config_db#(int)::set(this.env.i_agt.drv,"","pre_num",100);
//uvm_config_db#(int)::set(uvm_root::get(),"uvm_test_top.env.i_agt.drv","pre_num",100);
...
endfunction
function void my_driver::build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(int)::get(this,"","pre_num",pre_num))
uvm_report_info("CONFIG","PRE_NUM CONFIG FAILED!",UVM_LOW);
//uvm_config_db#(int)::get(uvm_root::get(),"uvm_test_top.env.i_agt.drv","pre_num",pre_num);
//uvm_config_db#(int)::get(uvm_test_top,"env.i_agt.drv","pre_num",pre_num);
...
endfunction
对于几个不同的set语句,均是对pre_num进行100的配值,区别在于发起的component不同;而对不同的get来说 uvm_config_db#(int)::get(this,"","pre_num",pre_num)表示每创建一个my_driver对象都要为自己的pre_num成员get一个配值;而后两句get语句则表示只会为my_driver类对象drv的pre_num成员get一个配值。
3.多重设定
上面的代码引申出一个问题,当有多个set配值时,应该听谁的话呢?原则为:发起者层次越高,优先级越高;发起时间越晚,优先级越高。
function void my_driver::build_phase(uvm_phase phase);
super.build_phase(phase);
uvm_config_db#(int)::get(this,"","pre_num",pre_num);
...
endfunction
function void my_test::build_phase(uvm_phase phase);
super.build_phase(phase);
uvm_config_db#(int)::set(uvm_root::get(),"uvm_test_top.env.i_agt.drv","pre_num",500);
uvm_config_db#(int)::set(this,"env.i_agt.drv","pre_num",100);
uvm_config_db#(int)::set(this.env,"i_agt.drv","pre_num",999);
...
endfunction
function void my_env::build_phase(uvm_phase phase);
super.build_phase(phase);
uvm_config_db#(int)::set(uvm_root::get(),"uvm_test_top.env.i_agt.drv","pre_num",200);
...
endfunction
在上面的代码中pre_num成员最终会被赋值为200,这是因为:发起者中层次最高的是第一句和最后一句的uvm_top(第二句是uvm_test_top,第三句是env,对层次了解不清楚可查阅uvm component树),而第四句的赋值时间晚于第一句,因此具有最高优先级,将pre_num成员最终会赋值为200。
如果是多次get呢?config机制允许set一次然后多次get,也就是说并不是get之后UVM就删除了该记录。
4.推荐用法
虽然set可以有多种多样的写法,一般来说,我们还是推荐固定写法:将发起者直接定为this。
uvm_config_db#(int)::set(this,"env.i_agt.drv","pre_num",100);
uvm_config_db#(int)::get(this,"","pre_num",pre_num);
这样对我们来说也简单省事,直接一个this搞定,让uvm_test_top在build_phase中完成所有的参数配置。
标签:pre,db,num,UVM,phase,config,uvm From: https://blog.csdn.net/zangzangbupei/article/details/140676189