Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • Start Here4
  • UVM Foundations14
  • UVM Phases & Simulation Lifecycle26
  • Factory & Configuration15
    • UVM Factory: Registration, Overrides and Debug
      • The Factory: Swapping Classes Without Editing the Env
      • Registration Macros: What uvm_component_utils Writes for You
      • The type_id::create Pattern
      • Override Resolution: Who Wins
      • Override Timing, Safety and Debug
      • Factory Advanced: Parameterized, Abstract and By-Name
      • Command-Line Overrides
      • Overriding Items and Sequences
    • config_db and Resources
  • Transaction-Level Modeling (TLM)13
  • UVM Sequences & Stimulus21
  • UVM Agents & Protocol VIP21
  • Environment & Test Classes11
  • Checking & Coverage in UVM21
  • UVM Register Abstraction Layer (RAL)22
  • Advanced UVM in Practice13
  • Debug & Regression10
  • Coding Practice47
  • Verification in Industry Practice10
  • Senior Prep: Architecture, Leadership and Interviews32
Loading lesson

‹UVM Factory: Registration, Overrides and Debug
  1. Topics
  2. UVM Verification
  3. Factory & Configuration
  4. UVM Factory: Registration, Overrides and Debug
  5. Overriding Items and Sequences

Part 3 · Factory & Configuration · Intermediate

Overriding Items and Sequences

Factory overrides for sequence items and sequences: the context argument of create, instance overrides scoped to a sequencer path, and swapping a sequence inside a virtual sequence.

