To use the uvm_*_param_utils macro's or not?

https://verificationacademy.com/cookbook/uvm/guidelines says you need to use them, whilst https://verificationacademy.com/verification-horizons/november-2014-volume-10-issue-3/Please-Can-Someone-Make-UVM-Easier-to-Use seems to suggest not to use them:

Unfortunately, even these macros will not create the necessary routines to print and override using the factory. You will need to register the class manually by writing this simple piece of code!

Any opinions?

Well you anyway need the macro to do factory registration. What the second article recommends is that you not use the field macros.

So, this is OK:


class some_class #(type T) extends uvm_component;
  T some_field;
  int some_other_field;
  
  `uvm_component_param_utils(some_class #(T))

   // implement the utility functions by hand
   // ... do_print, do_pack, do_copy, etc.
endclass

This should be avoided:


class some_class #(type T) extends uvm_component;
  T some_field;
  int some_other_field;
  
  `uvm_component_param_utils_begin(some_class #(T))
    `uvm_field_int(some_other_field);
    // for 'some_field' you anyway can't do any automation
  `uvm_component_param_utils_end

   // implement the utility functions by hand
   // ... do_print, do_pack, do_copy, etc.
endclass

I think the second article isnt discussing the field macro’s but the not using of “uvm_component_param_utils”. The code suggested on that page is:

class driverB #(type T = int) extends uvm_driver #(T);
  //`uvm_component_param_utils(driverB#(T))
  localparam type_name = $sformatf("driverB#(%s)",
				T::type_name);
  typedef uvm_component_registry #(driverB#(T),
				type_name) type_id;
  static function type_id get_type();
   return type_id::get();
  endfunction
  virtual function uvm_object_wrapper get_object_type();
   return type_id::get();
  endfunction
  virtual function string get_type_name();
   return type_name;
  endfunction
 endclass

As you can see the uvm_component_param_utils macro is commented out.

Browsing a bit further (especially) looking to the section “ParameterizedTests” in the cookbook is that you would need to write the registration manually if string based factory lookup would be required?

The problem with uvm_*_utils (not uvm_params_util) is that as a macro, it only gets compiled once before any parameter overriding takes place. This macro defines a type that associates a type and a string to be registered with the factory. (See http://go.mentor.com/mcem for more details). The problem is that the macro only gets compiled once and will associate the same string with each class parametrization. This works fine if there is only one specialization of the class parameters, but as soon as there are multiple specializations, you will get an error. The `uvm_params_util macro works around this by only registering the class type with the factory without an associated string name. The manual registration process without using any macros allows you to create a unique string name for each

In reply to Nico75:

I think the second article isnt discussing the field macro’s but the not using of “uvm_component_param_utils”. The code suggested on that page is:

class driverB #(type T = int) extends uvm_driver #(T);
//`uvm_component_param_utils(driverB#(T))
localparam type_name = $sformatf("driverB#(%s)",
T::type_name);
typedef uvm_component_registry #(driverB#(T),
type_name) type_id;
static function type_id get_type();
return type_id::get();
endfunction
virtual function uvm_object_wrapper get_object_type();
return type_id::get();
endfunction
virtual function string get_type_name();
return type_name;
endfunction
endclass

As you can see the uvm_component_param_utils macro is commented out.

Hi

Does this code compile in VCS? eda playground e.g.
I keep getting :

Error-[STASKEC_IAFSTC] Illegal argument to system task
testbench.sv, 7
“T::type_name”
Illegal argument T::type_name is passed to system task $sformatf.
Please correct the system task call and recompile.

Error-[CEPO] Cannot evaluate parameter override
testbench.sv, 7
The parameter override should be an expression containing only constant
numbers and previously defined parameters.
The override was applied to parameter ‘type_name’ of instance
‘_vcs_unit__1778430441.my_test_build_phase_drv’.
Source info: $sformatf(“driverB#(%s)”, T::type_name)

In reply to justrajdeep:

Two problems with your code.

  1. You did not override your driver’s
    T
    parameter, leaving it as an
    int
    . You should leave out the default
    = int
    to force an parameter override. The trick of assigning an
    int
    type to force an override is leftover from very early versions of SystemVerilog that did not allow declarations of a parameter without a default assignments.
  2. The example from the second article inserted the factory registration code directly instead of using the `uvm_object_utils macro fixing a problem with the UVM macro. It declares
    type_name
    as a
    const static
    variable instead of a
    localparam/parameter
    . You cannot use a variable, const or not in the declaration of another parameter.

In reply to dave_59:

Hi Dave,

I have fixed 1, in the EDA playground code.

For 2, that means the article is not syntactically correct?

I could not find a proper solution also. we cannot dynamically create the type_name based on the parameters passed.

I wonder why many DVCon papers have the type_name as localparam.

Thanks
Rajdeep

In reply to justrajdeep:
You have removed the error, but your fix is not useful as the driver would normally be overridden with a class derived from the base class
uvm_sequence_item
, not the base class itself.

You are correct that the article has a mistake. The packet and packetD classes cannot use the `uvm_object_utils macro and must register with the factory the same way as the driver does.

In reply to dave_59:

Thanks Dave.