UVM中有提供field automation机制,可以利用UVM內建的函数,比如print,clone,copy....,今天就聊一下我用copy函数遇到的问题。
class cfg1 extends uvm_object;
int id;
....
endclass
===============================================================
class cfg2 extends uvm_object;
int id;
cfg1 sub_cfg;
function new(string name = "cfg");
super.new(name);
sub_cfg = cfg1::type_id::create("sub_cfg");
endfunction
endclass
===============================================================
class ref extends uvm_component;
...
cfg2 o_cfg;
cfg1 s_cfg;
virtual function void build_phase(uvm_phase phase)
super.build_phase(phase);
if(!uvm_config_db#(cfg2)::get(this,$sformatf("o_cfg2"),"cfg",o_cfg))
`uvm_fatal(...)
s_cfg = o_cfg.sub_cfg;//保存了sub_cfg的handle
endfunction
endclass
上例中 class cfg2包含一个int 变量和一个cfg1的object ,如果在run_phase调用copy函数更新cfg2:
o_cfg_ary = cfg2::type_id::create("o_cfg_ary");
o_cfg_ary.sub_cfg.id = 2;
o_cfg.copy(o_cfg_ary);
o_cfg更新后,ref 拿到的仍然是原来的值 !!!!
root cause:
copy函数是深拷贝,所以在拷贝时cfg2中的object sub_cfg会重新分配内存空间,即handle地址发生变化.
ps:copy函数只拷贝利用field automation注册的变量和object。
一般在build_phase利用Config_db传递handle,一旦传递下去,如果中途handle发生改变,例如上例中本来想利用copy function改变ID(保证handle的地址不变,只更新内容),但o_cfg.sub_cfg的handle地址发生变化,且ref保存了sub_cfg handle的地址导致需要获取handle的class get到的handle仍然指向原来的内存空间。
1. 如果ref中用sub_cfg是采用 o_cfg.sub_cfg.id,copy 函数没有影响(即使o_cfg.sub_cfg的handle地址发生变化也不影响);
2. 如果ref中“s_cfg = o_cfg.sub_cfg”保存了sub_cfg handle的地址,但o_cfg.sub_cfg的handle地址发生变化,无法指向sub_cfg新分配的空间,也就拿不到更新之后的值;
solution:
o_cfg_ary = cfg2::type_id::create("o_cfg_ary");
o_cfg_ary.sub_cfg.id = 2;
o_cfg.copy(o_cfg_ary);
o_cfg.sub_cfg.copy(o_cfg_ary.sub_cfg);//递归调用copy函数