Part 11 · Senior Prep · Intermediate

Factory Registry & create() Interview Q&A

Model answers on uvm_factory registry, type_id::create mechanics, and why new() bypasses the factory.

Factory registry fundamentals

The factory is a type substitution registry — senior answers connect it to test reuse, not just API syntax.

Q: Why does UVM have a factory?

diagram
[INT][SENIOR][UVM] MODEL ANSWER

Q: Why the factory?

A:
  MECHANISM:  type_id::create() consults uvm_factory registry; set_type_override
              replaces the constructed type without editing env source.
  MOTIVATION:  Tests swap behavior (error driver, enhanced monitor) at runtime —
              reuse env, vary stimulus/checking per test without env forks.
  WHEN:       Regression needs multiple tests on one env; VIP offers derivations;
              debug tests substitute instrumented components.
  NOT WHEN:   Single directed block with one driver type — factory adds noise.
  PITFALL:    create() without factory registration — override silently ignored.
  EXAMPLE:    test sets set_type_override(axi_driver, axi_err_driver) before env.build;
              same env hierarchy runs error injection test unchanged.

Q: What happens inside type_id::create()?

diagram
[INT][SENIOR][UVM] MODEL ANSWER

Q: Inside type_id::create()?

A:
  MECHANISM:  create(name, parent) looks up registered type in factory, applies
              active type/instance overrides, calls overridden type's create method.
  MOTIVATION:  Single creation API decouples caller from concrete type — env code
              says create("drv", this) without knowing if debug_driver substituted.
  WHEN:       Every uvm_component and uvm_object construction in standard TBs.
  PITFALL:    Hard-coded typed variable: my_driver drv = my_driver::type_id::create(...)
              — override to debug_driver fails type assignment at compile time.
  EXAMPLE:    base class handle: uvm_driver #(axi_item) drv; create returns
              axi_err_driver instance when override active — use base type handle.

Q: new() vs type_id::create() — what breaks with new()?

diagram
[INT][SENIOR][UVM] MODEL ANSWER

Q: new() vs create()?

A:
  MECHANISM:  new() bypasses factory — constructs exact type requested, no override
              lookup, no name registration in component hierarchy via factory path.
  MOTIVATION:  Factory exists precisely to intercept construction — new() defeats it.
  WHEN:       Always create() for uvm_component/uvm_object in TB code. new() only
              inside class's own create implementation (factory callback).
  PITFALL:    env.build: drv = my_driver::type_id::create(...) in one agent but
              new() in another — inconsistent override behavior across agents.
  EXAMPLE:    Test sets override; env uses new() for driver — override never applies,
              2 hours debug until factory print shows no active override consumed.

Q: How do you register a type with the factory?

diagram
[INT][SENIOR][UVM] MODEL ANSWER

Q: Factory registration?

A:
  MECHANISM:  `uvm_component_utils(T) or `uvm_object_utils(T) macro registers type
              with factory at class definition time; type_id::get() returns handle.
  MOTIVATION:  Registration enables override lookup and name-based creation from
              testname and factory-based test selection.
  WHEN:       Every UVM class uses utils macro — missing macro means create fails or
              override cannot target the type.
  PITFALL:    Typo in utils macro argument vs class name — silent registration of
              wrong type, override targets wrong entry.
  EXAMPLE:    class axi_err_driver extends axi_driver;
              `uvm_component_utils(axi_err_driver) — now override target exists.

Key takeaways

  • create() consults factory; new() bypasses it entirely.

  • Use base-type handles when overrides may substitute derived types.

  • utils macro registration is mandatory for factory participation.

Common pitfalls

  • Mixed create() and new() in same env — inconsistent override behavior.

  • Derived-type local variable preventing override assignment.


Factory diagnostics and advanced create

Q: How do you audit active factory overrides?

diagram
[INT][SENIOR][UVM] MODEL ANSWER

Q: Audit factory overrides?

A:
  MECHANISM:  uvm_factory::get().print(verbosity) lists all type and instance
              overrides with original type, override type, and instance path.
  MOTIVATION:  Unexpected component type in waveform/debug almost always traces to
              override — print is faster than grep-ing test source.
  WHEN:       End of test build_phase, on UVM_FACTORY debug, or when component
              type mismatch suspected.
  PITFALL:    Never printing overrides — 'works in smoke test' but wrong driver
              in nightly because different test set global override.
  EXAMPLE:    print shows set_type_override(axi_driver, axi_err_driver) active —
              explains CRC errors injected when smoke test expected clean driver.

Q: Can you create components by name string without knowing the type?

diagram
[INT][SENIOR][UVM] MODEL ANSWER

Q: Create by name string?

A:
  MECHANISM:  factory.create_component_by_name(type_name, parent_path, name, parent)
              or create_component_by_type(type_id, ...) — string-based creation.
  MOTIVATION:  Test selection via +UVM_TESTNAME uses this path — run_test resolves
              string to registered type and creates test component.
  WHEN:       run_test(), dynamic test loading, generator tools emitting type names.
  PITFALL:    String typo in type name — creation fails at runtime with opaque error
              instead of compile-time catch.
  EXAMPLE:    run_test("burst_traffic_test")  factory looks up burst_traffic_test
              type_id  creates test under uvm_test_top.
systemverilog
// factory patterns — interview must-know
my_driver::type_id::set_type_override(err_driver::get_type());
uvm_component drv;
drv = my_driver::type_id::create("drv", this);  // base handle!

uvm_factory::get().print(1);  // audit overrides

Q: What is uvm_object_registry vs uvm_component_registry?

diagram
[INT][SENIOR][UVM] MODEL ANSWER

Q: object vs component registry?

A:
  MECHANISM:  uvm_component_registry for hierarchy members (agents, env); uvm_object_registry
              for transient objects (sequences, items). Both provide type_id wrapper.
  MOTIVATION:  Components need parent/name for hierarchy; objects need only name for
              factory lookup and sequence/item override scenarios.
  WHEN:       Component utils for agents/env/scb; object utils for seq/items/cfg objects.
  PITFALL:    Using component_utils on sequence class — wrong registry, hierarchy errors.
  EXAMPLE:    axi_item uses `uvm_object_utils — override item type for weighted err injection;
              axi_driver uses `uvm_component_utils — override driver for debug.

Q: When would you say 'I would not use the factory'?

diagram
[INT][SENIOR][UVM] MODEL ANSWER

Q: When skip factory?

A:
  MECHANISM:  Factory adds indirection — override lookup, print audit, registration macros.
  MOTIVATION:  Small directed TB with one test and fixed types gains nothing from override
              infrastructure — direct construction is simpler to debug.
  WHEN:       Unit-level SV testbench, single directed test, no planned scenario variants.
              Also skip when team lacks override discipline (override leaks cause bugs).
  PITFALL:    Claiming factory is always mandatory — signals textbook recitation not judgment.
  EXAMPLE:    200-line APB sanity TB: one driver, one test — I use create() for UVM
              compliance but no overrides; factory print always empty.

Key takeaways

  • factory.print() is the override audit tool — use it in debug.

  • run_test() resolves test type via factory string lookup.

  • Skipping factory for tiny TBs is valid senior judgment.

Common pitfalls

  • Never auditing overrides in multi-test regression.

  • component_utils on sequence classes — wrong registry type.