Regarding class array inside another class

Hi Team,

I have a requirement where I have array of classes inside another container class. I want to print content of every element of an array when I print the container class, however that is not happening.

class Register;
  string name;
  rand bit [3:0] rank;
  rand bit [3:0] pages;
 
  function new (string name);
    this.name = name;
  endfunction
 
  function void print();
    $display("name=%s rank=%0d pages=%0d", name, rank, pages);
  endfunction
 
endclass

class Container;
  Register regs[];

  function new (string name);
    regs = new[3];
    regs[0] = new("first");
    regs[1] = new("second");
    regs[2] = new("third");
  endfunction
 
endclass

module tb;
  Container c;

  initial begin
    c = new("MainContainer");
    $display ("-------- Initial Values --------");
    $display ("c = %p ", c);
  end
endmodule

I am getting below results,

c = '{regs:'{$unit_0x2edebd25::Register@5_1, $unit_0x2edebd25::Register@7_1, $unit_0x2edebd25::Register@9_1}}

Thank you.
-Mega

In reply to megamind:

When dealing with container classes in SystemVerilog, you need to understand the differences between “shallow” and “deep” access. When it comes to things like copying, comparing, and printing a hierarchy of contained classes, you must provide the necessary methods that traverse the hierarchy. That is what’s call a “deep” dive into the class. Otherwise, all you see is the top-level container, or “shallow” view of the class.

class Container;
  Register regs[];
  string m_name;
 
  function new (string name);
    m_name = name;
    regs = new[3];
    regs[0] = new("first");
    regs[1] = new("second");
    regs[2] = new("third");
  endfunction
  
  function void print();
    $display(m_name);
    foreach(regs[i]) regs[i].print();
  endfunction
endclass
 
module tb;
  Container c;
 
  initial begin
    c = new("MainContainer");
    $display ("-------- Initial Values --------");
    c.print();
  end
endmodule

In reply to megamind:

I don’t think you can achieve what you want this way.

As you already have a print method in the “Register” class, you can add a print method in the Container class :

foreach(reg[i]) reg[i].print()

And call this method instead.

In reply to dave_59:

In reply to megamind:
When dealing with container classes in SystemVerilog, you need to understand the differences between “shallow” and “deep” access. When it comes to things like copying, comparing, and printing a hierarchy of contained classes, you must provide the necessary methods that traverse the hierarchy. That is what’s call a “deep” dive into the class. Otherwise, all you see is the top-level container, or “shallow” view of the class.

class Container;
Register regs[];
string m_name;
function new (string name);
m_name = name;
regs = new[3];
regs[0] = new("first");
regs[1] = new("second");
regs[2] = new("third");
endfunction
function void print();
$display(m_name);
foreach(regs[i]) regs[i].print();
endfunction
endclass
module tb;
Container c;
initial begin
c = new("MainContainer");
$display ("-------- Initial Values --------");
c.print();
end
endmodule

Thank you Dave, on the systemverilog level it’s pretty clear now (at least seems to be) what needs to happen. On the UVM side – I was hoping, that if I have uvm_field_array_object(array_of_objects, UVM_ALL_ON) macro inside of the uvm_object_utils_begin/end construct, then this extension of the standard methods (like print, etc.) to cover the array_of_objects would happen automagically. Is it the case or not?

In reply to megamind:

Yes, assuming the object you are creating an array of also has it fields registered with `uvm_object_utils_begin/end, or if Register is a uvm_reg class, it has its do_print() method iterating over its fields using a different mechanism

If your array has a large number of elements, you should not be using `uvm_object_utils_begin/end as they have a lot of overhead.

In reply to dave_59:

In reply to megamind:
Yes, assuming the object you are creating an array of also has it fields registered with uvm_object_utils_begin/end, or if Register is a uvm_reg class, it has its do_print() method iterating over its fields using a different mechanism If your array has a large number of elements, you should not be using uvm_object_utils_begin/end as they have a lot of overhead.

Both register(it is not uvm_reg but just uvm_object) class and container class has been registered with the factory using uvm_object_utils_begin/end still when I print container class it only prints its variables and not hierarchy inside.

I have tried with all major simulators. Can you please take a look?
Thank you.

In reply to megamind:

In reply to dave_59:
Both register(it is not uvm_reg but just uvm_object) class and container class has been registered with the factory using uvm_object_utils_begin/end still when I print container class it only prints its variables and not hierarchy inside.
Error
I have tried with all major simulators. Can you please take a look?
Thank you.

It worked, when I used sprint! I thought I can just print class handle using %p, but that did not work, your comments are welcome too. Thank you.