Part 9 · Register Model (RAL) · Intermediate
Mirror Drift Debug Playbook
Deterministic checklist for false failures: classify drift, gather evidence, validate wiring/policies, and isolate root cause quickly.
Classify drift before fixing
Mirror drift means mirrored value no longer matches expected hardware state. First classify by symptom; each class points to a different root-cause cluster.
[UVM] mirror drift symptom taxonomy
Class A: stale mirror
mirror unchanged while monitor shows writes
likely predictor wiring/filter issue
Class B: wrong-bit mirror
mirrored differs by lanes or bit slices
likely adapter bus2reg mapping/endianness issue
Class C: policy drift
mismatch appears on W1C/RC/volatile fields
likely model access policy mismatch
Class D: timing/concurrency drift
checks fail only under parallel traffic
likely race with external writers or checkpoint placement
Class E: false compare baseline
mirror(UVM_CHECK) called after stale period without resync
expected side stale, observed side correctDo not patch blindly with extra reads; classify first.
Capture first failure with fixed seed and narrow time window.
Repeatability is more valuable than one-off pass after ad hoc edits.
Checklist for false failures
Run this checklist top-down. It is optimized for speed and prevents common detours.
[CHECK] false-failure triage checklist (use in order)
1) Prediction mode sanity
- Is set_auto_predict intentionally configured?
- If explicit mode: is predictor connected and active?
2) Wiring integrity
- predictor.map assigned?
- predictor.adapter assigned?
- monitor.ap connected to predictor.bus_in?
3) Transaction visibility
- Does monitor print transaction for failing address?
- Is transaction filtered out before predictor?
4) Adapter correctness
- bus2reg kind/addr/data/status correct?
- endianness/byte lanes aligned to map?
5) Access policy and field metadata
- RW/RO/W1C/RC correct in model?
- volatile bits marked properly?
6) Checkpoint timing
- Is mirror(UVM_CHECK) racing with concurrent writer?
- Should check move to quiescent boundary?
7) Resync experiment
- Run mirror(UVM_NO_CHECK) once before strict compare.
- If this clears failure, root is stale baseline, not immediate DUT corruption.
8) Path isolate
- Compare frontdoor and backdoor mirror results.
- Divergence suggests bus-path issue; convergence suggests mirror baseline issue.[CHECK] evidence packet to attach in bug report
- failing register full name and address
- expected(mirrored) vs observed(read) values
- desired value at failure time
- prediction mode (auto or explicit)
- last 3 monitor transactions for same address
- adapter bus2reg log line for failing transaction
- field access policy metadata
- whether failure reproduces with same seedInstrumented debug helpers (SystemVerilog)
Add narrow, deterministic instrumentation around the suspect register. Avoid flooding logs globally; localized traces preserve signal-to-noise.
task dump_reg_state(uvm_reg rg, string tag = "DBG");
uvm_reg_data_t des, mir;
des = rg.get();
mir = rg.get_mirrored_value();
`uvm_info(tag, $sformatf("%s desired=0x%0h mirrored=0x%0h",
rg.get_full_name(), des, mir), UVM_LOW)
endtask
task check_with_context(uvm_reg rg, uvm_path_e path, uvm_component parent);
uvm_status_e status;
dump_reg_state(rg, "PRE_MIRROR");
rg.mirror(status, UVM_CHECK, path, .parent(parent));
dump_reg_state(rg, "POST_MIRROR");
if (status != UVM_IS_OK)
`uvm_error("MIRROR_CTX", $sformatf("mirror check failed on %s", rg.get_full_name()))
endtaskclass debug_predictor_tap extends uvm_subscriber #(apb_item);
`uvm_component_utils(debug_predictor_tap)
virtual function void write(apb_item t);
if (t.addr == 'h0040) begin
`uvm_info("PRED_TAP",
$sformatf("addr=0x%0h data=0x%0h write=%0d", t.addr, t.data, t.write), UVM_LOW)
end
endfunction
endclassMinimal intrusive debug strategy
Trace one failing register path end-to-end before broad instrumentation.
Add temporary taps on monitor stream instead of modifying predictor internals first.
Keep debug code behind config knobs so it can stay reusable.
Case studies and closure criteria
These patterns appear repeatedly in production teams. Recognize them early to close issues faster.
Case 1: Missing predictor connection
Symptom:
mirror checks fail only after external firmware writes
Fix:
connect monitor.ap -> predictor.bus_in and disable auto_predict
Case 2: bus2reg addr truncation
Symptom:
failures cluster every 0x100 boundary, wrong register mirror updated
Fix:
correct adapter address width/mask logic
Case 3: W1C modeled as RW
Symptom:
mirror keeps sticky 1 while DUT cleared by write-1
Fix:
update field access policy to W1C and regenerate model
Case 4: compare timing race
Symptom:
intermittent mismatches only under high parallel traffic
Fix:
move mirror(UVM_CHECK) to quiescent phase boundary or lock writer schedule[RAL] closure criteria before declaring fix complete
- failing seed reproduces pre-fix and passes post-fix
- at least one neighboring seed also passes
- mirror(UVM_CHECK) no longer fails for affected register class
- predictor/adapter logs match expected value transitions
- no new regressions in built-in RAL sequences (reset/access/bit_bash)Key takeaways
Most mirror drift bugs are deterministic once classified correctly.
A fixed checklist removes guesswork and accelerates root-cause isolation.
False failures usually trace to stale baseline, adapter mapping, or policy mismatch.
Close fixes with reproducible seed evidence and targeted regression checks.
Common pitfalls
Masking drift by adding ad hoc reads everywhere.
Debugging with changing seeds and losing reproducibility.
Declaring fix after one pass without checking neighboring scenarios.