Skip to content

UVM RAL · Chapter 3 · Register Maps

Map Debugging

The address map is where whole-block bugs live: wrong offsets, overlaps, unreachable registers, wrong access, and bad reset values. These are structural faults, and a systematic sweep catches them where a hand-written test misses them. RAL ships a small library of built-in register test sequences that walk every register and check it: hardware reset compares reset values, bit-bash writes and reads back every accessible bit to catch stuck bits and overlaps, access sequences compare frontdoor against backdoor, and shared-access sequences keep aliased registers coherent. Their power is their coverage, but that is also their hazard, since a blind sweep trips side effects and mishandles volatile or write-only fields. This lesson covers each sequence and how to exclude the registers that must not be swept, then breaks a bit-bash over a W1C interrupt register that produces false failures and clears real interrupts.

Foundation12 min readUVM RALMap Debuggingbit_bashhw_resetBuilt-in SequencesNO_REG_TESTS

Chapter 3 · Section 3.5 · Register Maps

1. Why Should I Learn This?

The map bugs from this chapter are structural and block-wide, and the fastest, most reliable way to find them is not a clever hand-written test but a systematic sweep that touches every register. RAL gives you those sweeps for free, and knowing them turns 'is my map correct?' from an anxious manual audit into a few sequences you run and read the failures from. Bit-bash alone catches offset overlaps, unreachable registers, stuck bits, and wrong access policies across the whole block in one pass.

But the sweeps are powerful enough to be dangerous — they write and read everything — so learning them means learning to exclude the registers that a blind sweep would corrupt or false-fail: side-effecting, volatile, and write-only ones. Knowing both halves — which sequence catches which fault, and which registers to skip — is what lets you verify a map thoroughly without the sweep itself becoming a source of failures.

2. Industry Story — the bit-bash that acknowledged every interrupt

An engineer, wanting to verify a new block's map, runs the full built-in suite — hw_reset, then bit_bash, then access — across the whole model, exactly as recommended. hw_reset passes. bit_bash then begins writing and reading back every bit of every register to prove each is writable and readable, and it reaches INT_STATUS, a register full of W1C interrupt bits that hardware sets and software clears.

Two things go wrong at once. Bit-bash writes ones to those bits to test writability, and because they are W1C, every write clears whatever interrupts were pending — so the sweep silently acknowledges real interrupts that other parts of the environment were tracking, corrupting the test. And bit-bash expects the written value to read back (it is proving the bit is a plain writable bit), so on a W1C bit — which reads back cleared, not set — it reports a false failure: 'bit not writable.' The engineer now has a red bit-bash report full of false failures on every interrupt and status register, plus a downstream test failing because its interrupts vanished, and spends a day deciding whether the map is broken (it is not) or the RTL is (it is not). The cause is that bit-bash's write-and-read-back model does not apply to W1C, RC, RO, or write-only fields, and those registers should have been excluded from the sweep. The lesson: the built-in sweeps assume plain read-write, memory-like behaviour, so registers with side effects, volatility, or non-RW access must be excluded with NO_REG_TESTS (and its finer-grained siblings) — or the sweep both false-fails and corrupts state.

3. Concept — the built-in sweeps and what to skip

RAL's built-in register test sequences each walk the map and target a fault class:

  • uvm_reg_hw_reset_seq — resets the DUT and reads every register, comparing against the modelled reset (1.3). Catches wrong reset values, bad tie-offs, and mis-transcribed resets.
  • uvm_reg_bit_bash_seq — writes and reads back every accessible bit of every register, proving each bit is writable/readable per its access policy. Catches stuck bits, wrong access policies, and — because it reads each register's own value back — offset overlaps, aliasing errors, and unreachable registers (a register that reads back a neighbour's value fails).
  • uvm_reg_access_seq — writes each register and reads it back both frontdoor and backdoor, comparing. Catches addressing errors, adapter/byte-lane bugs, and wrong HDL backdoor paths (frontdoor and backdoor disagree).
  • uvm_reg_shared_access_seq / mem-shared sequences — exercise registers reachable through multiple maps or aliases, checking they stay coherent (3.2, 3.4).
  • uvm_mem_walk_seq — walks memories to check addressing across the whole array.

And the other half — exclusion. These sweeps assume plain, memory-like RW behaviour, so you must skip registers that are not: use the NO_REG_TESTS attribute (or finer ones like NO_REG_BIT_BASH_TEST, NO_REG_HW_RESET_TEST, NO_REG_ACCESS_TEST) to exclude side-effecting (RC, FIFO), volatile (hardware-updated status), write-only (WO), and interrupt (W1C/W1S) registers from the sweeps that would misbehave on them. Here is the library and what each catches:

