Difference between uvm_object_utils() and uvm_object_utils_begin()~end()

Hi,

I’m trying to understand the difference between uvm_object_utils() and uvm_object_utils_begin()~end().
Currently I’m learning site UVM/Performance Guidelines | Verification Academy. In here,

2 example show up as below,

(1). Lower performance.

// APB Bus sequence_item
class apb_seq_item extends uvm_sequence_item;
 
bit[31:0] addr;
bit[31:0] data;
apb_opcode_e we;
 
// Field macros:
`uvm_object_utils_begin(apb_seq_item)
  `uvm_field_int(addr, UVM_DEFAULT)
  `uvm_field_int(data, UVM_DEFAULT)
  `uvm_field_enum(we, apb_opcode_e, UVM_DEFAULT)
`uvm_object_utils_end
 
function new(string name = "apb_seq_item");
  super.new(name);
endfunction
 
endclass: apb_seq_item

(2) higher performance.

// APB Bus sequence_item
class apb_seq_item extends uvm_sequence_item;
 
bit[31:0] addr;
bit[31:0] data;
apb_opcode_e we;
 
`uvm_object_utils(apb_seq_item)
 
function new(string name = "apb_seq_item");
  super.new(name);
endfunction
 
// Sequence Item convenience method prototypes:
extern function void do_copy(uvm_object rhs);
extern function bit do_compare(uvm_object rhs, uvm_comparer comparer);
extern function string convert2string();
extern function void do_print(uvm_printer printer);
extern function void do_record(uvm_recorder recorder);
extern function void do_pack();
extern function void do_unpack(); 
endclass: apb_seq_item

So I was made one example for test above example in TLM-10 A Single Port Analysis FIFO(1) - EDA Playground
But I’m confused that when I change to see the result from uvm_object_utils_begin~end() to uvm_object_utils(), I can’t print transaction sequence items list.



class transaction extends uvm_sequence_item;
  //---------------------------------------
  // Variable Declaration
  //---------------------------------------
  bit 	   [7:0] dout;
  rand bit [7:0] din;
  rand bit [3:0] addr;
  rand bit       wr_rd;
  rand bit [7:0] wdata;
  
  //---------------------------------------
  // Utility and Field macros
  //---------------------------------------
  `uvm_object_utils(transaction)
  //---------------------------------------
  //Constructor
  //---------------------------------------  
  function new(string name = "transaction");
    super.new(name);
  endfunction
endclass

vs

class transaction extends uvm_sequence_item;
  //---------------------------------------
  // Variable Declaration
  //---------------------------------------
  bit 	   [7:0] dout;
  rand bit [7:0] din;
  rand bit [3:0] addr;
  rand bit       wr_rd;
  rand bit [7:0] wdata;
  
  //---------------------------------------
  // Utility and Field macros
  //---------------------------------------
 
  `uvm_object_utils_begin(transaction)
    `uvm_field_int(addr,UVM_ALL_ON)
    `uvm_field_int(wr_rd,UVM_ALL_ON)
    `uvm_field_int(wdata,UVM_ALL_ON)
  `uvm_object_utils_end
  
  //---------------------------------------
  //Constructor
  //---------------------------------------  
  function new(string name = "transaction");
    super.new(name);
  endfunction
endclass

When I ran above 2 example, I got this print

UVM_INFO component_a.sv(30) @ 0: uvm_test_top.env.comp_a [component_a]  Printing trans, 
 -------------------------------
Name   Type         Size  Value
-------------------------------
trans  transaction  -     @2356
-------------------------------

vs

UVM_INFO component_a.sv(30) @ 0: uvm_test_top.env.comp_a [component_a]  Printing trans, 
 ---------------------------------
Name     Type         Size  Value
---------------------------------
trans    transaction  -     @2356
  dout   integral     8     'h0  
  din    integral     8     'ha3 
  addr   integral     4     'ha  
  wr_rd  integral     1     'h1  
  wdata  integral     8     'hb1 
---------------------------------

When I printed out about sequence items I expected that I would get a transaction list items. But uvm_object_utils() can’t get a transaction item list.
Could you guide me please?

In reply to UVM_LOVE:

