The defines which makes
our job much easier which are a part of UVM, they are evil if we consider the
lines of code it generates when we expand the macro and the simulation time it
takes.
Say for a data class
which has 2 variables, m_a,m_b we usually write the data class as below:
class data extends
uvm_data_item;
rand bit m_a;
rand int
m_b;
`uvm_object_utils_begin(data)
`uvm_field_int(m_a)
`uvm_field_int(m_b)
`uvm_object_utils_end
endclass:data
The following two macros
do defining of functions like create, and registering with factory (as given
below)
`uvm_object_utils_begin(data)
`uvm_object_utils_end
And the field macros “uvm_field_*”
implements all the functions of data operations such as check_fields,copy, compare,
pack, unpack, print, setint. All these functions we may not use always and also
if we need to modify any of these functions we will write the custom code in
the methods do_copy,do_compare… so these macros just creates a whole lot of code
(each time a macro is called it creates a case statement as shown below) which
may not be required always (I have used copy, compare most of the times and
pack, unpack few times and whenever I have used compare its mostly custom
method)
Every time `uvm_field_int
is written the entire case statement at <3> is called which is about 100
lines of code, for the two variables m_a, m_b we have in the above data class
the macro adds 200 lines of redundant code if the macros are expanded (assuming
you are not using any of the built in functions and you are writing custom
functions where ever required) and say
if you have 100 variables then it becomes 10000 lines of code if the macro is
expanded, which severely affects the simulation performance. 3>
Defines and functions I have
used in writing above comment
=============================================================
`define
uvm_object_utils_begin(T) \
`m_uvm_register_converter(T)
\
`m_uvm_object_registry_internal(T,T) \
`m_uvm_object_create_func(T) \
`m_uvm_get_type_name_func(T) \
`uvm_field_utils_begin(T)
---------------------------------------------- 1
=============================================================
`define
uvm_field_utils_begin(T) \ ----------------------------------------------------
1
function
void __m_uvm_field_automation (uvm_object tmp_data__, \
int what__, \
string str__); \
------------------------------------------------- 2
begin \
T
local_data__; /* Used for copy and compare */ \
typedef T ___local_type____; \
string string_aa_key; /* Used for associative array lookups */ \
/*
Type is verified by uvm_object::compare() */ \
super.__m_uvm_field_automation(tmp_data__,
what__, str__); \
if(tmp_data__ != null) \
/* Allow objects in same hierarchy to be copied/compared */ \
if(!$cast(local_data__, tmp_data__)) return;
=============================================================
`define
uvm_field_int(ARG,FLAG) \ ----------------------------------------------- 3
case (what__) \
UVM_CHECK_FIELDS: \
UVM_COPY: \
begin \
if(local_data__ == null) return; \
if(!((FLAG)&UVM_NOCOPY)) ARG = local_data__.ARG; \
end \
UVM_COMPARE: \
.....
UVM_PACK: \
.......
UVM_UNPACK: \
......
UVM_RECORD: \
...........
UVM_PRINT: \
...........
UVM_SETINT: \
.......
=============================================================
`define
uvm_object_utils_end \
end
\
endfunction
\
=============================================================
// copy function as in
uvm_object.sv
// ----
function void
uvm_object::copy (uvm_object rhs);
//For cycle
checking
static int depth;
if((rhs !=null)
&& (uvm_global_copy_map.get(rhs) != null)) begin
return;
end
if(rhs==null)
begin
uvm_report_warning("NULLCP", "A null object was supplied to
copy; copy is ignored", UVM_NONE);
return;
end
uvm_global_copy_map.set(rhs, this);
++depth;
__m_uvm_field_automation(rhs, UVM_COPY,
"");
---------------------------------- 2
do_copy(rhs);
--------------------------------------------------------------------------------
3
--depth;
if(depth==0)
begin
uvm_global_copy_map.clear();
end
endfunction
=============================================================
// do_copy
// -------
function void
uvm_object::do_copy (uvm_object rhs);
return;
endfunction
=============================================================
1 is where the uvm_field_utils_egin is called as a
part of uvm_object_utils_begin
2 is where the function “__m_uvm_field_automation”
is called inside copy function.
3 is where user function do_copy is called as a part
of copy function after the function call “__m_uvm_field_automation”
inside copy function.
NOTE : if you are sure that you are going to use most of the functions as is then using macros reduces a lot of code user needs to write but we need to use these with caution if we are concerned about simulation performance.
Side note: the do_copy method is called in copy function after __m_uvm_field_automation is called, so if no_copy is not provided as a argument then that function is called initially followed by do_copy, if you implement custom do_copy method we should use NO_COPY argument so that the function __m_uvm_field_automation is not called and only do_copy is called.
Side note: the do_copy method is called in copy function after __m_uvm_field_automation is called, so if no_copy is not provided as a argument then that function is called initially followed by do_copy, if you implement custom do_copy method we should use NO_COPY argument so that the function __m_uvm_field_automation is not called and only do_copy is called.
No comments:
Post a Comment