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.
[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// You never write this — macro + factory infrastructure provide it
uvm_factory f = uvm_factory::get();
f.print(); // dumps registered types and active overridesKey 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
[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 runpackage my_tb_pkg;
import uvm_pkg::*;
`include "uvm_macros.svh"
`include "base_driver.sv"
`include "err_driver.sv"
`include "my_env.sv"
endpackageRegistry 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.
[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::createCommon 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.