Skip to content

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 probepoke a known value, peek it back, and cross-check a frontdoor read; agreement proves the path reaches the right storage.
  • Symptom triage:
    • peek reads X / poke has no effect -> the path does not resolve to real storage: a typo, wrong hdl_path root, 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:

Backdoor triage: prove resolution, then X/no-effect = unresolved, stale-vs-index = not indexed, disagrees-frontdoor = wrong placeX / no-effectstale vsindexvs frontdoorPROVE the path resolves first (HDL-path check / poke-known-value probe)PROVE the pathresolves first(HDL-path check/…Classify thesymptompeek X / poke no-effect -> path does NOT resolve (wrong root/hierarchy/slice/typo)peek X / pokeno-effect ->path does NOTresolve (wrong…stale/constant regardless of index -> memory path not indexed (8.4) / constant signalstale/constantregardless ofindex -> memorypath not indexe…disagrees with known-good frontdoor -> resolves to the WRONG register/bitdisagrees withknown-goodfrontdoor ->resolves to the…KEY: 'does not resolve' (loud X/no-effect) vs 'resolves to WRONG place' (subtle, plausible-but-wrong)KEY: 'does notresolve' (loudX/no-effect) vs'resolves to…
Figure 1 — triaging a backdoor failure. First PROVE the path resolves (built-in HDL-path check, or a poke-known-value/peek-back probe cross-checked with a frontdoor read). Then classify the symptom: peek X or poke no-effect -> the path does NOT resolve (wrong root/hierarchy/slice/typo) — the X is the absence of a path, not a held value; stale/constant regardless of index -> a memory path not indexed (8.4) or a constant signal; backdoor disagrees with a known-good frontdoor -> the path resolves to the WRONG register/bit. The essential distinction: 'does not resolve' (loud: X/no-effect) vs 'resolves to the wrong place' (subtle: a plausible but wrong value). Never read meaning into an unproven backdoor value.

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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// 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)
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// 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
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// 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

1

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
Buggy Code
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// 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.
Symptom

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.

Root Cause

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.

Fix

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_seq in 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/poke reach RTL storage through the hdl_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: peek X / poke no-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_path root/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.