When using `uvm_object_utils instead of field automation macros wrapped with uvm_object_utils_begin()~end(), it is up to you to provide the functionality that was automated for you, like the do_print() methods. Please see the link to the DVCon 2011 paper that suggests alternatives to the automation macros.

In reply to dave_59:

In reply to UVM_LOVE:
When using `uvm_object_utils instead of field automation macros wrapped with uvm_object_utils_begin()~end(), it is up to you to provide the functionality that was automated for you, like the do_print() methods. Please see the link to the DVCon 2011 paper that suggests alternatives to the automation macros.

Thanks for reply Dave.
I’m currently modifying the uvm_field_* in TLM-10 A Single Port Analysis FIFO(1) - EDA Playground

I understood that I need to make a do_print() method as below,


//-------------------------------------------
//		www.verificationguide.com 
//-------------------------------------------

class transaction extends uvm_sequence_item;
  //---------------------------------------
  // Variable Declaration
  //---------------------------------------
  bit 	   [7:0] dout;
  rand bit [7:0] din;
  rand bit [3:0] addr;
  rand bit       wr_rd;
  rand bit [7:0] wdata;
  
  //---------------------------------------
  // Utility and Field macros
  //---------------------------------------
/*  
  `uvm_object_utils_begin(transaction)
    `uvm_field_int(dout,UVM_ALL_ON)
    `uvm_field_int(din,UVM_ALL_ON)
    `uvm_field_int(addr,UVM_ALL_ON)
    `uvm_field_int(wr_rd,UVM_ALL_ON)
    `uvm_field_int(wdata,UVM_ALL_ON)
  `uvm_object_utils_end
*/  
  `uvm_object_utils(transaction)

    virtual function void do_print(uvm_printer printer);
    super.do_print(printer);
      printer.print_field_int("dout", dout, $bits(dout), UVM_HEX);
      printer.print_field_int("din", din, $bits(din), UVM_HEX);
      printer.print_field_int("addr", addr, $bits(addr), UVM_HEX);
      printer.print_field_int("wr_rd", wr_rd, $bits(wr_rd), UVM_HEX);
      printer.print_field_int("wdata", wdata, $bits(wdata), UVM_HEX);
    endfunction
  
  //---------------------------------------
  //Constructor
  //---------------------------------------  
  function new(string name = "transaction");
    super.new(name);
  endfunction
  
endclass

But when I call do_print() method in object class, do_print() make an error as below,

trans.do_print(trans);



``` verilog
//-------------------------------------------
//		www.verificationguide.com 
//-------------------------------------------

class component_b extends uvm_component;
  
  transaction trans;
  uvm_tlm_analysis_fifo #(transaction) analy_fifo;  

  `uvm_component_utils(component_b)
  
  //--------------------------------------- 
  // Constructor
  //---------------------------------------
  function new(string name, uvm_component parent);
    super.new(name, parent);
    analy_fifo = new("analy_fifo", this);
  endfunction : new
  
  //---------------------------------------
  // run_phase 
  //---------------------------------------
  virtual task run_phase(uvm_phase phase);
    phase.raise_objection(this);
    
    #100;
    `uvm_info(get_type_name(),$sformatf(" Before calling analysis fifo get method"),UVM_LOW)
    analy_fifo.get(trans);
    `uvm_info(get_type_name(),$sformatf(" After  calling analysis fifo get method"),UVM_LOW)
     trans.do_print(trans);
    phase.drop_objection(this);
  endtask : run_phase

endclass : component_b
                   |

xmvlog: *E,TYCMPAT (component_b.sv,32|23): formal and actual do not have assignment compatible data types

 

If I do correctly call do_print() method , what am I supposed to fix ?
Where does "do_print()" method call? Could you guide me please?

In reply to UVM_LOVE:

You do never call explicitely do_print. Instead you are calling print which is internaly calling do_print.

In reply to UVM_LOVE:

Hi UVM_LOVE
there is a request , if you share some eda link for the problem , please dont update it, rather make it new one while discuss going on, it will help to understand for other users.

Now for eda link, I am getting Compilation issue.

In reply to anoopjmd:

As I said, you do never call doPrint explicitely. You are calling print() instead.
In your case you are passing th transaction as argument to the do_print. This is wrong. See the definition of this function in your transaction class,
And here is the solution: