UVM RAL · Chapter 11 · Debugging RAL
Backdoor Path Debug
Backdoor peek and poke reach a register's RTL storage directly through its HDL path, bypassing the bus, adapter, mirror, and prediction, so a backdoor bug lives in one place: the path does not resolve to the storage you intended. The discipline is simple. Never trust a backdoor value you have not proven resolves. The symptom family is small too. A peek that reads X or a poke with no effect means the path reaches nothing. A value that stays constant regardless of index means a memory path was not indexed. A value that disagrees with a known-good frontdoor read means the path resolves, but to the wrong place. This lesson teaches proving resolution with a known-value probe and the built-in path check, and breaks a peek X from a wrong root that gets misread as a reset bug.
Foundation12 min readUVM RALdebuggingbackdoorhdl_pathresolution
Chapter 11 · Section 11.4 · Debugging RAL
1. Why Should I Learn This?
The backdoor bypasses the bus, adapter, mirror, and prediction, so when a backdoor value is wrong the cause is almost always the hdl_path not resolving — and a backdoor value you have not proven resolves can silently mislead every setup and check that relies on it (8.4). Knowing the small symptom family (X/no-effect, stale-regardless-of-index, disagrees-with-frontdoor) and the prove-it-resolves discipline is what keeps you from building on a path that reaches nothing or the wrong thing.
Learning backdoor path debugging completes the debug quartet: 11.1–11.3 handle the bus-path layers, and this handles the HDL-path layer that sits entirely outside them — and it is the one whose failures most often masquerade as DUT bugs.
2. Industry Story — the reset 'bug' that was an X from nowhere
A team's backdoor peek of a register out of reset returns X. The reading is immediate: 'the DUT is not resetting this register — bit-level X means uninitialized hardware,' and a reset bug is filed against the RTL. A designer investigates correct reset logic for a day, because the register does reset properly.
The peek returned X not because the register held X, but because the hdl_path did not resolve — the hdl_path root was wrong (a mis-named hierarchy level), so the backdoor read reached nothing, and 'nothing' reads as X. The X was not a value the register held; it was the absence of a resolved path. The team misread an unresolved path as a DUT reset bug, chasing hardware that was fine. Running the built-in HDL-path check would have flagged the path as unresolvable in seconds; a known-value probe (poke a value, peek it back) would have shown the poke had no effect — the tell of a path reaching nothing. Once the root was corrected, the peek returned the register's real (correct) reset value. The post-mortem lesson: a backdoor X is usually an unresolved hdl_path (wrong root/hierarchy/slice), not a DUT value — an X is the absence of a resolved path, not 'the register holds X'; never read meaning into a backdoor value you have not proven resolves, and verify paths with the built-in HDL-path check or a known-value probe before trusting (or blaming the DUT for) any backdoor result.
3. Concept — prove resolution; separate 'unresolved' from 'wrong place'
A backdoor failure is a path-resolution failure. The method: prove the path resolves, and classify the symptom.
- The discipline: prove it resolves first. Do not read meaning into any backdoor value until the path is proven to resolve. Two tools:
- the built-in HDL-path check (
uvm_reg_mem_hdl_paths_seq, 4.7) — validates that every register's path resolves; - a known-value probe —
pokea known value,peekit back, and cross-check a frontdoor read; agreement proves the path reaches the right storage.
- the built-in HDL-path check (
- Symptom triage:
peekreads X /pokehas no effect -> the path does not resolve to real storage: a typo, wronghdl_pathroot, missing hierarchy level, or wrong slice width. The X is absence of a path, not a held value.- Value stale/constant regardless of index -> for a memory, the path is not indexed per location (8.4); or the path resolves to a constant signal.
- Backdoor disagrees with a known-good frontdoor -> the path resolves, but to the wrong register/bit.
- The key distinction: does not resolve (X / no-effect — loud, obviously broken) vs resolves to the wrong place (a consistent, plausible, wrong value — subtle and dangerous, because it looks like a real value).
Here is the backdoor symptom-triage flow:
4. Mental Model — a backdoor value is only meaningful once the address is proven real
5. Working Example — proving resolution with a known-value probe
Prove the path resolves before trusting it, and classify a failure by symptom:
// PROVE RESOLUTION with a known-value probe: poke a chosen value, peek it back, cross-check frontdoor.
uvm_reg_data_t pk, fd; uvm_status_e s;
reg_h.poke(s, 32'hA5A5_1234); // write a KNOWN value directly to storage
reg_h.peek(s, pk); // read it back the backdoor way
reg_h.read(s, fd); // and a frontdoor read for cross-check
if (pk !== 32'hA5A5_1234)
`uvm_error("BKDDBG", "poke had NO EFFECT / peek != poked value -> path does NOT resolve (wrong root/slice)")
else if (fd !== pk)
`uvm_error("BKDDBG", "peek != frontdoor -> path RESOLVES but to the WRONG register/bit")
else
`uvm_info("BKDDBG", "poke==peek==frontdoor -> path PROVEN to resolve to the intended storage", UVM_LOW)// Or use the built-in HDL-path check to validate ALL paths resolve before relying on any of them (4.7):
uvm_reg_mem_hdl_paths_seq hp = uvm_reg_mem_hdl_paths_seq::type_id::create("hp");
hp.model = reg_model;
hp.start(null); // reports registers whose hdl_path does not resolve — run this BEFORE trusting backdoor// SYMPTOM triage once you observe a failure:
// peek X / poke no-effect -> UNRESOLVED path (typo, wrong root, missing hierarchy, wrong slice)
// stale/constant regardless of i -> memory path NOT INDEXED (8.4) or a constant signal
// backdoor != known-good frontdr -> resolves to the WRONG register/bit
// An X is the ABSENCE of a resolved path — NOT 'the register holds X'. Do not file a DUT bug on an X.The known-value probe (poke/peek/frontdoor agreement) proves the path reaches the intended storage; without that proof, a backdoor value — especially a plausible one — means nothing. The next section is an X misread as a DUT bug.
6. Debugging Session — a peek X misread as a reset bug
A backdoor peek returns X because the hdl_path root is wrong, so the path resolves to nothing — and the X is misread as a DUT reset bug instead of an unresolved path
X = UNRESOLVED PATH, NOT A HELD VALUE// The hdl_path ROOT is wrong (mis-named hierarchy level), so the backdoor reaches NOTHING:
reg_model.default_map.set_hdl_path_root("tb.dutt"); // BUG: 'dutt' — real hierarchy is 'tb.dut'
status_reg.add_hdl_path_slice("status_q", 0, 32);
// A backdoor peek of status_reg resolves to nothing -> returns X. The register itself resets fine.A backdoor peek of a register out of reset returns X. The immediate (wrong) reading is 'the DUT is not resetting this register — X means uninitialized hardware,' and a reset bug is filed against the RTL. A designer investigates the reset logic — which is correct — and finds nothing, because the register does reset properly. The X is constant (every peek returns X, regardless of DUT state), and a poke to the same register has no effect on a subsequent peek — both tells of a path reaching nothing, but they are easy to miss if you have already decided the X is a held value.
The hdl_path did not resolve: the hdl_path root was mis-named (tb.dutt instead of tb.dut), so the backdoor read reached no signal at all, and an unresolved backdoor read returns X. The X is therefore the absence of a resolved path — 'there is nothing at this address' — not the register's value; the register itself holds its correct reset value, reachable only if the path resolves. The failure was misdiagnosed because X was read as a held value (uninitialized hardware -> reset bug) rather than as unresolved-path. Confirming would have been instant: the built-in HDL-path check would flag status_reg's path as unresolvable, and a known-value probe would show a poke has no effect (peek still X) — the definitive signature of a path reaching nothing. It is not a DUT bug, a mirror bug (11.1), a prediction bug (11.2), or an adapter bug (11.3) — those are all bypassed by the backdoor; it is a path-resolution bug in the HDL-path layer.
Correct the hdl_path root to the real hierarchy (tb.dut), so the path resolves to the register's actual storage, and the peek returns the correct reset value. Then prove it with a known-value probe (poke/peek/frontdoor agreement) and run the built-in HDL-path check (uvm_reg_mem_hdl_paths_seq) to validate all paths resolve. The method the debug teaches: a backdoor X is almost always an unresolved hdl_path (wrong root/hierarchy/slice), not a DUT value — an X is the absence of a resolved path, so never file a DUT/reset bug on a backdoor X without first proving the path resolves. More generally: prove resolution (HDL-path check or known-value probe) before trusting any backdoor value, and distinguish unresolved (X / no-effect — loud) from resolves-to-the-wrong-place (plausible but wrong — subtle, caught only by cross-checking against a known-good frontdoor).
7. Common Mistakes
- Reading a backdoor X as a held value. An X is almost always an unresolved path (wrong root/hierarchy/slice) — the absence of a path, not 'the register holds X.' Prove resolution before blaming the DUT.
- Trusting a plausible backdoor value without proof. A path can resolve to the wrong register and return a believable-but-wrong value — cross-check against a known-good frontdoor.
- Not proving resolution first. Run the built-in HDL-path check or a poke-known-value/peek-back probe before relying on any backdoor read.
- Missing memory indexing. A backdoor value stale/constant regardless of index is an unindexed memory path (8.4), not a data bug.
- Confusing a path bug with mirror/prediction/adapter bugs. The backdoor bypasses all of those — a backdoor failure is a path-resolution bug.
8. Industry Best Practices
- Prove the path resolves before trusting any backdoor value. Known-value probe (poke/peek/frontdoor agreement) or the built-in HDL-path check (4.7).
- Treat a backdoor X as an unresolved path. Check the root, hierarchy, and slice before considering a DUT/reset bug.
- Cross-check backdoor against a known-good frontdoor. Catches a path that resolves to the wrong register — the subtle, plausible-but-wrong case.
- Run
uvm_reg_mem_hdl_paths_seqin bring-up. Validate that every register's path resolves before any test relies on backdoor. - Distinguish unresolved from wrong-place. X/no-effect is loud; a consistent wrong value is subtle — different symptoms, both path bugs.
9. Interview / Review Questions
10. Key Takeaways
- Backdoor
peek/pokereach RTL storage through thehdl_path, bypassing the bus, adapter, mirror, and prediction — so a backdoor failure is an HDL-path resolution bug, a layer apart from 11.1/11.2/11.3. - Never trust a backdoor value you have not proven resolves — use a known-value probe (poke known value / peek back / cross-check frontdoor) or the built-in HDL-path check (
uvm_reg_mem_hdl_paths_seq, 4.7). - Symptom triage:
peekX /pokeno-effect = path does not resolve (wrong root/hierarchy/slice/typo); stale/constant regardless of index = memory path not indexed (8.4) or a constant signal; disagrees with a known-good frontdoor = resolves to the wrong register/bit. - A backdoor X is the absence of a resolved path, not 'the register holds X' — the signature bug is an X misread as a DUT/reset bug when the
hdl_pathroot/hierarchy is wrong; never file a DUT bug on an unproven backdoor X. - Distinguish 'does not resolve' (loud: X/no-effect) from 'resolves to the wrong place' (subtle: plausible-but-wrong) — the second is more dangerous and is caught only by cross-checking against an independent known-good frontdoor, since a backdoor self-round-trip agrees with itself.
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 UVM RAL Debugging — Mirror Mismatches & Access Failures.
