Part 9 · Register Model (RAL) · Intermediate
Sequencer, Map, Adapter: set_sequencer Deep Dive
How reg maps route frontdoor operations through adapter and sequencer, plus multi-map and base address details.
What set_sequencer really binds
The call reg_model.default_map.set_sequencer(bus.sqr, adapter) does two critical bindings: it tells the map which sequencer executes frontdoor operations, and which adapter converts uvm_reg_bus_op into protocol items.
[UVM][RAL] frontdoor conversion pipeline
reg.write(status, data)
│
▼
map.do_write()
│
├─ uses sequencer bound by set_sequencer()
└─ uses adapter bound by set_sequencer()
│
▼
adapter.reg2bus(rw) -> apb_item/axi_item
│
▼
sequencer.start_item(item) -> driver -> DUTNo set_sequencer means RAL has no legal frontdoor route for that map.
Wrong adapter type causes bad data, address, or status translation.
Map binding is per-map, not global to the entire reg model.
Single-map and multi-map examples
Single map (common)
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
reg_model.default_map.set_sequencer(apb.sqr, apb_adapter);
endfunctionMultiple maps (APB + debug bus)
class soc_reg_env extends uvm_env;
core_reg_block reg_model;
apb_agent apb;
dbg_agent dbg;
apb_reg_adapter apb_adapter;
dbg_reg_adapter dbg_adapter;
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
// map used by normal software-like traffic
reg_model.apb_map.set_sequencer(apb.sqr, apb_adapter);
// map used by debug port accesses
reg_model.dbg_map.set_sequencer(dbg.sqr, dbg_adapter);
endfunction
endclass[RAL] map ownership model
default_map -> APB sequencer + APB adapter
dbg_map -> DBG sequencer + DBG adapter
cfg_map -> AXI-Lite sequencer + AXI adapter
Each map carries its own transport binding.
Wrong map call => valid transaction on wrong bus path.Always call set_sequencer on the map that the sequence will actually use.
For multi-map designs, name maps clearly to avoid accidental bus selection.
When tests override path/map, verify adapter and base addresses per map.
Adapter responsibilities in this binding
A set_sequencer binding is only as correct as the adapter implementation behind it.
class apb_reg_adapter extends uvm_reg_adapter;
`uvm_object_utils(apb_reg_adapter)
uvm_reg_addr_t base_addr = '0;
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 item = apb_item::type_id::create("item");
item.write = (rw.kind == UVM_WRITE);
item.addr = base_addr + rw.addr;
item.data = rw.data;
return item;
endfunction
virtual function void bus2reg(uvm_sequence_item bus_item, ref uvm_reg_bus_op rw);
apb_item item;
if (!$cast(item, bus_item)) begin
rw.status = UVM_NOT_OK;
return;
end
rw.kind = item.write ? UVM_WRITE : UVM_READ;
rw.addr = item.addr - base_addr;
rw.data = item.data;
rw.status = item.slverr ? UVM_NOT_OK : UVM_IS_OK;
endfunction
endclassDeep dive checklist for set_sequencer bugs
Print map name used by sequence; confirm it is the map bound in connect_phase.
Print sequencer full name from map to ensure expected bus agent is used.
Compare adapter instance pointer in set_sequencer and predictor.adapter.
Verify adapter base_addr translation against memory map docs.
Run one write to a known register and inspect monitor address/data.
Key takeaways
set_sequencer binds map transport: sequencer + adapter together.
Bindings are map-specific; multi-map envs need explicit per-map setup.
Most frontdoor routing bugs are map mismatch or adapter address translation errors.
Common pitfalls
Binding only default_map while tests use a secondary map.
Using different adapters for stimulus and prediction with inconsistent base_addr.
Assuming map binding is inherited automatically by sub-maps.