Difficulty: Medium · Puzzle 3 of 6 · Topic: Testbench Debug Puzzles: Why Did the Test Hang?
Interview log: 'late_shutdown_seq waiting for grant' forever. The same sequence works when the test starts it in run_phase. The driver code is shown below. Why does this version stall?
class my_driver extends uvm_driver #(my_item);
\`uvm_component_utils(my_driver)
virtual task main_phase(uvm_phase phase); // driver loop lives in main_phase
forever begin
seq_item_port.get_next_item(req);
drive_req(req);
seq_item_port.item_done();
end
endtask
endclass
class late_test extends uvm_test;
\`uvm_component_utils(late_test)
virtual task shutdown_phase(uvm_phase phase);
late_shutdown_seq seq;
phase.raise_objection(this);
seq = late_shutdown_seq::type_id::create("seq");
seq.start(env.agent.seqr); // hangs
phase.drop_objection(this);
endtask
endclassCheck which components are still actively driving sequence items in this phase.
1) Print which phase each component is in (or add a log at the top and bottom of every driver task). The driver prints "main_phase exit" before the sequence starts.
2) The sequencer only grants a sequence when the driver pulls with get_next_item. The driver's pull loop is in main_phase; when main_phase ended, UVM killed that forever loop, so nobody pulls any more.
3) The sequence therefore waits for a grant that can never come, and shutdown_phase holds its objection forever.
4) Fix: put the driver loop in run_phase (which runs in parallel with all the runtime phases) or start the traffic in main_phase.
5) Add a fail-fast check: a grant-timeout watchdog in the sequence, or a convention that all driver loops live in run_phase.
Note: if the driver loop were in run_phase, this exact test would NOT stall, because run_phase is still alive during shutdown_phase. The stall depends on the driver being phase-scoped.Answer: Bug: the driver's pull loop lives in main_phase, which has ended (and killed the loop) before shutdown_phase; the sequence waits for a grant nobody can give. Fix: move the driver loop to run_phase (alive across the runtime phases) or start the traffic in main_phase. Mixing run_phase and runtime-phase code for the same agent is discouraged.
Not run here: Needs the UVM phase scheduler: the bug is that the driver's forever loop lives in main_phase, which UVM ends (and kills) before shutdown_phase; this depends on the library's phase ordering and process-tree kill, which plain SV does not have.. The answer follows the language rules and the solution steps above.
People chase arbitration or priority settings, but a sequencer grant needs the driver to pull; the real question is which phase the pulling thread lives in and whether it is still alive.
What diagnostics would you add to fail fast if a sequence starts in an incompatible phase? Model answer: A watchdog in the sequence base class that errors if start_item has not been granted within a bounded time (with the sequencer's phase and the driver's last-pull timestamp in the message), plus a log of the current phase in every driver pull so the last pull time is visible. A convention check (driver loops only in run_phase) removes the class of bug.
First I ask which phase the thread that pulls items lives in, because a sequencer grant needs the driver to pull. The root cause is that the driver loop lives in main_phase, which has ended and killed the loop before shutdown_phase, so the sequence waits for a grant nobody can give. I confirm it by logging when the driver loop exits against when the sequence starts. The fix is to move the driver loop to run_phase, or to start the traffic in main_phase.