Override by type with name conflicts

I can’t use set_type_override_by_type() if the parent class has a “name-duplicate” in another package.

The packages and the classes:

package a_pkg;
   import uvm_pkg::*;

   class parent_obj extends uvm_object;
      `uvm_object_utils(parent_obj)

      function new(string name = "parent_obj");
         super.new(name);
      endfunction : new

      virtual function void do_thing();
         `uvm_info(get_name(), $sformatf("I'm parent in A"), UVM_LOW)
      endfunction : do_thing

   endclass : parent_obj

endpackage : a_pkg

package b_pkg;
   import uvm_pkg::*;

   class parent_obj extends uvm_object;
      `uvm_object_utils(parent_obj)

      function new(string name = "parent_obj");
         super.new(name);
      endfunction : new

      virtual function void do_thing();
         `uvm_info(get_name(), $sformatf("I'm parent in B"), UVM_LOW)
      endfunction : do_thing

   endclass : parent_obj

   class child_obj_b extends parent_obj;
      `uvm_object_utils(child_obj_b)

      function new(string name = "child_obj");
         super.new(name);
      endfunction : new

      virtual function void do_thing();
         `uvm_info(get_name(), $sformatf("I'm child in B"), UVM_LOW)
      endfunction : do_thing

   endclass : child_obj_b

endpackage : b_pkg

The test:

class base_test extends uvm_test;
   `uvm_component_utils(base_test)

   function new (string name, uvm_component parent);
      super.new(name, parent);
   endfunction

   virtual function void build_phase(uvm_phase phase);
      uvm_factory factory = uvm_factory::get();
      super.build_phase(phase);
      factory.set_type_override_by_type(b_pkg::parent_obj::get_type(), b_pkg::child_obj_b::get_type());
   endfunction : build_phase

   virtual task run_phase(uvm_phase phase);
      b_pkg::parent_obj b_pkg_parent_obj = b_pkg::parent_obj::type_id::create("b_pkg_parent_obj");
      a_pkg::parent_obj a_pkg_parent_obj = a_pkg::parent_obj::type_id::create("a_pkg_parent_obj");

      phase.raise_objection(this);

      b_pkg_parent_obj.do_thing();
      a_pkg_parent_obj.do_thing();

      super.run_phase(phase);
      phase.drop_objection(this);
   endtask

endclass : base_test

The result:

UVM_WARNING @ 0: reporter [TPRGED] Type name 'parent_obj' already registered with factory. No string-based lookup support for multiple types with the same type name.
UVM_INFO @ 0: reporter [RNTST] Running test base_test...
UVM_FATAL @ 0.0 ns: reporter [FCTTYP] Factory did not return an object of type 'parent_obj'. A component of type 'child_obj_b' was returned instead. Name=a_pkg_parent_obj Parent=null contxt=
UVM_INFO /org/seg/tools/eda/cadence/xcelium/22.03.v006/tools/methodology/UVM/CDNS-1.2/sv/src/base/uvm_report_catcher.svh(705) @ 0.0 ns: reporter [UVM/REPORT/CATCHER]

What should I do instead?
Also, why isn’t it working?

The `uvm_component_utils and `uvm_object_utils macros use their sole argument to register both a string name and a type with the UVM’s factory. If you are going to have the same class name in multiple packages, then you need to add the package name to the macro argument as shown below.

If you never plan to access the factory by string names, use the `uvm_component_param_utils and `uvm_object_param_utils macros instead. This skips the string name registration and only registers the class by type. I recommend by_type anyways as you get compile error instead of run-time errors if you make a mistake. It is alose slightly better for performance.

`include "uvm_macros.svh"
package p1;
import uvm_pkg::*;
class myobject extends uvm_object;
  `uvm_object_utils(p1::myobject)
  function new(string name="");
    super.new(name);
    $display("myobject from p1 %s %s", get_type_name(), get_name());
  endfunction
endclass
class myextended extends myobject;
  `uvm_object_utils(p1::myextended)
  function new(string name="");
    super.new(name);
    $display("extended from p1 %s %s", get_type_name(), get_name());
  endfunction
endclass
endpackage
package p2;
import uvm_pkg::*;
class myobject extends uvm_object;
  `uvm_object_utils(p2::myobject)
  function new(string name="");
    super.new(name);
    $display("myobject from p2 %s %s", get_type_name(), get_name());
  endfunction
endclass
class myextended extends myobject;
  `uvm_object_utils(p2::myextended)
  function new(string name="");
    super.new(name);
    $display("extended from p2 %s %s", get_type_name(), get_name());
  endfunction
endclass
endpackage

module top;
  uvm_pkg::uvm_factory factory = uvm_pkg::uvm_factory::get();

  p1::myobject p1mo;
  p2::myobject p2mo;
  initial begin
    factory.set_type_override_by_type(p1::myobject::get_type(), p1::myextended::get_type());
    p1mo = p1::myobject::type_id::create("p1mo");
    factory.set_type_override_by_name("p2::myobject", "p2::myextended");
    p2mo = p2::myobject::type_id::create("p2mo");

  end
endmodule