Part 9 · Register Model (RAL) · Intermediate
Desired vs Mirrored Theory
Two-value model fundamentals: what desired and mirrored represent, how each method changes them, and where policy/volatility alter expectations.
Mental model: intent vs belief
Treat desired as a queued software intent and mirrored as the model's best current estimate of hardware state. These values may intentionally diverge between staging and commit operations.
During a healthy frontdoor flow, divergence is temporary and explainable: set() changes desired only, update() drives bus and then mirror catches up via write response/predictor, read() may correct mirror from DUT observation.
desired changes on set(), write(value), and explicit set-like APIs.
mirrored changes on predict(), read(), mirror(), and successful write semantics.
Divergence is expected during planning; persistent divergence after synchronization is a signal.
Volatile and side-effect fields require policy-aware interpretation of mirror values.
Two-value model chart
Use this chart as a ground truth when reviewing code. If a method's expected value transition in logs does not match this table, your model assumptions are wrong.
[RAL] two-value model chart (single field perspective)
Method / Event Bus access? desired after call mirrored after call
─────────────────────────────────────────────────────────────────────────────────────────────
set(v) No v unchanged
get() No returns desired unchanged
get_mirrored_value() No unchanged returns mirrored
update(status) Maybe unchanged if write occurs: aligns to desired
write(status, v) Yes v expected to become v on success
read(status, v_out) Yes policy-dependent becomes observed DUT value
predict(v) No usually unchanged becomes v
mirror(status, UVM_CHECK) Yes unchanged becomes observed value if read succeeds
mirror(status, UVM_NO_CHECK)Yes unchanged becomes observed value
Notes:
- update() issues bus write only when desired != mirrored (per relevant map/policy).
- policy-dependent desired updates vary by register/field behavior and access policy.[UVM] transition timeline example
Initial reset:
desired=0x00, mirrored=0x00
Test plans new config:
set(0x2D) -> desired=0x2D, mirrored=0x00
Commit staged value:
update() -> bus write 0x2D
desired=0x2D, mirrored=0x2D
External master writes 0x3A:
DUT=0x3A, desired=0x2D, mirrored still 0x2D (until predictor/read)
Predictor sees monitor txn:
predict(0x3A) -> mirrored=0x3A (desired unchanged)
Interpretation:
Divergence desired!=mirrored now means software intent differs from observed state,
not necessarily a bug.SystemVerilog walk-through
The snippet below demonstrates intentional divergence and re-synchronization. Keep this style in diagnostics: print desired and mirrored before and after each operation.
task show_two_value_model(my_reg_block ral, uvm_component parent);
uvm_status_e status;
uvm_reg_data_t rd;
// Assume reset values are 0.
`uvm_info("MIRROR", $sformatf("init desired=0x%0h mirrored=0x%0h",
ral.ctrl.get(), ral.ctrl.get_mirrored_value()), UVM_LOW)
// Stage intent only.
ral.ctrl.set('h2D);
`uvm_info("MIRROR", $sformatf("after set desired=0x%0h mirrored=0x%0h",
ral.ctrl.get(), ral.ctrl.get_mirrored_value()), UVM_LOW)
// Commit staged intent through bus.
ral.ctrl.update(status, UVM_FRONTDOOR, .parent(parent));
`uvm_info("MIRROR", $sformatf("after update desired=0x%0h mirrored=0x%0h status=%s",
ral.ctrl.get(), ral.ctrl.get_mirrored_value(), status.name()),
UVM_LOW)
// Fresh bus read updates mirror with observed value.
ral.ctrl.read(status, rd, UVM_FRONTDOOR, .parent(parent));
`uvm_info("MIRROR", $sformatf("after read desired=0x%0h mirrored=0x%0h rd=0x%0h",
ral.ctrl.get(), ral.ctrl.get_mirrored_value(), rd), UVM_LOW)
endtaskInterpreting divergence correctly
desired != mirrored can mean staged-but-not-committed intent (normal).
mirrored stale after external write means missing predictor/readback (plumbing issue).
mirrored changes while desired static often indicates explicit prediction from monitor traffic.
After mirror(UVM_CHECK), mismatch message uses mirrored as expected baseline.
Volatile and side-effect fields
Two-value logic is straightforward for plain RW fields and subtle for volatile/W1C/RC fields. Policy semantics determine whether mirrored should be expected to track software intent or hardware-side evolution.
[RAL] policy-aware expectations
RW field:
expected steady state: desired == mirrored (after sync)
Volatile status counter:
mirrored may age quickly without fresh predictor/read.
desired is often irrelevant for pass/fail.
W1C interrupt bit:
desired write of 1 means "request clear", not "store 1".
mirror should reflect post-side-effect state.
RC field:
read itself causes state change; mirror update must model clear-on-read behavior.
Implication:
Always evaluate failures through access policy before blaming predictor wiring.// Example: W1C field modeling concept
class status_reg extends uvm_reg;
`uvm_object_utils(status_reg)
rand uvm_reg_field intr;
function new(string name = "status_reg");
super.new(name, 32, UVM_NO_COVERAGE);
endfunction
virtual function void build();
intr = uvm_reg_field::type_id::create("intr");
// access = W1C, reset = 0
intr.configure(this, 1, 0, "W1C", 0, 1'b0, 1, 1, 0);
endfunction
endclassKey takeaways
desired and mirrored are complementary, not redundant.
A divergence is information; classify it before treating it as failure.
Policy semantics define what 'correct mirror behavior' means for non-RW fields.
Print both values in logs to avoid chasing phantom mismatches.
Common pitfalls
Expecting volatile fields to stay equal without prediction/readback.
Treating W1C desired=1 as expected mirrored steady state.
Using get() in debug output when investigating mirror drift.