Part 7 · Environment & Tests · Intermediate
phase_ready_to_end: Gate Closure on True Quiescence
Use phase readiness checks to hold phase closure until scoreboards and analysis pipelines are empty, then release deterministically.
Why readiness hooks matter
Objections signal intent, but intent is not always equivalent to completed checking. phase_ready_to_end hooks let components delay phase ending briefly until internal pipelines are quiescent.
[UVM][ENV] intent vs completion
objection dropped:
"I am done generating"
ready_to_end true:
"all required observation/checking work is done"
both are needed for robust closure[CHECK] typical readiness conditions
- expected queue empty
- actual queue empty
- no in-flight predictor transaction
- no deferred compare task pendingUse readiness for bounded tail completion, not indefinite waits.
Keep conditions objective and measurable via counters/queues.
Document which component owns each readiness condition.
Scoreboard readiness implementation
class my_scoreboard extends uvm_scoreboard;
`uvm_component_utils(my_scoreboard)
my_txn exp_q[$];
my_txn act_q[$];
int unsigned inflight_pairs;
function bit is_quiescent();
return (exp_q.size() == 0) &&
(act_q.size() == 0) &&
(inflight_pairs == 0);
endfunction
task wait_quiescent_or_timeout(time limit);
time start_t = $time;
while (!is_quiescent()) begin
if (($time - start_t) >= limit) begin
`uvm_error("READY_END",
$sformatf("not quiescent in %0t exp=%0d act=%0d in_flight=%0d",
limit, exp_q.size(), act_q.size(), inflight_pairs))
return;
end
#10ns;
end
endtask
task phase_ready_to_end(uvm_phase phase);
if (phase.get_name() == "run")
wait_quiescent_or_timeout(500ns);
endtask
endclasstask phase_ready_to_end(uvm_phase phase);
if (phase.get_name() != "run")
return;
if (!env.sb.is_quiescent())
env.sb.wait_quiescent_or_timeout(500ns);
endtask[UVM][ENV] bounded readiness contract
ready_to_end may delay
but must not hang forever
always include local timeout and counters in error messageBound readiness waits with component-local timeout.
Emit queue/counter state on readiness failure.
Keep readiness logic deterministic and side-effect free.
Coordination with objections and drain
Interaction model
Test drops objection when stimulus generation is complete.
Drain time permits passive tail activity window.
ready_to_end verifies tail activity actually converged.
Global timeout remains ultimate protection for non-converging runs.
[UVM] layered closure stack
Layer 1: objection lifecycle (ownership)
Layer 2: drain_time window (latency allowance)
Layer 3: ready_to_end (quiescence proof)
Layer 4: global timeout (safety net)[ENV] when to avoid ready_to_end
- if component has no tail work and no queues
- if condition depends on unbounded external behavior
- if used to hide design deadlock rather than detect itKey takeaways
phase_ready_to_end turns end-of-test intent into measurable completion.
Use bounded waits with precise diagnostics to avoid silent hangs.
Readiness complements objections and drain, it does not replace them.
Layered closure architecture is robust under stress regressions.
Common pitfalls
Unbounded ready_to_end wait that becomes another hang source.
Readiness checks that mutate state and create heisenbugs.
Assuming empty one queue implies full-system quiescence.
Using ready_to_end to hide structural checker backlog bugs.