Part 5 · Sequences · Intermediate
Layered Sequences & uvm_sequence_library
Hub — reusable stimulus stacks from beat to virtual scenario, base sequence helpers, start() delegation, uvm_sequence_library registration, and factory overrides.
Overview
Flat tests that duplicate randomize() loops in every scenario become unmaintainable within a single project week. Layered sequences solve this by assigning one concern per level: atomic beats at the bottom, protocol bursts in the middle, multi-agent flows at the top. Higher layers call lower layers with start() or shared base helpers — they do not re-implement the same start_item/finish_item block five times.
This topic breaks layering and libraries into five focused lessons. Each lesson answers a different how question: how to map the beat→burst→flow→vseq stack, how base classes centralize helpers, how start() delegates sub-sequences, how uvm_sequence_library diversifies regressions, and how factory overrides swap library entries without editing the library source.
Lessons in this topic
Layering Stack Overview — beat→burst→flow→vseq diagram and abstraction boundaries.
Base Sequence Helpers — axi_base_seq send_beat() and shared knobs.
Starting Sub-Sequences — axi_four_beat_seq and start() semantics.
Sequence Library Registration — uvm_sequence_library and selection modes.
Factory Library Overrides — set_type_override_by_type for regression variants.
The layering stack
Legend: [STIM] [SEQ] [DRV] [UVM]
┌─────────────────────────────────────────────────────────────────────────┐
│ LAYERING STACK — one concern per level │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ TEST [STIM] chip_stress_test.start_vseq() │
│ │ │
│ ▼ │
│ VSEQ [SEQ] chip_stress_vseq (fork dma + pcie + axi) │
│ │ │
│ ▼ │
│ FLOW [SEQ] axi_burst_flow_seq (N bursts, gaps, backpressure)│
│ │ │
│ ▼ │
│ BURST [SEQ] axi_burst_seq (one burst: len, addr, data[]) │
│ │ │
│ ▼ │
│ BEAT [SEQ] axi_single_seq (one beat: start_item/finish_item)│
│ │ │
│ ▼ │
│ ITEM [UVM] axi_item (rand addr, data, burst_len) │
│ │ │
│ ▼ │
│ SEQUENCER [UVM] → DRIVER [DRV] → DUT pins │
│ │
└─────────────────────────────────────────────────────────────────────────┘Keep this diagram as your map. Every sub-lesson expands one box or arrow — never all five at once.
[STIM] layering vs monolithic — maintenance cost
MONOLITHIC (one 500-line body)
every test copies randomize loops
bug fix in burst logic → edit 40 tests
regression diversity = write 40 new tests
LAYERED (beat → burst → flow → vseq)
fix send_beat once in axi_base_seq
tests start chip_stress_vseq only
uvm_sequence_library randomizes burst mixKey takeaways
Layer: beat → burst → flow → virtual scenario → test — one abstraction per level.
Base sequences centralize send_beat and knobs; derived sequences override body().
start() delegates whole sub-sequences; inline start_item for atomic beats only.
uvm_sequence_library + factory overrides diversify regressions without new tests.
Common pitfalls
Mega-sequence that skips layers — zero reuse, copy-paste across tests.
Sub-sequence started on wrong sequencer — p_sequencer type mismatch.
Library with one sequence type — use a plain sequence instead.
Deep inheritance without base helpers — duplicated start_item blocks everywhere.