Skip to content
VLSI Mentor

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.

Standards & specifications

Governing standard
IEEE Std 1800.2 (UVM)(opens IEEE in a new tab)

Defines the UVM class library's API and semantics. Testbench structure, naming conventions and project methodology around that API are engineering practice, not requirements of the standard.

Reference implementation
Accellera UVM reference implementation(opens Accellera Systems Initiative in a new tab)

The open-source class library and user guide that most simulators ship. Useful alongside IEEE 1800.2 when a page discusses the implementation rather than the standardised API.

This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.

Where this fits

Part of the UVM RAL curriculum.