Part 9 · Register Model (RAL) · Intermediate

uvm_reg_predictor Wiring

How monitor transactions flow through adapter bus2reg into uvm_reg_predictor and update the register map mirror for reliable checks.

Signal path: monitor -> predictor -> map

Explicit prediction is the robust frontdoor architecture. The monitor observes bus traffic, predictor converts bus item to reg operation using adapter, then map updates mirror.

diagram
[UVM] predictor wiring diagram

  [BUS AGENT]
    monitor.ap  -------------------------------> predictor.bus_in
                                                     │
                                                     │ uses adapter.bus2reg()
                                                     ▼
                                                uvm_reg_bus_op
                                                     │
                                                     ▼
                                                predictor.map
                                                     │
                                                     ▼
                                          [RAL] mirrored value update

  Required assignments:
    predictor.map     = reg_model.default_map;
    predictor.adapter = bus_adapter;
    monitor.ap.connect(predictor.bus_in);
diagram
[CHECK] what each block owns

  monitor:
    passive observation of real bus traffic

  adapter.bus2reg:
    protocol item -> canonical uvm_reg_bus_op fields (kind/addr/data/status)

  predictor:
    finds matching reg/field via map, calls predict semantics

  map:
    address decoding context and access path metadata

Reference environment wiring (SystemVerilog)

The connect code below is the production baseline for frontdoor RAL usage. Keep auto_predict off when explicit predictor is present.

systemverilog
class reg_env extends uvm_env;
  `uvm_component_utils(reg_env)

  apb_agent                     apb;
  my_reg_block                  reg_model;
  apb_reg_adapter               adapter;
  uvm_reg_predictor #(apb_item) predictor;

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    apb       = apb_agent::type_id::create("apb", this);
    adapter   = apb_reg_adapter::type_id::create("adapter");
    predictor = uvm_reg_predictor#(apb_item)::type_id::create("predictor", this);

    reg_model = my_reg_block::type_id::create("reg_model");
    reg_model.build();
    reg_model.lock_model();
  endfunction

  function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);

    // Frontdoor path for register API calls.
    reg_model.default_map.set_sequencer(apb.sqr, adapter);

    // Use monitor-based explicit prediction.
    reg_model.default_map.set_auto_predict(0);
    predictor.map     = reg_model.default_map;
    predictor.adapter = adapter;
    apb.mon.ap.connect(predictor.bus_in);
  endfunction
endclass

Readability conventions

  • Set sequencer/adapter and predictor wiring in the same connect block.

  • Keep `set_auto_predict(0)` adjacent to predictor assignments to avoid split-brain behavior.

  • Name predictor instance clearly (`reg_predictor` or `predictor`) for grep-friendly debug.


Adapter contract for prediction correctness

Prediction quality depends on bus2reg correctness. Address, kind, data, and status must represent observed transfer semantics exactly.

systemverilog
class apb_reg_adapter extends uvm_reg_adapter;
  `uvm_object_utils(apb_reg_adapter)

  function new(string name = "apb_reg_adapter");
    super.new(name);
    supports_byte_enable = 0;
    provides_responses   = 0;
  endfunction

  virtual function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw);
    apb_item t = apb_item::type_id::create("t");
    t.addr  = rw.addr;
    t.data  = rw.data;
    t.write = (rw.kind == UVM_WRITE);
    return t;
  endfunction

  virtual function void bus2reg(uvm_sequence_item bus_item, ref uvm_reg_bus_op rw);
    apb_item t;
    if (!$cast(t, bus_item)) begin
      rw.status = UVM_NOT_OK;
      return;
    end
    rw.kind   = t.write ? UVM_WRITE : UVM_READ;
    rw.addr   = t.addr;
    rw.data   = t.data;
    rw.status = UVM_IS_OK;
  endfunction
endclass
diagram
[RAL] adapter mistakes and observed symptoms

  bus2reg addr wrong:
    mirror updates a different register than bus target

  bus2reg kind swapped (read/write):
    side-effect modeling and compare semantics collapse

  rw.status never set UVM_IS_OK:
    predictor may skip effective mirror update

  byte-lane/endianness mismodel:
    recurring bit-slice mismatches in mirror checks

Advanced wiring: multi-map and shared buses

SoC environments often have multiple maps or non-RAL traffic on the same monitor stream. Prediction still works if routing/filtering is explicit.

diagram
[UVM] multi-map considerations

  Scenario:
    one physical bus monitor carries:
      - RAL-mapped CSR traffic
      - non-CSR DMA/descriptor traffic

  Strategy:
    - filter monitor items before predictor when possible
    - or let bus2reg tag unsupported transactions with UVM_NOT_OK
    - ensure predictor.map matches address space for target block
    - create one predictor per map when address regions overlap logically
systemverilog
class csr_filter_subscriber extends uvm_subscriber #(apb_item);
  `uvm_component_utils(csr_filter_subscriber)
  uvm_analysis_port #(apb_item) csr_ap;

  function new(string name, uvm_component parent);
    super.new(name, parent);
    csr_ap = new("csr_ap", this);
  endfunction

  virtual function void write(apb_item t);
    if ((t.addr >= 'h0000) && (t.addr < 'h1000))
      csr_ap.write(t);
  endfunction
endclass

// connect_phase idea:
// apb.mon.ap -> filter.analysis_export
// filter.csr_ap -> predictor.bus_in

Key takeaways

  • Explicit predictor wiring is the default-safe architecture for frontdoor RAL.

  • Correct adapter bus2reg mapping is mandatory for trustworthy mirror state.

  • Keep auto_predict disabled when explicit predictor consumes monitor traffic.

  • In mixed-traffic systems, filter or map-route transactions intentionally.

Common pitfalls

  • Connecting predictor but forgetting to assign map or adapter.

  • Leaving auto_predict enabled alongside explicit prediction without intent.

  • Feeding predictor unrelated transactions and blaming random mirror drift.