Why do constructors in classes extended from UVM base classes need default values for arguments passed?

Hi,

I was trying to extend a uvm_mem class with an identical constructor, but, compile fails on `uvm_object_utils().

I later realised that this is due to arguments not having been assigned default values.
I did notice that this happens in UVM, and not in system_verilog. (if I drop the `uvm_object_utils() for this class, compile seems fine.

Just trying to understand why the UVM factory registration is expecting default values for all constructor arguments ?

Failing Case::

class A extends uvm_mem;
  
  `uvm_object_utils(A)
  function new (string name = "my_mem", 
               longint 	unsigned 	size ,
               int 	unsigned     	n_bits ,
               string 	          access	 = 	"RW",
                int              	has_coverage	 = 	UVM_NO_COVERAGE
                );
    super.new(name, size, n_bits, access, has_coverage);
  endfunction
endclass

Failing Error (in ncsim) : (Complains about size and n_bits in the code)
ncvlog: *E,FAABP1 (testbench.sv,20|21): Task/function call, or property/sequence instance does not specify all required formal arguments.

Passing case::

class A extends uvm_mem;
  
  `uvm_object_utils(A)
  function new (string name = "my_mem", 
               longint 	unsigned 	size =0,
               int 	unsigned     	n_bits =0,
               string 	          access	 = 	"RW",
                int              	has_coverage	 = 	UVM_NO_COVERAGE
                );
    super.new(name, size, n_bits, access, has_coverage);
  endfunction
endclass

In reply to KillSteal:

The UVM factory has a create() method that calls your class’s constructor. For uvm_object_registry, it only supplies one argument to new(name), and for uvm_component_registry, it only supplies two arguments new(name, parent).

So if even if you do not actually call the factory create() method, your code will not compile because the registration code only supplies one or two arguments to your constructor.

Adding a default argument value gets around the compilation error, but is not a good idea to add extra arguments to your class methods in general.

See my sessions on SystemVerilog OOP, especially the third presentation that shows how the factory works.

In reply to dave_59:

Thanks Dave. I guess my extension question is the below; and that’s the reason why I have additional arguments supplied to the constructor to begin with!

I am trying to configure my memory by passing the “size” and “n_bit” to uvm_mem via the extension A.


task run_phase(uvm_phase phase);
  A a;
  a = new("my_mem",10,10); //Let's say this piece of code exists everywhere in TB, whenever a new mem is configured.
  $display("size = %0d", a.get_size());
  $display("n_bits = %0d", a.get_n_bits());
endtask
    

Complete Code here: (Look at line 10, and line 35)

What am I missing ?

In reply to KillSteal:

Sorry, I didn’t notice you were using uvm_mem the first time. Some of the UVM Register base classes doesn’t play nice with the UVM factory. But since most people use automated scripts to build this, it’s rarely needed. So don’t register your classes with the factory, or use the uvm_config_db to get the values you need for the missing arguments.

In reply to dave_59:

Awesome. Thanks Dave.