This is follow-up post about automatic setting of a variable in UVM component after being set in config_db. Like anything in UVM,there are 2 parts. The registration and actual call. Let’s do the registration first.
For a component, you can define fields using uvm_field_*
macros between uvm_component_utils_begin
and uvm_component_utils_end
. In this example, I will trace uvm_field_int
.
`uvm_component_utils_begin(foobar)
`uvm_field_int (addr, UVM_ALL_ON)
`uvm_component_utils_end
In src/macros/uvm_object_defines.svh
, these macros are defined as follows.
uvm_field_utils_begin
defines __m_uvm_field_automation
which calls super.__m_uvm_field_automation()
before the fields macros expand to switch-case for each of the operations.
`define uvm_field_utils_begin(T) \
function void __m_uvm_field_automation (uvm_object tmp_data__, \
int what__, \
string str__); \
begin \
T local_data__; /* Used for copy and compare */ \
typedef T ___local_type____; \
string string_aa_key; /* Used for associative array lookups */ \
uvm_object __current_scopes[$]; \
if(what__ inside {UVM_SETINT,UVM_SETSTR,UVM_SETOBJ}) begin \
if(__m_uvm_status_container.m_do_cycle_check(this)) begin \
return; \
end \
else \
__current_scopes=__m_uvm_status_container.m_uvm_cycle_scopes; \
end \
super.__m_uvm_field_automation(tmp_data__, what__, str__); \
/* Type is verified by uvm_object::compare() */ \
In the same file, uvm_field_int
defines several branches for difference operation. For UVM_SETINT
which we are interested in, we can see that it matches the name, and if it’s writable, it will assign to ARG
from uvm_object::__m_uvm_status_container.bitstream
`define uvm_field_int(ARG,FLAG) \
begin \
case (what__) \
...
...
UVM_SETINT: \
begin \
bit matched; \
__m_uvm_status_container.scope.set_arg(`"ARG`"); \
matched = uvm_is_match(str__, __m_uvm_status_container.scope.get()); \
if(matched) begin \
if((FLAG)&UVM_READONLY) begin \
uvm_report_warning("RDONLY", $sformatf("Readonly argument match %s is ignored", \
__m_uvm_status_container.get_full_scope_arg()), UVM_NONE); \
end \
else begin \
if (__m_uvm_status_container.print_matches) \
uvm_report_info("STRMTC", {"set_int()", ": Matched string ", str__, " to field ", __m_uvm_status_container.get_full_scope_arg()}, UVM_LOW); \
ARG = uvm_object::__m_uvm_status_container.bitstream; \
uvm_object::__m_uvm_status_container.status = 1; \
end \
end \
__m_uvm_status_container.scope.unset_arg(`"ARG`"); \
end \
endcase \
end
Let’s move to actual call side, __m_uvm_field_automation
is called from set_int_local
. uvm_object::__m_uvm_status_container.bitstream
is set to the value passed from the called. We will see it in a second.
function void uvm_object::set_int_local (string field_name,
uvm_bitstream_t value,
bit recurse=1);
__m_uvm_status_container.cycle_check.delete();
__m_uvm_status_container.m_uvm_cycle_scopes.delete();
this.__m_uvm_status_container.status = 0;
this.__m_uvm_status_container.bitstream = value;
__m_uvm_field_automation(null, UVM_SETINT, field_name);
set_local_int
is called from apply_config_settings
after looking up values from config_db. I am pasting the related code, but there is several lookups happening before the call. Read your UVM.
Note, value passed is the value passed read from the config db.
function void uvm_component::apply_config_settings (bit verbose=0);
...
...
begin
uvm_resource#(uvm_bitstream_t) rbs;
if($cast(rbs, r))
set_int_local(name, rbs.read(this));
else begin
uvm_resource#(int) ri;
if($cast(ri, r))
set_int_local(name, ri.read(this));
else begin
uvm_resource#(int unsigned) riu;
if($cast(riu, r))
set_int_local(name, riu.read(this));
apply_config_setting
is called by the build_phase
from the uvm_component.svh
. That’s it.
function void uvm_component::build_phase(uvm_phase phase);
m_build_done = 1;
build();
endfunction
// Backward compatibility build function
function void uvm_component::build();
m_build_done = 1;
apply_config_settings(print_config_matches);
if(m_phasing_active == 0) begin
uvm_report_warning("UVM_DEPRECATED", "build()/build_phase() has been called explicitly, outside of the phasing system. This usage of build is deprecated and may lead to unexpected behavior.");
end
endfunction
Fin.