Part 3 · Factory & Configuration · Intermediate

Factory Registry Concept: Global Constructor Map

What the uvm_factory registry stores, how types register at elaboration, and how create requests resolve to concrete constructors.

Registry mental model

Think of uvm_factory as a name-to-constructor table plus override tables. Registration macros populate the table at startup; create() queries it at build time.

diagram
[FACTORY][UVM] registry tables (conceptual)

TYPE TABLE
  "base_driver"   -> ctor proxy for base_driver
  "err_driver"    -> ctor proxy for err_driver
  "my_env"        -> ctor proxy for my_env

TYPE OVERRIDE TABLE
  base_driver -> err_driver          (global)

INSTANCE OVERRIDE TABLE
  "uvm_test_top.env.agt0.drv" -> stress_driver

CREATE REQUEST
  request: base_driver, inst="drv", parent=my_agent
  resolve: walk instance path + type overrides
  result:  ctor proxy for winning type
systemverilog
// You never write this — macro + factory infrastructure provide it
uvm_factory f = uvm_factory::get();
f.print();  // dumps registered types and active overrides

Key takeaways

  • Registration is static; overrides are dynamic policy layered on top.

  • The factory never guesses — unregistered types cannot be created.

  • Registry state is global; discipline keeps overrides scenario-local.

Common pitfalls

  • Assuming create() works without a registration macro.

  • Expecting runtime re-registration of the same type name.

  • Mixing duplicate type names across packages without namespacing discipline.


Registration timing and visibility

Types become visible to the factory when their package elaborates and static initializers run.

Elaboration sequence

diagram
[UVM][FACTORY] elaboration timeline

1) import uvm_pkg + agent/env packages
2) static registry objects construct (via utils macro)
3) run_test() starts UVM phase scheduler
4) test build_phase issues first create() calls

if package import missing:
  type not registered -> create() fails at compile or run
systemverilog
package my_tb_pkg;
  import uvm_pkg::*;
  `include "uvm_macros.svh"
  `include "base_driver.sv"
  `include "err_driver.sv"
  `include "my_env.sv"
endpackage

Registry inspection habits

  • Call factory.print() once per failing scenario before deep debug.

  • Compare registered type list against env create() requests.

  • Verify extension classes appear in registry before applying overrides.

diagram
[FACTORY] quick registry audit

registered?
  err_driver listed in factory.print

override active?
  base_driver -> err_driver entry present

create target?
  env still requests base_driver via type_id::create

Common pitfalls

  • Including SV files without importing the package that registers them.

  • Conditional compilation that drops registration in some build modes.

  • Relying on string type names instead of get_type() proxies.