The short answer: The UVM factory is a registry of classes that lets a test replace one class with a derived class without touching the environment. Classes register with `uvm_object_utils or `uvm_component_utils, and code creates them with type_id::create() instead of new(). A test then sets a type override (replace a class everywhere) or an instance override (replace it only under a given hierarchy path), and every create() call returns the substitute.
The factory is what makes a UVM environment reusable. The same environment can run a normal test, an error-injection test and a corner-case test, and only the test changes. This post explains how it works and the mistakes that silently break it.
- How create() works
- Registering and creating
- Type and instance overrides
- Overrides from the command line
- Debugging the factory
- Mistakes that silently break overrides
Table of Contents
Part 1: How create() works

Part 2: Registering and creating
class bus_item extends uvm_sequence_item;
`uvm_object_utils(bus_item) // objects
...
endclass
class bus_driver extends uvm_driver #(bus_item);
`uvm_component_utils(bus_driver) // components
...
endclass
// always create through the factory
item = bus_item::type_id::create("item");
drv = bus_driver::type_id::create("drv", this);
Parameterised classes use `uvm_object_param_utils and `uvm_component_param_utils.
Part 3: Type and instance overrides
class err_item extends bus_item;
`uvm_object_utils(err_item)
constraint c_bad { addr[1:0] != 0; } // misaligned addresses
...
endclass
class err_test extends base_test;
`uvm_component_utils(err_test)
function void build_phase(uvm_phase phase);
// every bus_item becomes an err_item
bus_item::type_id::set_type_override(err_item::get_type());
// only the driver under agt_in becomes a slow driver
bus_driver::type_id::set_inst_override(slow_driver::get_type(),
"env.agt_in.drv", this);
super.build_phase(phase); // build the env AFTER setting overrides
endfunction
endclass
- Set overrides in build_phase before the components or objects are created, which usually means before calling super.build_phase.
- Instance overrides take priority over type overrides.
- The override type must be derived from the original type.
Part 4: Overrides from the command line
+uvm_set_type_override=bus_item,err_item
+uvm_set_inst_override=bus_driver,slow_driver,uvm_test_top.env.agt_in.drv
Handy for quick experiments without writing a new test class.
Part 5: Debugging the factory
function void end_of_elaboration_phase(uvm_phase phase);
uvm_factory::get().print(); // shows registered types and overrides
uvm_top.print_topology(); // shows what was actually built
endfunction
Part 6: Mistakes that silently break overrides
- Creating with
new()instead oftype_id::create(): the factory is bypassed. - Forgetting the utils macro in the derived class: the override type isn’t registered.
- Setting the override after the object was created, for example after super.build_phase.
- A wrong instance path in set_inst_override: nothing matches, and nothing warns you. Print the topology to check paths.
Practise this on VLSI Forge
I built VLSI Forge so you can write RTL in your browser, run it on a real simulator and check every signal in the waveform. Free, nothing to install.
Design Verification problems · Daily challenge
Previous in my UVM series: Phases and objections. Next: Configuration and uvm_config_db.
FAQ
What is the UVM factory?
A central registry that creates UVM objects and components and lets tests substitute derived classes through overrides.
What is the difference between a type override and an instance override?
A type override replaces a class everywhere; an instance override replaces it only for components or objects created under a specific hierarchical path.
Why use type_id::create() instead of new()?
Because only create() goes through the factory, so only it honours overrides.
Where should I set factory overrides?
In the test’s build_phase, before the environment builds the components or objects being overridden.
