This post will explain user-definable do_*
hook functions. In Field Macros, we saw that the standard data methods, such as copy()
and compare()
, called the user-definable hook functions, such as do_copy()
and do_compare()
. I will define these hook functions in this post.
Jelly Bean Transaction Class with “do” Functions
Let’s add the “do
” functions to the jelly_bean_transaction
class.
do_copy
The do_copy()
method is called by the copy()
method. The do_copy()
method is used to copy all the properties of a jelly_bean_transaction
object (lines 10 to 14). Note that we have to cast a uvm_object
(rhs
) to a jelly_bean_transaction
(that
) in order to access the properties of the jelly_bean_transaction
object (line 4). We must call the super.do_copy()
to copy the properties defined in the super class (line 9).
virtual function void do_copy( uvm_object rhs );
jelly_bean_transaction that;
if ( ! $cast( that, rhs ) ) begin
`uvm_error( get_name(), "rhs is not a jelly_bean_transaction" )
return;
end
super.do_copy( rhs );
this.flavor = that.flavor;
this.color = that.color;
this.sugar_free = that.sugar_free;
this.sour = that.sour;
this.taste = that.taste;
endfunction: do_copy
do_compare
The do_compare()
method is called by the compare()
method. The do_compare()
is used to compare each property of the jelly_bean_transaction
object. The do_compare()
returns 1
if the comparison succeeds, and returns 0
if the comparison fails (lines 6 to 11). Note that we have to cast a uvm_object
(rhs
) to a jelly_bean_transaction
(that
) again in order to access the properties of the jelly_bean_transaction
object (line 4). We must call the super.do_compare()
to compare the properties of the super class (line 6). The uvm_comparer
argument provides a policy object for doing comparisons, but we do not use it.
virtual function bit do_compare( uvm_object rhs, uvm_comparer comparer );
jelly_bean_transaction that;
if ( ! $cast( that, rhs ) ) return 0;
return ( super.do_compare( rhs, comparer ) &&
this.flavor == that.flavor &&
this.color == that.color &&
this.sugar_free == that.sugar_free &&
this.sour == that.sour &&
this.taste == that.taste );
endfunction: do_compare
do_pack
The do_pack()
method is called by the pack()
, pack_bytes()
, and pack_ints()
methods. The do_pack()
is used to pack each propery of the jelly_bean_transaction
object using a uvm_packer
policy object. Please see Register Abstraction for how each property is packed. The packer
determines how the packing should be done. We must call the super.do_pack()
to pack the properties of the super class (line 5).
virtual function void do_pack( uvm_packer packer );
bit R1; // reserved bit
bit [5:0] R6; // reserved bits
super.do_pack( packer );
packer.pack_field_int( .value( flavor ), .size( 3 ) );
packer.pack_field_int( .value( color ), .size( 2 ) );
packer.pack_field_int( .value( sugar_free ), .size( 1 ) );
packer.pack_field_int( .value( sour ), .size( 1 ) );
packer.pack_field_int( .value( R1 ), .size( 1 ) );
packer.pack_field_int( .value( taste ), .size( 2 ) );
packer.pack_field_int( .value( R6 ), .size( 6 ) );
endfunction: do_pack
do_unpack
The do_unpack()
method is called by the unpack()
, unpack_bytes()
, and unpack_ints()
methods. The do_unpack()
is used to unpack each property of the jelly_bean_transaction
object using a uvm_packer
policy object. The packer
determines how the unpacking should be done. We must call the super.do_unpack()
to unpack the properties of the super class (line 5).
virtual function void do_unpack( uvm_packer packer );
bit R1; // reserved bit
bit [5:0] R6; // reserved bits
super.do_unpack( packer );
flavor = flavor_e'( packer.unpack_field_int( .size( 3 ) ) );
color = color_e '( packer.unpack_field_int( .size( 2 ) ) );
sugar_free = packer.unpack_field_int( .size( 1 ) );
sour = packer.unpack_field_int( .size( 1 ) );
R1 = packer.unpack_field_int( .size( 1 ) );
taste = taste_e '( packer.unpack_field_int( .size( 2 ) ) );
R6 = packer.unpack_field_int( .size( 6 ) );
endfunction: do_unpack
convert2string
The convert2string()
method is called by the user to provide object information in the form of a string. The convert2string()
is used to convert each property of the jelly_bean_transaction
object into a string. We should call the super.convert2string()
to convert the properties of the super class into the string (line 2).
virtual function string convert2string();
string s = super.convert2string();
s = { s, $psprintf( "\nname : %s", get_name() ) };
s = { s, $psprintf( "\nflavor : %s", flavor.name() ) };
s = { s, $psprintf( "\ncolor : %s", color.name() ) };
s = { s, $psprintf( "\nsugar_free: %b", sugar_free ) };
s = { s, $psprintf( "\nsour : %b", sour ) };
s = { s, $psprintf( "\ntaste : %s", taste.name() ) };
return s;
endfunction: convert2string
Test the “do” Hooks
Let’s test the “do
” hooks. We will define the run_phase()
task of the jelly_bean_test
class as follows.
- Create three
jelly_bean_transaction
s;jb_tx1
,jb_tx2
andjb_tx3
(lines 11 to 13). - Randomize the
jb_tx1
(line 14). - Copy the properties of the
jb_tx1
tojb_tx2
(line 18). - Copy the properties of the
jb_tx1
tojb_tx3
, but using thepack()
andunpack()
methods instead of calling thecopy()
method (lines 24 and 25). - Now the
jb_tx1
,jb_tx2
, andjb_tx3
should have the same property values. Verify it using thecompare()
method (lines 29 to 39). - Print the properties of the
jb_tx1
,jb_tx2
, andjb_tx3
using theconvert2string()
method to visually verify the property values (lines 43 to 45).
task run_phase( uvm_phase phase );
jelly_bean_transaction jb_tx1;
jelly_bean_transaction jb_tx2;
jelly_bean_transaction jb_tx3;
uvm_packer jb_packer;
bit bitstream[];
int num_bits;
phase.raise_objection( .obj( this ) );
jb_tx1 = jelly_bean_transaction::type_id::create( "jb_tx1" );
jb_tx2 = jelly_bean_transaction::type_id::create( "jb_tx2" );
jb_tx3 = jelly_bean_transaction::type_id::create( "jb_tx3" );
assert( jb_tx1.randomize() );
// copy jb_tx1 to jb_tx2
jb_tx2.copy( jb_tx1 );
// create jb_tx3 by packing and unpacking jb_tx1
jb_packer = new;
jb_packer.big_endian = 0;
num_bits = jb_tx1.pack ( bitstream, jb_packer );
num_bits = jb_tx3.unpack( bitstream, jb_packer );
// check if jb_tx1, jb_tx2 and jb_tx3 have the same properties
if ( jb_tx1.compare( jb_tx2 ) ) begin
`uvm_info( get_name(), "jb_tx1 and jb_tx2 matched", UVM_NONE )
end else begin
`uvm_error( get_name(), "jb_tx1 and jb_tx2 mismatched" )
end
if ( jb_tx2.compare( jb_tx3 ) ) begin
`uvm_info( get_name(), "jb_tx2 and jb_tx3 matched", UVM_NONE )
end else begin
`uvm_error( get_name(), "jb_tx2 and jb_tx3 mismatched" )
end
// print each object
`uvm_info( get_name(), jb_tx1.convert2string(), UVM_NONE )
`uvm_info( get_name(), jb_tx2.convert2string(), UVM_NONE )
`uvm_info( get_name(), jb_tx3.convert2string(), UVM_NONE )
phase.drop_objection( .obj( this ) );
endtask: run_phase
You might have noticed that we created a uvm_packer
object (jb_packer
) on line 22 and set its big_endian
property to 0
(line 23). We used this packer when we pack and unpack the jelly_bean_transaction
(lines 24 and 25). This is to make sure we pack each property value in little endian as we did in Register Abstraction. If you just want to pack and unpack and don’t care about the bitstream representation, you don’t have to create the uvm_packer
object. If you don’t specify the uvm_packer
, the global uvm_default_packer
policy will be used, of which the value of big_endian
is 1
. The following diagram shows how the value of big_endian
affects the bitstream representation. The m_bits
is a property of the uvm_packer
and it represents the packed bitstream in the form of a bit
array.
Pack in little endian and in big endian
Simulation
Here is a simulation result. As you see, all three jelly_bean_transaction
s have same property values.
UVM_INFO jb15.sv(589) @ 0: uvm_test_top [uvm_test_top] jb_tx1 and jb_tx2 matched
UVM_INFO jb15.sv(595) @ 0: uvm_test_top [uvm_test_top] jb_tx2 and jb_tx3 matched
UVM_INFO jb15.sv(602) @ 0: uvm_test_top [uvm_test_top]
name : jb_tx1
flavor : CHOCOLATE
color : RED
sugar_free: 1
sour : 0
taste : UNKNOWN
UVM_INFO jb15.sv(603) @ 0: uvm_test_top [uvm_test_top]
name : jb_tx2
flavor : CHOCOLATE
color : RED
sugar_free: 1
sour : 0
taste : UNKNOWN
UVM_INFO jb15.sv(604) @ 0: uvm_test_top [uvm_test_top]
name : jb_tx3
flavor : CHOCOLATE
color : RED
sugar_free: 1
sour : 0
taste : UNKNOWN