UVM RAL · Chapter 6 · Predictors
uvm_reg_predictor
The predictor is a small, specific class, defined by what it needs and what it does. It is parameterized by the bus item type so it can receive and decode transactions of that exact type from the monitor. It depends on three things: a map, which turns an observed address into a specific register; an adapter, whose bus2reg method decodes each observed transaction into a generic operation; and an analysis export connected to the bus monitor so it receives every transaction the monitor sees. On each observed item it runs one fixed algorithm: decode with bus2reg, resolve which register lives at that address, and call predict to update that register's mirror, dropping items whose address is not in this map. This lesson details the class, its wiring, and its algorithm, then breaks a predictor that has everything except an adapter, so it receives every transaction but can decode none and the mirror never updates.
Foundation12 min readUVM RALuvm_reg_predictorbus2regmapadapterAnalysis Port
Chapter 6 · Section 6.3 · Predictors
1. Why Should I Learn This?
The predictor is small but has a precise set of dependencies, and every one of them is a place it can be mis-wired into silent failure. It needs the right item type to receive traffic, the right adapter to decode it, the right map to place it, and a connection to the monitor to see it — and missing or wrong any of these makes the predictor exist but do nothing, so the mirror drifts exactly as if there were no predictor at all (6.1). Understanding the class's internal algorithm — decode, resolve, predict — is what lets you connect it correctly and, when it fails, know which dependency is missing from the symptom.
Learning the uvm_reg_predictor class in depth turns the abstract 'connect a predictor' of 6.1 into a concrete, debuggable component: you know what it needs, what it does with each observed transaction, and how each missing dependency manifests. It is the implementation behind the motivation.
2. Industry Story — the predictor that received everything and understood nothing
A team, moving to a multi-master environment, correctly creates a uvm_reg_predictor#(apb_item), connects its bus_in to the APB monitor's analysis port, and sets its map. They test it, and the mirror still drifts on other-master accesses exactly as before — even though the predictor is clearly connected and receiving transactions (a debug print in the predictor fires on every bus access).
The predictor was never given its adapter. On each observed item, the predictor's algorithm tries to call the adapter's bus2reg to decode the transaction — but with no adapter set, it cannot decode anything, so it receives every transaction and turns none of them into a mirror update. The mirror never advances from observed traffic, and a RAL read after another master's write mismatches, identically to the no-predictor case of 6.1. The confusion is that the predictor is visibly working — it is connected, it is receiving items — so the engineer assumes prediction is happening and looks elsewhere. The fix is one line: apb_predictor.adapter = apb_adapter;. The lesson: the predictor needs three things to function — the right item type, a map, and an adapter — and a predictor missing its adapter receives every transaction but can decode none, so the mirror never updates even though the predictor is connected and alive.
3. Concept — the class, its dependencies, and its algorithm
uvm_reg_predictor#(BUSITEM) is a small class with three dependencies and one algorithm:
- Parameterized by the bus item type.
uvm_reg_predictor#(apb_item)— it receives and casts transactions of that type; the parameter must match the monitor's item. map— the map whose address space the observed traffic belongs to. The predictor uses it (get_reg_by_offset) to resolve an observed address to a specific register.adapter— the same adapter the bus uses. The predictor calls itsbus2regto decode each observed transaction into a generic operation.bus_in— an analysis export you connect to the bus monitor's analysis port, so the predictor receives every observed transaction.
Its algorithm runs on each observed item (the analysis write callback):
bus2reg— decode the observed item into a genericuvm_reg_bus_op(address, kind, data, status).- Resolve the register —
map.get_reg_by_offset(rw.addr)finds which register lives at that address. If none does (the address is not in this map), the item is dropped — it is traffic for another block. predict— call the resolved register'spredictto update its mirror from the decoded operation (applying the field policies). Apre_predicthook lets you adjust before the update.
So the predictor needs a decoder (the adapter) and an address book (the map) to turn an observed transaction into a mirror update. Here is that algorithm:
4. Mental Model — a subscriber that decodes, resolves, and predicts
5. Working Example — building and wiring the predictor
The predictor is created parameterized by the bus item, given its map and adapter, and subscribed to the monitor:
class my_env extends uvm_env;
uvm_reg_predictor#(apb_item) apb_predictor; // parameterized by the OBSERVED item type
// ... reg_model, apb_agent, apb_adapter ...
virtual function void build_phase(uvm_phase phase);
// ... build/lock/reset the model; build the agent and 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);
// The predictor's THREE dependencies:
apb_predictor.map = reg_model.default_map; // 1. address book (resolve register)
apb_predictor.adapter = apb_adapter; // 2. decoder (bus2reg)
apb_agent.monitor.ap.connect(apb_predictor.bus_in); // 3. connection (receive traffic)
// Using explicit prediction -> turn auto-predict off (6.2).
reg_model.default_map.set_auto_predict(0);
endfunction
endclassAn optional pre_predict hook lets you adjust an observed operation before it updates the mirror:
// Extend the predictor to hook each observed op before it is applied (e.g., filter, log).
class my_predictor extends uvm_reg_predictor#(apb_item);
`uvm_object_utils(my_predictor)
virtual function void pre_predict(uvm_reg_item rw);
// Inspect or adjust rw before the mirror update — e.g., skip a known side-channel access.
super.pre_predict(rw);
endfunction
endclassWith the item type, map, adapter, and connection all in place, the predictor decodes each observed transaction, resolves the register, and updates its mirror — so the mirror tracks all bus traffic (6.1). The next section removes the decoder.
6. Debugging Session — the predictor with no adapter
A predictor connected and given a map but never given an adapter receives every transaction but can decode none, so the mirror never updates
MISSING ADAPTER ON PREDICTORapb_predictor = uvm_reg_predictor#(apb_item)::type_id::create("apb_predictor", this);
apb_predictor.map = reg_model.default_map; // map set
apb_agent.monitor.ap.connect(apb_predictor.bus_in); // connected to the monitor
// BUG: apb_predictor.adapter is never set (null).
// The predictor RECEIVES every observed item, but its algorithm needs the adapter's
// bus2reg to DECODE it -> with no adapter, it decodes nothing and updates nothing.
// A RAL read after another master's write mismatches (mirror never advanced).The mirror drifts on other-master (or passive) accesses exactly as if there were no predictor — a RAL read after an external write mismatches, DUT correct, mirror stale — even though the predictor is clearly connected and alive: a debug print in the predictor fires on every bus transaction, so it is visibly receiving traffic. This is what makes it confusing: 6.1's no-predictor symptom, but with a predictor that is demonstrably running. The engineer, seeing the predictor receive items, assumes prediction is happening and looks elsewhere for the drift.
The predictor was never given its adapter. Its per-item algorithm is decode-resolve-predict, and the decode step calls the adapter's bus2reg to turn the raw observed transaction into a generic operation; with no adapter, there is nothing to decode with, so the predictor receives every transaction and cannot turn any of them into a mirror update. The map being set lets it resolve addresses, and the bus_in connection lets it receive traffic — but without the adapter it cannot get from a raw bus item to an operation, so resolve and predict never run. The predictor is connected and alive but non-functioning, which is why it looks like no predictor while visibly receiving items.
Give the predictor its adapter: apb_predictor.adapter = apb_adapter; (as in Section 5), so it can bus2reg each observed transaction, resolve the register, and update the mirror. The rule the bug teaches: the predictor needs all three dependencies — the right item type, a map, and an adapter — to function; missing the adapter, it receives every transaction but decodes none, so the mirror never updates even though the predictor is connected and alive. When the mirror drifts but a debug print shows the predictor receiving items, the predictor is running but non-functioning — check that its map and, especially, its adapter are set.
7. Common Mistakes
- Predictor with no
adapter. It receives traffic but cannot decode it; the mirror never updates. - Predictor with no
map(or the wrong one). It cannot resolve an observed address to a register (multi-map: 6.4). - Wrong item-type parameter.
uvm_reg_predictor#(wrong_item)cannot cast the monitor's transactions. bus_innot connected to the monitor. The predictor receives nothing.- Assuming a connected predictor is a functioning one. It must decode and resolve; connection alone is not enough.
8. Industry Best Practices
- Set all three dependencies as one idiom.
map,adapter, andbus_in.connect(monitor.ap)together, plusset_auto_predict(0)(6.2). - Parameterize with the monitor's actual item type. So the predictor can cast and decode observed transactions.
- Use
pre_predictfor filtering or logging. Adjust or skip observed operations before they update the mirror. - Diagnose a drifting mirror by the predictor's dependencies. Receiving-but-not-updating is a missing adapter/map; not-receiving is a connection/item-type issue.
- Verify the predictor updates the mirror with a real non-RAL access. Not just that it receives items — confirm the mirror advances.
9. Interview / Review Questions
10. Key Takeaways
uvm_reg_predictor#(BUSITEM)is parameterized by the bus item type and depends on three things: a map (resolve register by address), an adapter (decode viabus2reg), andbus_inconnected to the monitor (receive traffic).- Its per-item algorithm is decode (
bus2reg) → resolve (map.get_reg_by_offset) → predict (reg.predict), dropping items whose address is not in the map (another block's traffic). - It needs a decoder (adapter) and an address book (map) to turn an observed transaction into a mirror update; missing either makes it receive traffic but update nothing.
- The signature bug is a predictor with no adapter: connected and alive (it receives every item) but non-functioning (it decodes none), so the mirror drifts like the no-predictor case — receiving is not functioning.
- Verify prediction by confirming the mirror advances on a real non-RAL access, and diagnose a drifting mirror by the dependency: receiving-but-not-updating is a missing adapter/map; not-receiving is a connection/item-type issue.