Built-in register test sequences: hw_reset, bit_bash, access, shared-access, and the exclusion attributeuvm_reg_hw_reset_seq — reset valuesreset the DUT, read every register, compare vs modelled reset; catches wrong defaults and bad tie-offs (1.3)reset the DUT, read every register, compare vs modelled reset; catches wrong defaults and bad tie-offs (1.3)uvm_reg_bit_bash_seq — every bit + reachabilitywrite/read-back every bit per its access; catches stuck bits, wrong access, and offset overlaps / unreachable registerswrite/read-back every bit per its access; catches stuck bits, wrong access, and offset overlaps / unreachable registersuvm_reg_access_seq — frontdoor vs backdoorwrite and read each register both paths and compare; catches addressing, byte-lane, and HDL backdoor-path errorswrite and read each register both paths and compare; catches addressing, byte-lane, and HDL backdoor-path errorsuvm_reg_shared_access_seq — aliases / multi-mapexercise registers reached via multiple maps/aliases; checks they stay coherent (3.2, 3.4)exercise registers reached via multiple maps/aliases; checks they stay coherent (3.2, 3.4)NO_REG_TESTS — exclude non-RW registersside-effecting (RC/FIFO), volatile status, write-only, and W1C/W1S interrupt registers must be excluded or the sweeps false-fail / corrupt stateside-effecting (RC/FIFO), volatile status, write-only, and W1C/W1S interrupt registers must be excluded or the sweeps false-fail / corrupt state
Figure 1 — RAL's built-in register test sequences and the fault class each catches. hw_reset checks reset values; bit_bash proves every bit writable/readable and, by reading each register's own value back, catches overlaps and unreachable registers; access compares frontdoor vs backdoor to catch addressing/path errors; shared-access checks aliased/multi-map coherence. All assume plain RW behaviour, so side-effecting, volatile, write-only, and interrupt registers must be EXCLUDED (NO_REG_TESTS) or the sweep false-fails and corrupts state.

4. Mental Model — sweep everything, but tell the sweep what it must not touch

5. Working Example — running the sweeps, and excluding what must be skipped

First, mark the registers a sweep must not touch — set the exclusion attribute where the register is built:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// In the block's build(), flag registers the sweeps must skip.
virtual function void build();
  // ... create/configure/build registers, create map, add_reg, lock ...
 
  // INT_STATUS is W1C (interrupts) — exclude from bit-bash (and usually all sweeps).
  uvm_resource_db#(bit)::set({"REG::", int_status.get_full_name()},
                             "NO_REG_TESTS", 1, this);
  // EVENT_COUNT is RC (read-clears) — exclude so the sweep does not drain it.
  uvm_resource_db#(bit)::set({"REG::", event_count.get_full_name()},
                             "NO_REG_TESTS", 1, this);
  // KEY is WO (write-only) — exclude from bit-bash's read-back check specifically.
  uvm_resource_db#(bit)::set({"REG::", key.get_full_name()},
                             "NO_REG_BIT_BASH_TEST", 1, this);
endfunction

Then run the built-in suite over the model — the sweeps walk every register except those excluded:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// In a test's run_phase: verify the map with the built-in library.
uvm_reg_hw_reset_seq  rst  = uvm_reg_hw_reset_seq::type_id::create("rst");
uvm_reg_bit_bash_seq  bash = uvm_reg_bit_bash_seq::type_id::create("bash");
uvm_reg_access_seq    acc  = uvm_reg_access_seq::type_id::create("acc");
 
rst.model  = reg_model;  rst.start(bus_sequencer);   // reset values across the block
bash.model = reg_model;  bash.start(bus_sequencer);  // every bit + overlaps/reachability
acc.model  = reg_model;  acc.start(bus_sequencer);   // frontdoor vs backdoor
// The excluded W1C/RC/WO registers are skipped, so no false failures and no drained state.

The sweeps do the walking; the exclusions keep the sweeps honest on the registers whose behaviour is not plain read-write. Together they verify the map thoroughly without the sweep itself becoming a bug source.

6. Debugging Session — the bit-bash over the interrupt register

1

Running bit-bash over a W1C interrupt register produces false 'not writable' failures and clears real pending interrupts

