Difficulty: Medium · Puzzle 5 of 6 · Topic: Testbench Debug Puzzles: Why Did the Test Hang?
Sequence hangs on get_response only when DUT returns error responses. Normal responses complete. Determine the missing piece.
class rsp_seq extends uvm_sequence #(my_item);
virtual task body();
my_item req, rsp;
repeat (20) begin
\`uvm_do(req)
get_response(rsp); // hangs on error cases
end
endtask
endclass
virtual task my_driver::run_phase(uvm_phase phase);
my_item req, rsp;
forever begin
seq_item_port.get_next_item(req);
rsp = my_item::type_id::create("rsp");
rsp.set_id_info(req);
if (req.inject_err) begin
seq_item_port.item_done();
continue; // bug: no put_response on this path
end
seq_item_port.item_done(rsp);
end
endtaskCompare response-path behavior for success and error branches.
1) Add response queue depth trace in the sequence around get_response calls.
2) Correlate hangs to requests with inject_err asserted.
3) Inspect driver branch and confirm error path never sends response object back.
4) Return an explicit error response (or stop waiting for response by contract).
5) Add sequence-level timeout for get_response to expose future response-contract breaks.Answer: Bug: driver does not put/send response on error path, but sequence always waits for one. Fix: always return a response (including error status) or change sequence contract to not call get_response for no-rsp flows.
Checked by running the code in Verilator 5; the printed output supports the answer above. Plain-SV model of the response channel (mailbox), not the UVM library: the error path sends no response, so get_response never returns.
Debugging only successful traffic misses the path that violates the response contract.
How would you encode in the item whether a response is mandatory so sequence behavior is explicit? Model answer: Add a rsp_required bit (or an enum RSP_NONE/RSP_OK/RSP_ERR in the request) that the sequence sets, and a mandatory status field in the response; the driver always sends exactly one response when rsp_required is set (including the error case), and the sequence calls get_response only when it set the bit.
First I check the response contract on the failing path, because the sequence is stuck waiting in get_response. The root cause is that the driver does not send a response on the error path, while the sequence always waits for one. I confirm it by comparing driver response puts against sequence get_response calls on an error item. The fix is to always return a response, including an error status, or to change the sequence so it does not wait in flows without a response.