UVM RAL · Chapter 6 · Predictors
Why Predictors Matter
The mirror is RAL's running estimate of what the hardware holds, and it is only as honest as RAL's knowledge of what changed that hardware. On its own, RAL only knows the accesses it originates. But hardware is touched by more than RAL: another bus master may write a register, software on an embedded core may configure the block while RAL watches passively, or a different agent may drive the bus entirely. In each case the design changes and the mirror drifts. The predictor closes this gap. It subscribes to the bus monitor and, for every transaction it observes, uses the adapter to reconstruct the operation and update the mirror, so the mirror tracks all register activity on the bus rather than only what RAL drove. This lesson explains why predictors exist and breaks a multi-master scenario where, with no predictor, a second master's write leaves the mirror stale and a later read mismatches.
Foundation11 min readUVM RALPredictorMirrorMonitorMulti-masterPassive
Chapter 6 · Section 6.1 · Predictors
1. Why Should I Learn This?
Every environment beyond the simplest single-master active testbench needs a predictor, because in any realistic setup the hardware is changed by more than RAL's own frontdoor accesses — a second master, an embedded core, a passive-monitoring configuration. Without a predictor, the mirror silently drifts the moment anything other than RAL touches a register, and the drift shows up as a mirror mismatch that looks like a DUT bug but is really the model not knowing about an access it did not drive. Understanding the predictor is what lets you keep the mirror honest in multi-master and passive scenarios, which is most real ones.
Learning why predictors matter — the gap between 'RAL knows its own accesses' and 'the mirror must track all register activity' — sets up the whole chapter: how the two prediction modes work (6.2), and how the predictor is built and connected. It is the component that makes RAL's self-checking survive contact with a real, multi-agent environment.
2. Industry Story — the mirror that missed the other master
A block's registers can be programmed by two masters: the main CPU and a separate DMA engine that also configures a few control registers. The verification environment models CPU accesses with RAL and drives them actively, but does not connect a predictor to the bus monitor — the mirror updates only from RAL's own frontdoor accesses.
A test has the DMA engine (driven by a different agent) write a CTRL register, then has RAL read CTRL to check its state. The read mismatches: the DUT holds the value the DMA wrote, but RAL's mirror still holds the value from the last CPU access (or reset), because nothing told RAL about the DMA's write — the DMA drove the bus, RAL did not, and with no predictor watching the bus, RAL never observed it. The engineer files a CTRL coherency bug against the RTL; the designer bounces it, because the register correctly holds what the DMA wrote. A day is lost before the team realizes the model was blind to the second master: RAL only knows what RAL does, and without a predictor the mirror cannot track an access RAL did not originate. The lesson: the mirror is only honest if RAL learns about every change to the hardware, but RAL only knows its own accesses — a predictor, subscribed to the bus monitor, is what updates the mirror from all observed traffic, including other masters', and without one the mirror drifts on any access RAL did not drive.
3. Concept — the gap RAL cannot see, and the predictor that closes it
The predictor exists because of a gap between two facts:
- The mirror must track all register activity on the bus. Its whole value is being RAL's estimate of what the hardware holds, and the hardware holds whatever the last access left — regardless of who drove that access.
- RAL, on its own, only knows the accesses it originates. A frontdoor
write/readupdates the mirror because RAL performed it. But an access driven by another master, or by software, or by a different agent while RAL watches passively, is invisible to RAL — it did not drive it, so it does not update the mirror for it.
The predictor (uvm_reg_predictor) closes the gap by observing rather than originating: it subscribes to the bus monitor's analysis port, and for every transaction the monitor reports, it calls the adapter's bus2reg (5.2) to reconstruct the register operation and updates the mirror accordingly. So the mirror is maintained from observed traffic — every access on the bus, whoever drove it — not just RAL's own. This is what makes RAL correct under:
- Multiple masters — another master's write updates the mirror because the predictor saw it on the bus.
- Passive monitoring — RAL drives nothing (an embedded core or external stimulus does), and the predictor keeps the whole register model current purely from observation.
Here is the predictor watching the bus and catching traffic RAL did not originate:
4. Mental Model — the mirror needs a witness on the bus, not just a memory of what RAL did
5. Working Example — connecting a predictor so the mirror tracks the bus
The predictor subscribes to the monitor and is given the map and adapter, so it can reconstruct and place observed operations:
// In the env: create the predictor and wire it to the bus monitor.
class my_env extends uvm_env;
uvm_reg_predictor#(apb_item) apb_predictor; // parameterized by the bus item type
// ...
virtual function void build_phase(uvm_phase phase);
// ... build model (build/lock/reset), agent, adapter ...
apb_predictor = uvm_reg_predictor#(apb_item)::type_id::create("apb_predictor", this);
endfunction
virtual function void connect_phase(uvm_phase phase);
reg_model.default_map.set_sequencer(apb_agent.sequencer, apb_adapter);
// Give the predictor the map and adapter, and SUBSCRIBE it to the monitor's analysis port.
apb_predictor.map = reg_model.default_map;
apb_predictor.adapter = apb_adapter;
apb_agent.monitor.ap.connect(apb_predictor.bus_in); // every observed txn -> predictor
endfunction
endclassNow the mirror tracks all bus traffic — including another master's — so a RAL read after an external write is coherent:
uvm_status_e s; logic [31:0] got;
// Another master (a different agent) writes CTRL on the bus. The MONITOR observes it,
// the predictor calls bus2reg and updates the mirror — even though RAL did not drive it.
// ... dma_agent drives a write of 0xABCD to CTRL ...
ctrl.read(s, got); // RAL reads CTRL: DUT holds 0xABCD, and the mirror ALSO holds 0xABCD
// (the predictor updated it from the observed DMA write) -> MATCHBecause the predictor watched the bus, the mirror learned about the other master's write, and the read is coherent. The next section removes the predictor.
6. Debugging Session — the missing predictor and the stale mirror
With no predictor, a register written by another master leaves RAL's mirror stale, so a later RAL read mismatches
NO PREDICTOR// The env connects the map's sequencer + adapter, but NEVER connects a predictor:
reg_model.default_map.set_sequencer(apb_agent.sequencer, apb_adapter);
// (missing) apb_predictor.map/adapter set; monitor.ap.connect(apb_predictor.bus_in);
// A DIFFERENT master writes CTRL on the bus; RAL does not drive it and has no predictor:
// ... dma_agent drives a write of 0xABCD to CTRL ...
ctrl.read(s, got); // DUT = 0xABCD, but RAL's mirror is still the old value (reset / last CPU)
// UVM_ERROR: CTRL mirror mismatch: mirrored <old>, got 0xABCDA RAL read mismatches after a register was changed by something other than RAL — another master, an embedded core, a side-band write. The reported actual value is correct (it is what the other master wrote), and the mirrored value is stale (the last value RAL knew about). It looks like a register coherency bug in the RTL, and a bug filed against the DUT gets bounced because the register correctly holds what the other master wrote. The tell is that the mismatch follows an access RAL did not drive: the DUT is right, the mirror is behind, and RAL had no way to know about the change.
No predictor is connected, so the mirror is updated only by RAL's own frontdoor accesses. When another master writes a register, RAL does not drive the access and has no witness on the bus, so it never learns the register changed and the mirror stays at its last-known value. The DUT is coherent — it holds what the other master wrote — but the model is blind to any access it did not originate. This is the predictor's reason for existing made visible: RAL's self-updates cover only RAL's traffic, and without a predictor watching the bus, the mirror cannot track the other master, so it drifts and the next RAL read mismatches.
Connect a predictor to the bus monitor and give it the map and adapter (Section 5), so the mirror is updated from all observed traffic, not just RAL's. After the DMA write, the predictor reconstructs it via bus2reg and updates CTRL's mirror, so the subsequent RAL read is coherent. The rule the bug teaches: the mirror must track all register activity, but RAL only knows its own accesses, so any environment with a second master, an embedded core, or passive monitoring needs a predictor subscribed to the bus monitor — without one, the mirror drifts on every access RAL did not drive. When a read mismatches after something other than RAL changed a register, suspect a missing predictor.
7. Common Mistakes
- No predictor in a multi-master or passive environment. The mirror drifts on any access RAL did not drive.
- Connecting only the sequencer, not the predictor. The map's
set_sequencerenables frontdoor driving; the predictor separately keeps the mirror honest from observation. - Blaming the DUT for a mismatch after an external access. DUT correct, mirror stale is a missing-predictor signature, not an RTL bug.
- Forgetting the predictor's map/adapter. It needs both to reconstruct and place observed operations.
- Assuming RAL's self-updates cover everything. They cover only RAL's own accesses.
8. Industry Best Practices
- Connect a predictor for anything beyond a single-master active testbench. Multiple masters and passive monitoring require it.
- Subscribe the predictor to the bus monitor's analysis port. So every observed transaction updates the mirror.
- Give the predictor the map and adapter. It uses
bus2regto reconstruct observed operations onto the right registers. - Use passive prediction for embedded-software or external-stimulus scenarios. RAL drives nothing; the predictor keeps the model current from observation alone.
- Diagnose external-access mismatches as predictor gaps. DUT right, mirror behind after a non-RAL access means the predictor did not (or could not) see it.
9. Interview / Review Questions
10. Key Takeaways
- The mirror must track all register activity on the bus (the hardware holds whatever the last access left), but RAL alone only knows the accesses it originates.
- The predictor closes the gap by observing: it subscribes to the bus monitor and, via
bus2reg, updates the mirror from every observed transaction, whoever drove it. - This makes RAL correct with multiple masters (another master's write updates the mirror because the predictor saw it) and in passive monitoring (RAL drives nothing; the predictor keeps the whole model current from observation).
- Connect a predictor for anything beyond a single-master active testbench: give it the map and adapter and subscribe it to the monitor's analysis port.
- The signature bug is no predictor: an access RAL did not drive leaves the mirror stale, so a later RAL read mismatches — DUT correct, mirror behind is a missing-predictor signature, not an RTL coherency bug.