Part 3 · Factory & Configuration · Intermediate

Override Timing: Register Before create()

Correct build_phase ordering, too-late override anti-patterns, package-time overrides, and timeline diagrams for test/env build chains.

Golden ordering rule

Overrides affect only future create() calls. Register policy in test build_phase before super.build_phase() triggers env construction.

diagram
[FACTORY][UVM] build_phase timeline (correct)

err_test.build_phase
  | apply_factory_overrides()      <-- overrides registered
  | super.build_phase()
  |   base_test.build_phase
  |     env = my_env::create()
  |       my_env.build_phase
  |         drv = base_driver::create()  <-- override applied
  |           returns err_driver
systemverilog
class err_test extends base_test;
  `uvm_component_utils(err_test)

  function void build_phase(uvm_phase phase);
    apply_factory_overrides();
    super.build_phase(phase);
  endfunction

  virtual function void apply_factory_overrides();
    base_driver::type_id::set_type_override(err_driver::get_type());
  endfunction
endclass

Key takeaways

  • Too-late overrides are the most common factory bug in real projects.

  • super.build_phase() usually starts the create chain — override before it.

  • Treat override registration as phase-0 of test build policy.

Common pitfalls

  • super.build_phase() first, override second — original type already built.

  • Override in connect_phase for components created in build_phase.

  • Assuming re-create will happen automatically after late override.


Too-late patterns and package-time policy

Some codebases register overrides in package initial blocks or env constructors — know trade-offs and visibility risks.

Too-late anti-pattern

systemverilog
function void build_phase(uvm_phase phase);
  super.build_phase(phase); // env/agents/drivers already built
  base_driver::type_id::set_type_override(err_driver::get_type());
  // too late for drv created during super.build_phase
endfunction
diagram
[FACTORY] too-late symptom signature

factory.print shows override active
BUT
get_type_name() reports base type for target instance

root cause:
  create happened before override registration

Early registration options

  • Test build_phase before super — preferred and explicit.

  • base_test::new or early static init — use only with clear docs.

  • Package init blocks — global blast radius, avoid in reusable VIP.

systemverilog
// Acceptable for global debug policy in dedicated debug package only
initial begin
  base_monitor::type_id::set_type_override(verbose_monitor::get_type());
end
diagram
[UVM][FACTORY] timing checklist

[ ] override registered
[ ] no target create before registration
[ ] super.build_phase after override setup
[ ] elaboration type names verified

Common pitfalls

  • Package-time global overrides leaking across unrelated tests.

  • Conditional overrides inside env based on plusargs after children built.

  • Factory set in run_phase expecting rebuild of hierarchy.