目录
6.1 UVM Utility Macros and field macros
6.1.2 `uvm_field_sarray_* macros
6.1.3 `uvm_field_array_* macros
6.2 Code with `uvm_object_utils
6.3 Code with `uvm_object_utils_begin and `uvm_object_utils_end
6.4.2 print method with `uvm_object_utils
6.4.3.1 do_print() method example
6.5 Copy and clone methods in UVM
6.5.2.1 do_copy method example
6.6.2.1 do_compare method example
6.7 Pack and Unpack methods in UVM
6.7.1 pack and unpack methods example
6.7.2 do_pack and do_unpack methods in UVM
6.7.2.1 do_pack and do_unpack methods example
uvm_object类是所有uvm层次类的基类,如uvm_report_object、uvm_component、uvm_transaction、uvm_sequence_item、uvm_sequence等。它在定义一组方法(如create, copy, print, clone, compare, record等)方面起着重要作用。
6.1 UVM Utility Macros and field macros
我们在UVM factory章节已经看到了“create”方法是如何工作的,“create”方法为对象分配内存空间并返回相同类型的句柄。
`uvm_object_utils或`uvm_abject_utils_begin`uvm_object_utils_end宏用于在uvm工厂中注册uvm_object和其他派生类型,如uvm_transaction、uvm_sequece_items。
UVM字段宏(field macros)提供了 create, copy, print, clone, compare, record等方法的实现。工厂中有不同的`uvm_field_*宏可用于各种数据类型变量的注册。`uvm_field_*宏至少接受两个参数作为arg(与`uvm_field_*宏兼容的变量的实例名)和flag(用作添加相应数据方法的控制机制)。
new()方法很重要,可以用相应的类名作为扩充来定义。
注:在编译期间,这些UVM自动化宏扩展了相应宏可用的完整代码。
Syntax without field macros:
`uvm_object_utils(<class Type>)
Syntax with field macros:
`uvm_object_utils_begin(<class_type>)
`uvm_field_*(<arg>, <flag>)
`uvm_object_utils_end
以下字段宏通常用于标量/动态类属性的数据方法[data methods](copy, compare, pack, unpack, print, clone, 等)。可以从UVM参考文件中研究完整列表。
6.1.1 `uvm_field_* macros
`uvm_field_*宏实现标量属性的数据方法。
6.1.2 `uvm_field_sarray_* macros
`uvm_field_sarray*宏实现一维静态数组属性的数据方法。
6.1.3 `uvm_field_array_* macros
uvm_field_array*宏实现一维动态数组属性的数据方法。
6.1.4 `uvm_field_* macro flag
也可以指定打印的进制。默认是16进制HEX。
6.2 Code with `uvm_object_utils
typedef enum{RED, GREEN, BLUE} color_type;
class my_object extends uvm_object;
int o_var;
string o_name;
color_type colors;
byte data[4];
bit [7:0] addr;
`uvm_object_utils(my_object)
function new(string name = "my_object");
super.new(name);
endfunction
endclass
6.3 Code with `uvm_object_utils_begin and `uvm_object_utils_end
typedef enum{RED, GREEN, BLUE} color_type;
class my_object extends uvm_object;
rand int value;
string names;
rand color_type colors;
rand byte data[4];
rand bit [7:0] addr;
`uvm_object_utils_begin(my_object)
`uvm_field_int(value, UVM_ALL_ON)
`uvm_field_string(names, UVM_ALL_ON)
`uvm_field_enum(color_type, colors, UVM_ALL_ON)
`uvm_field_sarray_int(data, UVM_ALL_ON)
`uvm_field_int(addr, UVM_ALL_ON)
`uvm_object_utils_end
function new(string name = "my_object");
super.new(name);
endfunction
endclass
6.4 UVM中的打印方法
打印方法用于以格式良好的方式深度打印UVM对象类的属性。需要根据类属性的数据类型使用适当的`uvm_field_*宏。
注意:sprint()方法与print()方法相同,不同的是sprint()方法以字符串格式打印对象。
6.4.1 打印方法示例
typedef enum{RED, GREEN, BLUE} color_type;
class temp_class extends uvm_object;
rand bit [7:0] tmp_addr;
rand bit [7:0] tmp_data;
function new(string name = "temp_class");
super.new(name);
endfunction
`uvm_object_utils_begin(temp_class)
`uvm_field_int(tmp_addr, UVM_ALL_ON)
`uvm_field_int(tmp_data, UVM_ALL_ON)
`uvm_object_utils_end
endclass
class my_object extends uvm_object;
rand int value;
string names;
rand color_type colors;
rand byte data[4];
rand bit [7:0] addr;
rand temp_class tmp;
`uvm_object_utils_begin(my_object)
`uvm_field_int(value, UVM_ALL_ON)
`uvm_field_string(names, UVM_ALL_ON)
`uvm_field_enum(color_type, colors, UVM_ALL_ON)
`uvm_field_sarray_int(data, UVM_ALL_ON)
`uvm_field_int(addr, UVM_ALL_ON)
`uvm_field_object(tmp, UVM_ALL_ON)
`uvm_object_utils_end
function new(string name = "my_object");
super.new(name);
tmp = new();
this.names = "UVM";
endfunction
endclass
class my_test extends uvm_test;
`uvm_component_utils(my_test)
my_object obj;
bit packed_data_bits[];
byte unsigned packed_data_bytes[];
int unsigned packed_data_ints[];
my_object unpack_obj;
function new(string name = "my_test", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
obj = my_object::type_id::create("obj", this);
assert(obj.randomize());
obj.print();
// or
//`uvm_info(get_full_name(), $sformatf("obj = \n%s", obj.sprint()), UVM_LOW);
endfunction
endclass
module tb_top;
initial begin
run_test("my_test");
end
endmodule
Output:
UVM_INFO @ 0: reporter [RNTST] Running test my_test...
--------------------------------------------
Name Type Size Value
--------------------------------------------
obj my_object - @349
value integral 32 'h1f135537
names string 3 UVM
colors color_type 32 GREEN
data sa(integral) 4 -
[0] integral 8 'h9f
[1] integral 8 'h33
[2] integral 8 'h12
[3] integral 8 'h9c
addr integral 8 'h2f
tmp temp_class - @350
tmp_addr integral 8 'h39
tmp_data integral 8 'hbd
--------------------------------------------
6.4.2 print method with `uvm_object_utils
如果print方法与`uvm_object_utils一起使用,则不会打印类属性。
typedef enum{RED, GREEN, BLUE} color_type;
class my_object extends uvm_object;
rand int o_var;
string o_name;
rand color_type colors;
rand byte data[4];
rand bit [7:0] addr;
`uvm_object_utils(my_object)
function new(string name = "my_object");
super.new(name);
endfunction
endclass
class my_test extends uvm_test;
`uvm_component_utils(my_test)
my_object obj;
function new(string name = "my_test", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
obj = my_object::type_id::create("obj", this);
assert(obj.randomize());
obj.print();
endfunction
function void end_of_elaboration_phase(uvm_phase phase);
super.end_of_elaboration_phase(phase);
uvm_top.print_topology();
endfunction
endclass
module tb_top;
initial begin
run_test("my_test");
end
endmodule
Output:
UVM_INFO @ 0: reporter [RNTST] Running test my_test...
----------------------------
Name Type Size Value
----------------------------
obj my_object - @1872
----------------------------
UVM_INFO /xcelium20.09/tools//methodology/UVM/CDNS-1.2/sv/src/base/uvm_root.svh(605) @ 0: reporter [UVMTOP] UVM testbench topology:
----------------------------------
Name Type Size Value
----------------------------------
uvm_test_top my_test - @1805
----------------------------------
6.4.3 do_print() method
UVM自动化宏主要涉及许多影响仿真器性能的附加代码。因此,不建议使用。相反,do_print()回调方法是一个用户定义的钩子,由print()或sprint()方法调用。用户必须调用在do_print()实现的printer API来添加要打印的信息。
6.4.3.1 do_print() method example
typedef enum{RED, GREEN, BLUE} color_type;
class temp_class extends uvm_object;
rand bit [7:0] tmp_addr;
rand bit [7:0] tmp_data;
function new(string name = "temp_class");
super.new(name);
endfunction
`uvm_object_utils(temp_class)
function void do_print(uvm_printer printer);
super.do_print(printer);
printer.print_field_int("tmp_addr", tmp_addr, $bits(tmp_addr), UVM_HEX);
printer.print_field_int("tmp_data", tmp_data, $bits(tmp_data), UVM_HEX);
endfunction
endclass
class my_object extends uvm_object;
rand int value;
string names = "UVM";
rand color_type colors;
rand byte data[4];
rand bit [7:0] addr;
rand temp_class tmp;
`uvm_object_utils(my_object)
function new(string name = "my_object");
super.new(name);
tmp = new();
endfunction
function void do_print(uvm_printer printer);
super.do_print(printer);
printer.print_field_int("value", value, $bits(value), UVM_HEX);
printer.print_string("names", names);
printer.print_string("colors", colors.name);
foreach(data[i])
printer.print_field_int($sformatf("data[%0d]", i), data[i], $bits(data[i]), UVM_HEX);
printer.print_field_int("addr", addr, $bits(addr), UVM_HEX);
printer.print_object("tmp", tmp);
endfunction
endclass
class my_test extends uvm_test;
`uvm_component_utils(my_test)
my_object obj;
function new(string name = "my_test", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
obj = my_object::type_id::create("obj", this);
assert(obj.randomize());
obj.print();
endfunction
endclass
module tb_top;
initial begin
run_test("my_test");
end
endmodule
Output:
UVM_INFO @ 0: reporter [RNTST] Running test my_test...
------------------------------------------
Name Type Size Value
------------------------------------------
obj my_object - @1876
value integral 32 'ha4a4f87e
names string 3 UVM
colors string 3 RED
data[0] integral 8 'hc6
data[1] integral 8 'h4c
data[2] integral 8 'hf
data[3] integral 8 'h89
addr integral 8 'h53
tmp temp_class - @1878
tmp_addr integral 8 'hea
tmp_data integral 8 'hdf
------------------------------------------
6.5 Copy and clone methods in UVM
6.5.1 copy method in UVM
copy()方法是深度复制(deep copy)。
6.5.1.1 copy method example
typedef enum{RED, GREEN, BLUE} color_type;
class temp_class extends uvm_object;
rand bit [7:0] tmp_addr;
rand bit [7:0] tmp_data;
function new(string name = "temp_class");
super.new(name);
endfunction
`uvm_object_utils_begin(temp_class)
`uvm_field_int(tmp_addr, UVM_ALL_ON)
`uvm_field_int(tmp_data, UVM_ALL_ON)
`uvm_object_utils_end
endclass
class my_object extends uvm_object;
rand int value;
string names;
rand color_type colors;
rand byte data[4];
rand bit [7:0] addr;
rand temp_class tmp;
`uvm_object_utils_begin(my_object)
`uvm_field_int(value, UVM_ALL_ON)
`uvm_field_string(names, UVM_ALL_ON)
`uvm_field_enum(color_type, colors, UVM_ALL_ON)
`uvm_field_sarray_int(data, UVM_ALL_ON)
`uvm_field_int(addr, UVM_ALL_ON)
`uvm_field_object(tmp, UVM_ALL_ON)
`uvm_object_utils_end
function new(string name = "my_object");
super.new(name);
tmp = new();
this.names = "UVM";
endfunction
endclass
class my_test extends uvm_test;
`uvm_component_utils(my_test)
my_object obj_A, obj_B;
bit packed_data_bits[];
byte unsigned packed_data_bytes[];
int unsigned packed_data_ints[];
my_object unpack_obj;
function new(string name = "my_test", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
obj_A = my_object::type_id::create("obj_A", this);
obj_B = my_object::type_id::create("obj_B", this);
assert(obj_A.randomize());
assert(obj_B.randomize());
`uvm_info(get_full_name(), $sformatf("Before copying: obj_A = \n%s and obj_B = \n%s", obj_A.sprint(), obj_B.sprint()), UVM_LOW);
obj_B.copy(obj_A);
`uvm_info(get_full_name(), $sformatf("After copying: obj_A = \n%s and obj_B = \n%s", obj_A.sprint(), obj_B.sprint()), UVM_LOW);
endfunction
endclass
module tb_top;
initial begin
run_test("my_test");
end
endmodule
Output:
可见copy()后obj_B和obj_A完全一样。
UVM_INFO testbench.sv(65) @ 0: uvm_test_top [uvm_test_top] Before copying: obj_A =
--------------------------------------------
Name Type Size Value
--------------------------------------------
obj_A my_object - @349
value integral 32 'h1f135537
names string 3 UVM
colors color_type 32 GREEN
data sa(integral) 4 -
[0] integral 8 'h9f
[1] integral 8 'h33
[2] integral 8 'h12
[3] integral 8 'h9c
addr integral 8 'h2f
tmp temp_class - @350
tmp_addr integral 8 'h39
tmp_data integral 8 'hbd
--------------------------------------------
and obj_B =
--------------------------------------------
Name Type Size Value
--------------------------------------------
obj_B my_object - @351
value integral 32 'he96c3deb
names string 3 UVM
colors color_type 32 RED
data sa(integral) 4 -
[0] integral 8 'hcb
[1] integral 8 'h49
[2] integral 8 'hcc
[3] integral 8 'h49
addr integral 8 'h6d
tmp temp_class - @352
tmp_addr integral 8 'h66
tmp_data integral 8 'h27
--------------------------------------------
UVM_INFO testbench.sv(67) @ 0: uvm_test_top [uvm_test_top] After copying: obj_A =
--------------------------------------------
Name Type Size Value
--------------------------------------------
obj_A my_object - @349
value integral 32 'h1f135537
names string 3 UVM
colors color_type 32 GREEN
data sa(integral) 4 -
[0] integral 8 'h9f
[1] integral 8 'h33
[2] integral 8 'h12
[3] integral 8 'h9c
addr integral 8 'h2f
tmp temp_class - @350
tmp_addr integral 8 'h39
tmp_data integral 8 'hbd
--------------------------------------------
and obj_B =
--------------------------------------------
Name Type Size Value
--------------------------------------------
obj_B my_object - @351
value integral 32 'h1f135537
names string 3 UVM
colors color_type 32 GREEN
data sa(integral) 4 -
[0] integral 8 'h9f
[1] integral 8 'h33
[2] integral 8 'h12
[3] integral 8 'h9c
addr integral 8 'h2f
tmp temp_class - @355
tmp_addr integral 8 'h39
tmp_data integral 8 'hbd
--------------------------------------------
6.5.2 do_copy method
do_copy()回调
方法是由copy()方法
调用的一个用户定义的hook。派生类应覆盖 uvm_object_utils_begin, uvm_object_utils_end
并且`uvm_field_*
不使用宏。
6.5.2.1 do_copy method example
`include "uvm_macros.svh"
import uvm_pkg::*;
typedef enum{RED, GREEN, BLUE} color_type;
class temp_class extends uvm_object;
rand bit [7:0] tmp_addr;
rand bit [7:0] tmp_data;
function new(string name = "temp_class");
super.new(name);
endfunction
`uvm_object_utils(temp_class)
function void do_copy(uvm_object local_h);
temp_class tmp_h;
super.do_copy(local_h);
// $cast is necessary: uvm_object local_h do not have temp_class properties (tmp_addr and tmp_data)
// temp_class is extended from uvm_object, so child class temp_class handle is required for copying each property.
$cast(tmp_h, local_h);
tmp_addr = tmp_h.tmp_addr;
tmp_data = tmp_h.tmp_data;
endfunction
endclass
class my_object extends uvm_object;
rand int value;
string names;
rand color_type colors;
rand byte data[4];
rand bit [7:0] addr;
rand temp_class tmp;
`uvm_object_utils(my_object)
function new(string name = "my_object");
super.new(name);
tmp = new();
endfunction
function void do_copy(uvm_object local_h);
my_object my_obj;
super.do_copy(local_h);
$cast(my_obj, local_h);
value = my_obj.value;
names = my_obj.names;
colors= my_obj.colors;
data = my_obj.data;
addr = my_obj.addr;
tmp.copy(my_obj.tmp);
endfunction
endclass
class my_test extends uvm_test;
`uvm_component_utils(my_test)
my_object obj_A, obj_B;
function new(string name = "my_test", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
obj_A = my_object::type_id::create("obj_A", this);
obj_B = my_object::type_id::create("obj_B", this);
assert(obj_A.randomize());
assert(obj_B.randomize());
`uvm_info(get_full_name(), "Before copying", UVM_LOW);
obj_print(obj_A);
obj_print(obj_B);
obj_B.copy(obj_A);
`uvm_info(get_full_name(), "After copying", UVM_LOW);
obj_print(obj_B);
endfunction
function void obj_print(uvm_object obj);
my_object my_obj;
string out;
$cast(my_obj, obj);
$display("-----------------------------");
$display("---------- %s ----------", my_obj.get_name);
$display("-----------------------------");
$sformat(out, "value = %0h, names = %s, addr = %0h", my_obj.value, my_obj.names, my_obj.addr);
`uvm_info(get_full_name(), $sformatf("%s", out), UVM_LOW);
foreach(my_obj.data[i]) `uvm_info(get_full_name(), $sformatf("data[%0d] = %h", i, my_obj.data[i]), UVM_LOW);
$sformat(out, "tmp_addr = %0h, tmp_data = %0h", my_obj.tmp.tmp_addr, my_obj.tmp.tmp_data);
`uvm_info(get_full_name(), $sformatf("tmp: %s", out), UVM_LOW);
endfunction
endclass
module tb_top;
initial begin
run_test("my_test");
end
endmodule
Output:
UVM_INFO testbench.sv(69) @ 0: uvm_test_top [uvm_test_top] Before copying
-----------------------------
---------- obj_A ----------
-----------------------------
UVM_INFO testbench.sv(85) @ 0: uvm_test_top [uvm_test_top] value = 1f135537, names = , addr = 2f
UVM_INFO testbench.sv(86) @ 0: uvm_test_top [uvm_test_top] data[0] = 9f
UVM_INFO testbench.sv(86) @ 0: uvm_test_top [uvm_test_top] data[1] = 33
UVM_INFO testbench.sv(86) @ 0: uvm_test_top [uvm_test_top] data[2] = 12
UVM_INFO testbench.sv(86) @ 0: uvm_test_top [uvm_test_top] data[3] = 9c
UVM_INFO testbench.sv(88) @ 0: uvm_test_top [uvm_test_top] tmp: tmp_addr = 39, tmp_data = bd
-----------------------------
---------- obj_B ----------
-----------------------------
UVM_INFO testbench.sv(85) @ 0: uvm_test_top [uvm_test_top] value = e96c3deb, names = , addr = 6d
UVM_INFO testbench.sv(86) @ 0: uvm_test_top [uvm_test_top] data[0] = cb
UVM_INFO testbench.sv(86) @ 0: uvm_test_top [uvm_test_top] data[1] = 49
UVM_INFO testbench.sv(86) @ 0: uvm_test_top [uvm_test_top] data[2] = cc
UVM_INFO testbench.sv(86) @ 0: uvm_test_top [uvm_test_top] data[3] = 49
UVM_INFO testbench.sv(88) @ 0: uvm_test_top [uvm_test_top] tmp: tmp_addr = 66, tmp_data = 27
UVM_INFO testbench.sv(73) @ 0: uvm_test_top [uvm_test_top] After copying
-----------------------------
---------- obj_B ----------
-----------------------------
UVM_INFO testbench.sv(85) @ 0: uvm_test_top [uvm_test_top] value = 1f135537, names = , addr = 2f
UVM_INFO testbench.sv(86) @ 0: uvm_test_top [uvm_test_top] data[0] = 9f
UVM_INFO testbench.sv(86) @ 0: uvm_test_top [uvm_test_top] data[1] = 33
UVM_INFO testbench.sv(86) @ 0: uvm_test_top [uvm_test_top] data[2] = 12
UVM_INFO testbench.sv(86) @ 0: uvm_test_top [uvm_test_top] data[3] = 9c
UVM_INFO testbench.sv(88) @ 0: uvm_test_top [uvm_test_top] tmp: tmp_addr = 39, tmp_data = bd
6.5.3 clone method in UVM
clone 方法调用 create() 方法,然后调用 copy()。因此,它创建并返回对象的副本。
`include "uvm_macros.svh"
import uvm_pkg::*;
typedef enum{RED, GREEN, BLUE} color_type;
class temp_class extends uvm_object;
rand bit [7:0] tmp_addr;
rand bit [7:0] tmp_data;
function new(string name = "temp_class");
super.new(name);
endfunction
`uvm_object_utils_begin(temp_class)
`uvm_field_int(tmp_addr, UVM_ALL_ON)
`uvm_field_int(tmp_data, UVM_ALL_ON)
`uvm_object_utils_end
endclass
class my_object extends uvm_object;
rand int value;
string names;
rand color_type colors;
rand byte data[4];
rand bit [7:0] addr;
rand temp_class tmp;
`uvm_object_utils_begin(my_object)
`uvm_field_int(value, UVM_ALL_ON)
`uvm_field_string(names, UVM_ALL_ON)
`uvm_field_enum(color_type, colors, UVM_ALL_ON)
`uvm_field_sarray_int(data, UVM_ALL_ON)
`uvm_field_int(addr, UVM_ALL_ON)
`uvm_field_object(tmp, UVM_ALL_ON)
`uvm_object_utils_end
function new(string name = "my_object");
super.new(name);
tmp = new();
endfunction
endclass
class my_test extends uvm_test;
`uvm_component_utils(my_test)
my_object obj_A, obj_B;
function new(string name = "my_test", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
obj_A = my_object::type_id::create("obj_A", this);
assert(obj_A.randomize());
if(obj_B == null) `uvm_info(get_full_name(), "obj_B is not created", UVM_LOW);
$cast(obj_B, obj_A.clone());
`uvm_info(get_full_name(), $sformatf("AFter clone:\n obj_A = \n%s and obj_B = \n%s", obj_A.sprint(), obj_B.sprint()), UVM_LOW);
endfunction
endclass
module tb_top;
initial begin
run_test("my_test");
end
endmodule
Output:
UVM_INFO testbench.sv(55) @ 0: uvm_test_top [uvm_test_top] obj_B is not created
UVM_INFO testbench.sv(57) @ 0: uvm_test_top [uvm_test_top] AFter clone:
obj_A =
--------------------------------------------
Name Type Size Value
--------------------------------------------
obj_A my_object - @1877
value integral 32 'ha4a4f87e
names string 0 ""
colors color_type 32 RED
data sa(integral) 4 -
[0] integral 8 'hc6
[1] integral 8 'h4c
[2] integral 8 'hf
[3] integral 8 'h89
addr integral 8 'h53
tmp temp_class - @1878
tmp_addr integral 8 'hea
tmp_data integral 8 'hdf
--------------------------------------------
and obj_B =
--------------------------------------------
Name Type Size Value
--------------------------------------------
obj_A my_object - @1881
value integral 32 'ha4a4f87e
names string 0 ""
colors color_type 32 RED
data sa(integral) 4 -
[0] integral 8 'hc6
[1] integral 8 'h4c
[2] integral 8 'hf
[3] integral 8 'h89
addr integral 8 'h53
tmp temp_class - @1852
tmp_addr integral 8 'hea
tmp_data integral 8 'hdf
--------------------------------------------
6.6 compare method in UVM
如果两个object的所有参数都一样,则compare返回1。这是深比较(deep compare)。
6.6.1 compare method example
`include "uvm_macros.svh"
import uvm_pkg::*;
typedef enum{RED, GREEN, BLUE} color_type;
class temp_class extends uvm_object;
rand bit [7:0] tmp_addr;
rand bit [7:0] tmp_data;
function new(string name = "temp_class");
super.new(name);
endfunction
`uvm_object_utils_begin(temp_class)
`uvm_field_int(tmp_addr, UVM_ALL_ON)
`uvm_field_int(tmp_data, UVM_ALL_ON)
`uvm_object_utils_end
endclass
class my_object extends uvm_object;
rand int value;
string names;
rand color_type colors;
rand byte data[4];
rand bit [7:0] addr;
rand temp_class tmp;
`uvm_object_utils_begin(my_object)
`uvm_field_int(value, UVM_ALL_ON)
`uvm_field_string(names, UVM_ALL_ON)
`uvm_field_enum(color_type, colors, UVM_ALL_ON)
`uvm_field_sarray_int(data, UVM_ALL_ON)
`uvm_field_int(addr, UVM_ALL_ON)
`uvm_field_object(tmp, UVM_ALL_ON)
`uvm_object_utils_end
function new(string name = "my_object");
super.new(name);
tmp = new();
endfunction
endclass
class my_test extends uvm_test;
`uvm_component_utils(my_test)
my_object obj_A, obj_B;
function new(string name = "my_test", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
obj_A = my_object::type_id::create("obj_A", this);
obj_B = my_object::type_id::create("obj_B", this);
assert(obj_A.randomize());
assert(obj_B.randomize());
`uvm_info(get_full_name(), $sformatf("obj_A = \n%s and obj_B = \n%s", obj_A.sprint(), obj_B.sprint()), UVM_LOW);
my_compare(obj_A, obj_B);
obj_B.copy(obj_A);
`uvm_info(get_full_name(), "obj_B is copied to obj_A", UVM_LOW);
my_compare(obj_A, obj_B);
endfunction
function void my_compare(my_object obj_A, obj_B);
if(obj_B.compare(obj_A)) begin
`uvm_info(get_full_name(), "Comparison matched", UVM_LOW);
end
else begin
`uvm_info(get_full_name(), "Comparison did not match", UVM_LOW);
end
endfunction
endclass
module tb_top;
initial begin
run_test("my_test");
end
endmodule
Output:
UVM_INFO testbench.sv(57) @ 0: uvm_test_top [uvm_test_top] obj_A =
--------------------------------------------
Name Type Size Value
--------------------------------------------
obj_A my_object - @349
value integral 32 'h1f135537
names string 0 ""
colors color_type 32 GREEN
data sa(integral) 4 -
[0] integral 8 'h9f
[1] integral 8 'h33
[2] integral 8 'h12
[3] integral 8 'h9c
addr integral 8 'h2f
tmp temp_class - @350
tmp_addr integral 8 'h39
tmp_data integral 8 'hbd
--------------------------------------------
and obj_B =
--------------------------------------------
Name Type Size Value
--------------------------------------------
obj_B my_object - @351
value integral 32 'he96c3deb
names string 0 ""
colors color_type 32 RED
data sa(integral) 4 -
[0] integral 8 'hcb
[1] integral 8 'h49
[2] integral 8 'hcc
[3] integral 8 'h49
addr integral 8 'h6d
tmp temp_class - @352
tmp_addr integral 8 'h66
tmp_data integral 8 'h27
--------------------------------------------
UVM_INFO /apps/vcsmx/vcs/Q-2020.03-SP1-1//etc/uvm-1.2/src/base/uvm_comparer.svh(351) @ 0: reporter [MISCMP] Miscompare for obj_B.value: lhs = 'he96c3deb : rhs = 'h1f135537
UVM_INFO /apps/vcsmx/vcs/Q-2020.03-SP1-1//etc/uvm-1.2/src/base/uvm_comparer.svh(382) @ 0: reporter [MISCMP] 1 Miscompare(s) for object obj_A@349 vs. obj_B@351
UVM_INFO testbench.sv(69) @ 0: uvm_test_top [uvm_test_top] Comparison did not match
UVM_INFO testbench.sv(60) @ 0: uvm_test_top [uvm_test_top] obj_B is copied to obj_A
UVM_INFO testbench.sv(66) @ 0: uvm_test_top [uvm_test_top] Comparison matched
6.6.2 do_compare method
The do_compare()
回调方法是一个由 compare()方法调用的用户定义的钩子(hook)。
派生类应该重载没有用到的 uvm_object_utils_begin, `uvm_object_utils_end
and `uvm_field_*
注册宏。
6.6.2.1 do_compare method example
`include "uvm_macros.svh"
import uvm_pkg::*;
typedef enum{RED, GREEN, BLUE} color_type;
class temp_class extends uvm_object;
rand bit [7:0] tmp_addr;
rand bit [7:0] tmp_data;
function new(string name = "temp_class");
super.new(name);
endfunction
`uvm_object_utils(temp_class)
function void do_copy(uvm_object local_h);
temp_class tmp_h;
super.do_copy(local_h);
// $cast is necessary: uvm_object local_h do not have temp_class properties (tmp_addr and tmp_data)
// temp_class is extended from uvm_object, so child class temp_class handle is required for copying each property.
$cast(tmp_h, local_h);
tmp_addr = tmp_h.tmp_addr;
tmp_data = tmp_h.tmp_data;
endfunction
function bit do_compare(uvm_object local_h, uvm_comparer comparer);
temp_class tmp_h;
$cast(tmp_h, local_h);
return (super.do_compare(tmp_h, comparer) &
tmp_addr == tmp_h.tmp_addr &
tmp_data == tmp_h.tmp_data);
endfunction
endclass
class my_object extends uvm_object;
rand int value;
string names;
rand color_type colors;
rand byte data[4];
rand bit [7:0] addr;
rand temp_class tmp;
`uvm_object_utils(my_object)
function new(string name = "my_object");
super.new(name);
tmp = new();
endfunction
function void do_copy(uvm_object local_h);
my_object my_obj;
super.do_copy(local_h);
$cast(my_obj, local_h);
value = my_obj.value;
names = my_obj.names;
colors= my_obj.colors;
data = my_obj.data;
addr = my_obj.addr;
tmp.copy(my_obj.tmp);
endfunction
function bit do_compare(uvm_object local_h, uvm_comparer comparer);
my_object my_obj;
$cast(my_obj, local_h);
return (super.do_compare(my_obj, comparer) &
value == my_obj.value &
names == my_obj.names &
colors == my_obj.colors &
data == my_obj.data &
addr == my_obj.addr &
tmp.do_compare(my_obj.tmp, comparer));
endfunction
endclass
class my_test extends uvm_test;
`uvm_component_utils(my_test)
my_object obj_A, obj_B;
function new(string name = "my_test", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
obj_A = my_object::type_id::create("obj_A", this);
obj_B = my_object::type_id::create("obj_B", this);
assert(obj_A.randomize());
assert(obj_B.randomize());
`uvm_info(get_full_name(), "Before copying", UVM_LOW);
obj_print(obj_A);
obj_print(obj_B);
my_compare(obj_A, obj_B);
obj_B.copy(obj_A);
`uvm_info(get_full_name(), "After copying", UVM_LOW);
obj_print(obj_B);
my_compare(obj_A, obj_B);
endfunction
function void obj_print(uvm_object obj);
my_object my_obj;
string out;
$cast(my_obj, obj);
$display("-----------------------------");
$display("---------- %s ----------", my_obj.get_name);
$display("-----------------------------");
$sformat(out, "value = %0h, names = %s, addr = %0h", my_obj.value, my_obj.names, my_obj.addr);
`uvm_info(get_full_name(), $sformatf("%s", out), UVM_LOW);
foreach(my_obj.data[i]) `uvm_info(get_full_name(), $sformatf("data[%0d] = %h", i, my_obj.data[i]), UVM_LOW);
$sformat(out, "tmp_addr = %0h, tmp_data = %0h", my_obj.tmp.tmp_addr, my_obj.tmp.tmp_data);
`uvm_info(get_full_name(), $sformatf("tmp: %s", out), UVM_LOW);
endfunction
function void my_compare(my_object obj_A, obj_B);
if(obj_B.compare(obj_A)) begin
`uvm_info(get_full_name(), "Comparison matched", UVM_LOW);
end
else begin
`uvm_info(get_full_name(), "Comparison did not match", UVM_LOW);
end
endfunction
endclass
module tb_top;
initial begin
run_test("my_test");
end
endmodule
Output:
UVM_INFO testbench.sv(89) @ 0: uvm_test_top [uvm_test_top] Before copying
-----------------------------
---------- obj_A ----------
-----------------------------
UVM_INFO testbench.sv(107) @ 0: uvm_test_top [uvm_test_top] value = 1f135537, names = , addr = 2f
UVM_INFO testbench.sv(108) @ 0: uvm_test_top [uvm_test_top] data[0] = 9f
UVM_INFO testbench.sv(108) @ 0: uvm_test_top [uvm_test_top] data[1] = 33
UVM_INFO testbench.sv(108) @ 0: uvm_test_top [uvm_test_top] data[2] = 12
UVM_INFO testbench.sv(108) @ 0: uvm_test_top [uvm_test_top] data[3] = 9c
UVM_INFO testbench.sv(110) @ 0: uvm_test_top [uvm_test_top] tmp: tmp_addr = 39, tmp_data = bd
-----------------------------
---------- obj_B ----------
-----------------------------
UVM_INFO testbench.sv(107) @ 0: uvm_test_top [uvm_test_top] value = e96c3deb, names = , addr = 6d
UVM_INFO testbench.sv(108) @ 0: uvm_test_top [uvm_test_top] data[0] = cb
UVM_INFO testbench.sv(108) @ 0: uvm_test_top [uvm_test_top] data[1] = 49
UVM_INFO testbench.sv(108) @ 0: uvm_test_top [uvm_test_top] data[2] = cc
UVM_INFO testbench.sv(108) @ 0: uvm_test_top [uvm_test_top] data[3] = 49
UVM_INFO testbench.sv(110) @ 0: uvm_test_top [uvm_test_top] tmp: tmp_addr = 66, tmp_data = 27
UVM_INFO testbench.sv(118) @ 0: uvm_test_top [uvm_test_top] Comparison did not match
UVM_INFO testbench.sv(94) @ 0: uvm_test_top [uvm_test_top] After copying
-----------------------------
---------- obj_B ----------
-----------------------------
UVM_INFO testbench.sv(107) @ 0: uvm_test_top [uvm_test_top] value = 1f135537, names = , addr = 2f
UVM_INFO testbench.sv(108) @ 0: uvm_test_top [uvm_test_top] data[0] = 9f
UVM_INFO testbench.sv(108) @ 0: uvm_test_top [uvm_test_top] data[1] = 33
UVM_INFO testbench.sv(108) @ 0: uvm_test_top [uvm_test_top] data[2] = 12
UVM_INFO testbench.sv(108) @ 0: uvm_test_top [uvm_test_top] data[3] = 9c
UVM_INFO testbench.sv(110) @ 0: uvm_test_top [uvm_test_top] tmp: tmp_addr = 39, tmp_data = bd
UVM_INFO testbench.sv(115) @ 0: uvm_test_top [uvm_test_top] Comparison matched
6.7 Pack and Unpack methods in UVM
6.7.1 pack and unpack methods example
6.7.2 do_pack and do_unpack methods in UVM
6.7.2.1 do_pack and do_unpack methods example
[TBD]