Why create method is not part of uvm_object_wrapper?

uvm_object_registry and uvm_component_registry implements following methods [IEEE 1800.2-2020, section 8.2.4 and 8.2.3 respectivelly]:

  • create_object/component
  • get_type_name
  • get
  • create
  • set_type_override
  • set_inst_override
  • initialize

However, only create_* and get_type_name are part of uvm_object_wrapper, which serves as the abstract interface for factory registries [8.3.2].

My question is: what is the architectural reason for this separation?

Are the remaining methods intended to be a syntactic sugar over the global uvm_factory singleton, allowing usage such as:

base_trans::type_id::set_type_override(child_trans::get_type());

instead of directly accessing the factory:

uvm_factory::get().set_type_override_by_type(
  base_trans::get_type(),
  child_trans::get_type()
);

Or is there a deeper design reason why these methods are not part of uvm_object_wrapper despite being implemented by all registry classes?

uvm_object_wrapper is an abstract base class with no parameters. It contains the virtual methods create_* and get_type_name. The other methods are static and use the parameterized extended class type. The create() method must have a return type that matches the parameter type.

I see it now, thank you very much!

Indeed, the get and create methods can’t be placed in uvm_object_wrapper because they depend on the type parameter T. At first, I didn’t understand what the issue was with the static methods set_type_override and set_inst_override, since their prototypes don’t depend on T and static method can be placed in an abstract class. Then I realized that static methods cannot be virtual, so they cannot be overridden by derived classes.

So, is this more of a technical limitation rather than an intentional design choice?

Of course, I would say it’s by design of the language, not a limitation. :grinning_face: