6 UVM Object

目录

6.1 UVM Utility Macros and field macros

6.1.1 `uvm_field_* macros

6.1.2 `uvm_field_sarray_* macros

6.1.3 `uvm_field_array_* macros

6.1.4 `uvm_field_* macro flag

6.2 Code with `uvm_object_utils

6.3 Code with `uvm_object_utils_begin and `uvm_object_utils_end

6.4 UVM中的打印方法

6.4.1 打印方法示例

6.4.2 print method with `uvm_object_utils

6.4.3 do_print() method

6.4.3.1 do_print() method example

6.5 Copy and clone methods in UVM

6.5.1 copy method in UVM

6.5.1.1 copy method example

6.5.2 do_copy method

6.5.2.1 do_copy method example

6.5.3 clone method in UVM

6.6 compare method in UVM 

6.6.1 compare method example

6.6.2 do_compare method

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]

资源下载链接为: https://pan.quark.cn/s/1e68be2bff6a 这些压缩包文件里有大约60个小程序的源码示例,是学习小程序开发的优质资源。小程序是一种无需下载安装就能用的轻量级应用,广泛应用于生活服务、电商购物、社交互动等众多领域。研究这些源码,开发者能深入学习小程序开发技术和最佳实践。wx_app-master.zip可能是一个基础小程序项目模板,涵盖小程序的基本结构和组件使用。学习者可借此了解小程序的目录结构、配置文件,以及wxml、wxss和JavaScript的结合方式。BearDiary-master.zip和weapp-bear-diary-master.zip可能是日记类小程序示例,展示如何实现用户记录、查看和管理个人日记等功能,包括处理用户输入、存储数据和创建交互式界面。WXNews-master.zip和仿知乎日报.zip可能是新闻阅读类小程序的源码,使用网络请求API获取实时新闻数据并展示。学习者能通过这些代码学习处理网络请求、动态加载数据和设计适应性强的布局。wechat-weapp-gank-master.zip可能是一个类似“干货集中营”的技术分享平台小程序示例,涉及数据分类、搜索功能和用户交互设计,可学习如何组织和展示大量数据及实现筛选和搜索功能。Xiaoxiazhihu (知乎日报) 微信小程序 d.zip是仿知乎日报的小程序,涉及数据同步、新闻详情页设计和滑动效果实现,是模仿流行应用界面和用户体验的良好学习案例。仿豆瓣电影-demo.zip提供电影信息查询和展示功能,可能涉及API接口调用、数据解析以及评分和评论系统实现,有助于开发者理解如何集成外部服务和处理展示多媒体内容。仿今日头条app.zip类似今日头条的小程序,涵盖新闻推荐算法、个性化推荐和推送通知等复杂功能,能让开发者学习处理大数据流和提供个性化用户体验。
资源下载链接为: https://pan.quark.cn/s/76d9f06f4cda Vue.js 是一款由尤雨溪开发的轻量级前端 JavaScript 框架,凭借简洁的 API、高效的虚拟 DOM、组件化设计以及强大的生态系统,在现代 Web 开发领域广受欢迎。在开发“基于 Vue 的电商后台管理系统”时,Vue.js 发挥了核心作用,助力构建出高效且易于维护的管理界面。 Vue.js 的核心特性包括:虚拟 DOM,通过计算差异仅更新必要部分,避免直接操作 DOM 产生的性能损耗;双向数据绑定,借助 v-bind 和 v-model 指令,实现视图与模型数据的同步;指令系统,如 v-if、v-for、v-on 等,扩展 HTML 行为,增强模板功能;组件化,允许开发者创建可复用的 UI 部件,每个组件拥有独立的视图和数据逻辑,便于独立开发、测试与重用。 在电商后台管理系统中,常见的组件有商品列表、订单管理、用户管理等,它们通过 props 接收父组件数据,并通过事件向父组件传递信息,组件可嵌套以构建复杂 UI 结构。对于多页面应用,Vue.js 结合 Vue Router 实现页面跳转,Vue Router 支持动态路由匹配、命名路由、路由懒加载等功能,助力单页应用(SPA)的构建。Vuex 作为 Vue.js 的官方状态管理工具,可用于集中管理全局共享状态,如用户登录状态、购物车信息等,通过 actions、mutations 和 getters 实现状态的改变与获取。Vue.js 通常搭配 Axios 库进行 API 请求,处理后端接口数据,在电商后台管理系统中,涉及商品的增删改查、订单的创建更新、用户信息同步等操作,都需要与后端交互。Vue.js 支持使用 Jest 或 Mocha 等测试框架进行单元测试和集成测试,这对于电商后台管理系统尤为重要,能够及时发现并
资源下载链接为: https://pan.quark.cn/s/edccc07f4fda “吉林大学数据库实验代码和实验报告.zip”是一个包含数据库课程实验资料的压缩包,涵盖了实验代码、实验报告以及学习资源。这些资料有助于深入理解数据库原理、操作以及编程语言与数据库的交互。 实验报告:“55170606刘桦数据库应用程序开发实验报告.doc”记录了实验的全过程,包括实验目标、环境搭建、操作步骤、遇到的问题及解决方法和总结。通过阅读这份报告,能够掌握数据库应用开发的核心技术和实践经验。 数据库与Java交互:“JAVA 对DB2中的BLOB对象的.ppt”介绍了如何在Java中处理DB2数据库的BLOB对象。BLOB用于存储大量二进制数据,如图片、音频或视频。该教程可能涉及使用JDBC API进行数据库连接、SQL语句执行以及BLOB数据的处理。 操作演示:“操作演示.rar”可能包含数据库操作的示例,通过SQL脚本或图形化工具展示数据库的增删改查等基本操作以及复杂查询和事务管理,帮助学生更好地理解数据库的实际操作。 任务文件:“task1”至“task10”代表实验的不同阶段,每个任务对应一个数据库概念或技术,如关系模型、索引、视图、存储过程等。通过完成这些任务,学生可以逐步掌握数据库设计和管理的核心技能。 CG11 DB2 programming with Java:这可能是一份关于使用Java进行DB2数据库编程的课程材料,详细介绍了如何使用Java编写数据库应用程序,涵盖JDBC驱动、连接池、事务处理等内容。 task9和task2:这两个文件可能涉及特定的数据库技术或挑战,如数据库优化、并发控制、备份恢复等,有助于学生提升数据库系统的实际操作能力。 该压缩包提供了丰富的数据库学习资源,包含理论知识和实践环节,是学习数据库管理、编程和系统设计的良好素材。通过深入研究
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值