Part 5 · Sequences · Intermediate

Factory Library Overrides: set_type_override_by_type

Swap library candidates via factory without editing the library, per-test stress variants, and override scope.

Why factory overrides on libraries

A sequence library hard-codes candidate types at compile time. When a regression needs a stress variant of one candidate — longer bursts, more errors, different constraints — editing the library affects every test. The UVM factory lets you replace a registered type with a derived type in

test build_phase via set_type_override_by_type, so the library still calls axi_rand_burst_seq::get_type() but UVM constructs axi_stress_burst_seq instead.

diagram
[UVM] factory indirection

  library selects: axi_rand_burst_seq::get_type()
       │
       │  factory lookup
       ▼
  set_type_override registered?
    YES  construct axi_stress_burst_seq  (derived, same interface)
    NO   construct axi_rand_burst_seq   (original)

Stress variant and override

systemverilog
// Derived stress variant — same base, aggressive knobs
class axi_stress_burst_seq extends axi_rand_burst_seq;
  `uvm_object_utils(axi_stress_burst_seq)

  function new(string name = "axi_stress_burst_seq");
    super.new(name);
    num_bursts   = 50;
    allow_errors = 1;
  endfunction

  constraint stress_len {
    burst_len dist { 7 := 60, 15 := 40 };  // longer bursts
  }
endclass

// In test build_phase — swap without touching axi_seq_lib source
class test_axi_stress_lib extends uvm_test;
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    set_type_override_by_type(
      axi_rand_burst_seq::get_type(),
      axi_stress_burst_seq::get_type()
    );
  endfunction

  task run_phase(uvm_phase phase);
    axi_seq_lib lib = axi_seq_lib::type_id::create("lib");
    lib.selection_mode = UVM_SEQ_LIB_RAND;
    phase.raise_objection(this);
    lib.start(env.axi_agent.sqr);  // when lib picks burst, gets stress variant
    phase.drop_objection(this);
  endtask
endclass
  • Override is by type, not instance — every create() of axi_rand_burst_seq gets stress.

  • Derived class must be factory-registered (`uvm_object_utils) and compatible interface.

  • set in build_phase before env constructs sequences that might create the type.


Override scope and per-test control

Factory overrides can be global or instance-scoped. For libraries, type-level override is the common case:

systemverilog
// Global type override — entire test hierarchy
set_type_override_by_type(
  axi_rand_burst_seq::get_type(),
  axi_stress_burst_seq::get_type()
);

// Instance override — only this env's sequences (when using create_by_type with parent)
set_inst_override_by_type(
  env.axi_agent.sqr,
  axi_rand_burst_seq::get_type(),
  axi_stress_burst_seq::get_type()
);

Walkthrough — library pick with override active

diagram
Legend: [STIM] [SEQ] [UVM]

  T0  test build_phase: set_type_override_by_type(burst  stress_burst)
  T1  test run_phase: lib.start(axi_sqr)
  T2  library random pick: axi_rand_burst_seq::get_type()
  T3  [UVM] factory: override hit  type_id::create returns axi_stress_burst_seq
  T4  stress_burst.body(): num_bursts=50, long burst_len dist
  T5  send_beat × hundreds  driver busy  regression stress achieved
  T6  next pick might be axi_error_inj_seq — no override, original runs

Only the overridden type is swapped. Other library candidates run unchanged — targeted stress without a separate library class.


Integration patterns

  • One library, many tests: default test uses stock types; stress test sets override in build_phase.

  • Plusarg-gated override: if ($test$plusargs("STRESS")) set_type_override… in build_phase.

  • Override error_inj_seq with directed_err_seq for bug-hunt without new library registration.

  • Print factory overrides at UVM_MEDIUM in build_phase — confirms which test variant is active.

systemverilog
function void build_phase(uvm_phase phase);
  super.build_phase(phase);
  if ($test$plusargs("AXI_STRESS")) begin
    set_type_override_by_type(
      axi_rand_burst_seq::get_type(),
      axi_stress_burst_seq::get_type()
    );
    `uvm_info("TEST", "factory: burst → stress_burst override active", UVM_LOW)
  end
endfunction

Key takeaways

  • set_type_override_by_type swaps library candidates without editing library source.

  • Derived stress variants extend original — same start() interface, different constraints.

  • Override in build_phase; plusarg gate for regression matrix from one test binary.

Common pitfalls

  • Override target not factory-registered — create returns wrong type or fatal.

  • Stress subclass breaks base send_beat contract — override buys bugs, not stress.

  • set_type_override after sequences already created — too late, instances already built.

  • Forgetting override is test-local — global override in package pollutes other tests.