Difficulty: Hard · Puzzle 6 of 6 · Topic: Analysis, Scoreboards and RAL
UVM 1.2. A front-door `reg.read()` always returns 0 although the bus waveform shows the right read data. The adapter's `provides_responses` is left at 0. The driver builds a separate response item and sends it with item_done(rsp). Why does the model not get the data, and what are two fixes?
class bus_adapter extends uvm_reg_adapter;
`uvm_object_utils(bus_adapter)
function new(string name = "bus_adapter"); super.new(name); endfunction // provides_responses stays 0
function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw);
bus_item b = bus_item::type_id::create("b");
b.write = (rw.kind == UVM_WRITE);
b.addr = rw.addr;
b.wdata = rw.data;
return b;
endfunction
function void bus2reg(uvm_sequence_item bus_item_in, ref uvm_reg_bus_op rw);
bus_item b;
if (!$cast(b, bus_item_in)) `uvm_fatal("ADAPT", "wrong type")
rw.data = b.rdata;
rw.status = UVM_IS_OK;
endfunction
endclass
// driver
seq_item_port.get_next_item(req);
rsp = bus_item::type_id::create("rsp");
rsp.set_id_info(req);
vif.drive_and_sample(req, rsp.rdata); // read data goes into rsp
seq_item_port.item_done(rsp);After the transfer, bus2reg is called on some bus item. Which one, when provides_responses is 0?
1) With `provides_responses == 0` the register layer assumes the driver writes the read data back into the request item itself, and it calls bus2reg on that same request object (the one reg2bus created).
2) This driver writes rdata into a separate rsp item, so the request's rdata keeps its default 0, and bus2reg copies 0 into the register operation. The response item is not used by the register layer in this mode.
3) Fix A: drive/sample into the request (`vif.drive_and_sample(req, req.rdata)`) and call item_done() with no response.
4) Fix B: set `provides_responses = 1` in the adapter's constructor, keep the separate response, and make sure the driver sends it with a matching id (set_id_info(req)); then bus2reg is called on the response item.Answer: bus2reg runs on the request item (provides_responses = 0), but the driver put the data in a separate response; put the data in req, or set provides_responses = 1.
Not run here: The UVM library is not installed here, so this cannot be executed; uvm_reg_adapter and the register sequence's response handling are UVM library code; the claim is from the UVM 1.2 source (uvm_reg_map do_bus_read) and is the least certain of the register items.. The answer follows the language rules and the solution steps above.
The waveform and the driver are both 'right', the monitor even shows the correct value; the fault is in which object bus2reg converts, and no message points at it.
What can go wrong if you set provides_responses = 1 but the driver never sends a response? Model answer: the register sequence waits for a response that never comes, so the read hangs (the test eventually dies on the global timeout); the response must carry the request's ids, which is what set_id_info(req) is for.