SWEEP WITHOUT EXCLUSION
Buggy Code
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// The whole model is bit-bashed with NO exclusions. INT_STATUS is full of W1C bits.
uvm_reg_bit_bash_seq bash = uvm_reg_bit_bash_seq::type_id::create("bash");
bash.model = reg_model;
bash.start(bus_sequencer);   // BUG: bit-bash writes 1s to W1C bits (clearing interrupts)
                             //      and expects them to read back 1 (they read 0 -> false fail)
// Result: false 'INT_STATUS bit not writable' errors, AND pending interrupts silently cleared.
Symptom

The bit-bash report is red with 'bit not writable' failures on every interrupt and status register, while plain RW registers pass — and, separately, a downstream part of the test that was tracking interrupts starts failing because its pending interrupts have vanished. It looks like the map or the RTL has a swathe of broken bits, and time is spent deciding whether to trust a report that is failing on registers that are, in fact, behaving exactly as specified. The two symptoms (false failures + missing interrupts) point at the same cause but look like two different bugs.

Root Cause

Bit-bash assumes plain read-write behaviour: it writes a value to a bit and expects to read that value back, proving the bit is writable and readable. That model is wrong for W1C (and W1S, RC, RO, WO). On a W1C bit, writing 1 clears the bit, so it reads back 0, not 1 — bit-bash sees the mismatch and reports 'not writable,' a false failure, when the bit is behaving correctly. Simultaneously, those 1-writes are real clears: they acknowledge whatever interrupts were pending, corrupting state the rest of the environment depended on. The map and RTL are correct; the sweep applied a memory-like test to registers whose access policy is not memory-like, and it both mis-judged and disturbed them because they were never excluded.

Fix

Exclude the non-RW registers from the sweep with the NO_REG_TESTS attribute (or the finer NO_REG_BIT_BASH_TEST), as in Section 5, so bit-bash skips the W1C interrupt registers, the RC counters, the WO keys, and the volatile status — no false failures and no cleared interrupts. Where such a register's behaviour still needs checking, write a targeted policy test for it (the clear, the read-clear, the write-no-readback) rather than the generic sweep. The rule the bug teaches: the built-in sweeps assume memory-like RW behaviour, so exclude every register that is not — side-effecting, volatile, write-only, interrupt — or the sweep both false-fails on them and corrupts their state. A red sweep report full of failures on registers that are behaving per spec is a missing-exclusion problem, not a map problem.

7. Common Mistakes

  • Running sweeps without exclusions. Bit-bash false-fails on W1C/RC/RO/WO and clears interrupts / drains counters.
  • Hand-auditing a map instead of sweeping it. The built-in sequences catch structural faults (overlaps, unreachable, reset) far more reliably.
  • Excluding too much. Blanket-excluding registers hides real bugs; exclude only the specific sequences that misbehave on a given register.
  • Ignoring the frontdoor-vs-backdoor access sequence. It is what catches addressing and HDL-path errors that bit-bash alone can miss.
  • Treating a red sweep on spec-correct registers as a DUT/map bug. It is usually a missing exclusion, not a real failure.

8. Industry Best Practices

  • Verify every map with the built-in suite. hw_reset, bit_bash, access, and shared-access as a standard map-bring-up step.
  • Exclude non-RW registers precisely. Use NO_REG_TESTS and the finer per-sequence attributes for side-effecting, volatile, write-only, and interrupt registers.
  • Run the reset sweep first. Cheapest and highest-yield; it catches power-on defects before the writing sweeps run.
  • Add targeted policy tests for excluded registers. A W1C/RC/WO register skipped by the sweep still needs its own behaviour checked.
  • Read a red sweep critically. Failures clustered on non-RW registers usually mean a missing exclusion, not a broken map.

9. Interview / Review Questions

10. Key Takeaways

  • Map bugs are structural and block-wide, so verify a map with systematic sweeps, not hand-written per-register tests.
  • The built-in library: hw_reset (reset values), bit_bash (every bit writable/readable, plus overlaps and unreachable registers via read-back-your-own-value), access (frontdoor vs backdoor), shared_access (aliases/multi-map coherence).
  • The sweeps assume plain read-write, memory-like behaviour, so exclude non-RW registers — side-effecting (RC/FIFO), volatile status, write-only (WO), and interrupt (W1C/W1S) — with NO_REG_TESTS and its finer siblings.
  • Sweeping a non-RW register both false-fails (its read-back does not match the memory-like expectation) and corrupts state (clearing interrupts, draining counters).
  • A red sweep report whose failures track access policy rather than address structure is a missing-exclusion problem, not a broken map; add targeted policy tests for the excluded registers.