Skip to content

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 its bus2reg to 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):

  1. bus2reg — decode the observed item into a generic uvm_reg_bus_op (address, kind, data, status).
  2. Resolve the registermap.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.
  3. predict — call the resolved register's predict to update its mirror from the decoded operation (applying the field policies). A pre_predict hook 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:

Predictor algorithm: observed item to bus2reg to get_reg_by_offset to predictnoyesmonitor deliversitem to bus_inadapter.bus2reg(item,rw): decode opmap.get_reg_by_offset(rw.addr):find registerregister inthis map?not in map —drop (anotherblock's traffic)reg.predict(rw.data):update the mirror(per policy)mirror nowtracks theobserved access
Figure 1 — the predictor's algorithm on each observed transaction. The monitor delivers an item to bus_in; the predictor calls the ADAPTER's bus2reg to decode it into a generic op, uses the MAP's get_reg_by_offset to resolve which register lives at that address (dropping the item if the address is not in this map — it is another block's traffic), and calls that register's predict to update its mirror. It needs the adapter (to decode) and the map (to resolve); missing either, it receives items but cannot turn them into mirror updates.

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:

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

An optional pre_predict hook lets you adjust an observed operation before it updates the mirror:

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

With 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

1

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

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.

Root Cause

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.

Fix

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_in not 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, and bus_in.connect(monitor.ap) together, plus set_auto_predict(0) (6.2).
  • Parameterize with the monitor's actual item type. So the predictor can cast and decode observed transactions.
  • Use pre_predict for 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 via bus2reg), and bus_in connected 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.