On this page

    A new DMA bug: it mishandles a packet whose words have a particular bit pattern, but only on the input stream, never on the register bus. You want error-flavoured items on in_agt and nowhere else, for one test, without touching the packet sequence. A type override on axis_item would also change every item the output monitor creates. You need an instance override for objects, and objects have no place in the component tree. This lesson shows how to give them one.

    The idea: objects get an address only if you give them one

    Components have a permanent address, their full hierarchical name. Sequences and items are created on the fly and belong to nothing in the tree. When you create one, the factory forms its instance path from the context string you pass, plus the name. No context, and the path is just the name: "it", "pkt". An instance override can only target an address that exists, so path-scoped overrides on stimulus depend on every create passing a meaningful context.

    For sequences the natural context is get_full_name(). Once a sequence is started, its full name is its parent sequence's full name plus its own name, or, for a top-level sequence, the sequencer's full name plus its name. Inside axis_pkt_seq started on in_agt.sqr, that is uvm_test_top.env.in_agt.sqr.pkt.

    The picture

    Flow: the item created in a sequence on in_agt.sqr gets a path under that sequencer and matches the instance override; the monitor's item with no context does not.
    An item created with the sequence's full name as context lives at a path under the sequencer, so an instance override scoped to in_agt.sqr reaches it. The output monitor's items, created without a context, are left alone.

    Build it: path-scoped stimulus overrides

    Step 1: create items with a context

    The bench's packet sequence creates items with a name only, which is fine for type overrides but leaves no address for instance overrides:

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    // snippet: from the course DMA bench
    // A packet of n words; the last word carries TLAST.
    class axis_pkt_seq extends uvm_sequence #(axis_item);
      `uvm_object_utils(axis_pkt_seq)
      rand int unsigned n;
      constraint n_c { n inside {[1:16]}; }
    
      function new(string name = "axis_pkt_seq");
        super.new(name);
      endfunction
    
      task body();
        for (int i = 0; i < n; i++) begin
          axis_item it = axis_item::type_id::create("it");
          start_item(it);
          if (!it.randomize() with { last == (i == n - 1); })   // i and n are not item fields
            `uvm_fatal("RAND", "axis_item randomize failed")
          finish_item(it);
        end
      endtask
    endclass

    The one-word change that makes path-scoped overrides possible is the third argument:

    design.sv
    // snippet: inside axis_pkt_seq::body, creating each beat with a context
    axis_item it = axis_item::type_id::create("it", null, get_full_name());
    // path: uvm_test_top.env.in_agt.sqr.pkt.it when pkt runs on in_agt.sqr

    Step 2: register an instance override on the sequencer path

    The test targets everything created under the input sequencer. The pattern covers the sequence and every item it creates; the output side and the APB side are unaffected.

    design.sv
    1
    2
    3
    4
    // snippet: in a test's build_phase
    axis_item::type_id::set_inst_override(axis_err_item::get_type(),
                                          "env.in_agt.sqr.*", this);
    // this prefixes the test's full name: "uvm_test_top.env.in_agt.sqr.*"

    axis_err_item must extend axis_item and carry its own ` uvm_object_utils `` (without it, the inherited type_id trap silently turns the override into a no-op).

    Step 3: override a sequence inside a virtual sequence

    The same idea replaces a whole sequence. A virtual sequence that coordinates the DMA (program registers, then stream data) creates its sub-sequences through the factory, with its own full name as context:

    design.sv
    1
    2
    3
    4
    5
    6
    7
    // snippet: a virtual sequence's body; the test can swap the packet sequence
    task body();
      axis_pkt_seq pkt = axis_pkt_seq::type_id::create("pkt", null, get_full_name());
      if (!pkt.randomize() with { n == 8; })
        `uvm_fatal("RAND", "axis_pkt_seq randomize failed")
      pkt.start(in_sqr, this);        // parent = this vseq
    endtask

    Because the virtual sequence passes itself as parent, pkt's full name is the virtual sequence's full name plus .pkt, not the input sequencer's path. If the test started the virtual sequence with vseq.start(null) from a test task, its full name is just vseq, so the sub-sequence is vseq.pkt. The override pattern must follow that chain:

    design.sv
    // snippet: replace only the packet sequence inside the vseq
    axis_pkt_seq::type_id::set_inst_override(axis_burst_seq::get_type(), "vseq.pkt");

    Common pitfall

    The factory path of an object is fixed at the moment of create. If a sequence creates its items in body() after start(), get_full_name() already includes the sequencer or parent. If it creates them in its constructor or before start, the context is incomplete and path-scoped overrides miss.

    Watch it run

    The bench as shipped uses type overrides only, so its evidence is the familiar truncation line. With the context change and the instance override in place, two things confirm the override: items from in_agt report get_type_name() as axis_err_item (log it from the driver at UVM_HIGH), and debug_create_by_type for the item's path shows the match:

    design.sv
    // snippet: confirm which item class a path resolves to
    uvm_factory::get().debug_create_by_type(axis_item::get_type(),
                                            "uvm_test_top.env.in_agt.sqr.pkt", "it");

    The scoreboard's numbers are also a check: an error item that changes only data bits leaves the word count unchanged, so the line 8 words matched, 0 mismatched from a smoke-style run should still appear, because the scoreboard predicts from the observed input words.

    Choosing the scope of a stimulus override

    Goal

    Override

    Requirement

    Every item of a type, everywhere (including monitors' items)

    Type override

    None

    Items from one agent's sequences only

    Instance override at ...<agent>.sqr.*

    Items created with get_full_name() as context

    One sequence inside a virtual sequence

    Instance override at the parent chain, such as vseq.pkt

    Sub-sequence created with the parent's full name as context

    A different sequence class for one test

    Type override on the sequence class

    The replacement extends the original and keeps its knobs

    The last row is often the cleanest: a test that wants bursty packets type-overrides axis_pkt_seq with a subclass whose constraints differ. Every place that creates the packet sequence through the factory picks it up, and the replacement keeps the n field that callers randomize.

    What breaks: the override aimed at the wrong address

    A team wanted error items on one of two identical stream agents. They wrote set_inst_override_by_type(axis_item::get_type(), axis_err_item::get_type(), "uvm_test_top.env.in_agt.*"), reran, and saw no error items. The pattern was fine: * matches dots, so it would have covered uvm_test_top.env.in_agt.sqr.pkt.it. But the sequence created its items with no context, so the path the factory actually saw for each item was just it, which matches nothing under in_agt. One call to debug_create_by_type with the item's real context showed the gap between the address the team imagined and the one the code produced.

    Two habits prevent this: always pass get_full_name() as the context when creating items and sub-sequences, and write object override patterns from the sequencer path down (...in_agt.sqr.*). When the target is "every item of this type everywhere", use a type override and skip paths entirely.

    Interview

    "How do you override a sequence item for one agent only?"

    A weak answer: "Use an instance override with the agent's path."

    A strong answer: "Objects only have a factory path if you give them one, so the sequence creates items with create(name, null, get_full_name()). A started sequence's full name is its sequencer's path plus its name, or its parent sequence's full name if it has one. Then I register set_inst_override for axis_item at uvm_test_top.env.in_agt.sqr.*, and the other agent's items are untouched. For a sequence inside a virtual sequence the path follows the parent chain, like vseq.pkt. I confirm with debug_create_by_type."

    Follow-ups: Why might the override still miss? (items created before start, or no context) and When is a type override the better choice? (when every instance should change).

    Check yourself A sequence started on uvm_test_top.env.in_agt.sqr with parent null is named pkt. It creates axis_item::type_id::create("it", null, get_full_name()). What path does the factory resolve?

    uvm_test_top.env.in_agt.sqr.pkt.it. A started top-level sequence's full name is the sequencer's full name plus its own name; the item's path is that context plus .it.

    Check yourself The same pkt is started from a virtual sequence with pkt.start(in_sqr, this), and the virtual sequence was started with vseq.start(null). Does an instance override at uvm_test_top.env.in_agt.sqr.* reach its items?

    No. With a parent, pkt's full name is the parent's full name plus .pkt, here vseq.pkt, so its items live at vseq.pkt.it. The override pattern must match that chain, for example vseq.pkt.*, or *.pkt.it if you accept the broader reach.

    Check yourself Why does the bench's monitor create its items without a context, and is that a problem?

    Nobody needs to override a monitor's items per path: a monitor reports what it saw, and changing its item class would change what subscribers receive everywhere. A type override still reaches it if ever needed. Contexts matter for stimulus objects, where per-agent variation is common.

    Next: the factory decides which class is built. The other half of reusable benches is deciding how each instance is configured: config_db and resources.

    Related topics

    • The type_id::create pattern

    • Configuring sequences

    • Virtual sequences

    • Layered and derived items

    Previous

    52 / 280

    Next: config_db and Resources

    Up next

    Up nextconfig_db and Resources

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • The Factory: Swapping Classes Without Editing the Env
    • Registration Macros: What uvm_component_utils Writes for You
    • The type_id::create Pattern