Part 10 · Advanced Topics · Intermediate
set_drain_time and Trailing Activity
Why drain windows exist, how phase_done.set_drain_time behaves, timing diagrams, and tuning drain values for regression scale.
Why zero-count is not always safe to end immediately
When objection count reaches zero, active stimulus may be done, but passive infrastructure can still be processing trailing activity: monitors sampling final beats, scoreboards matching delayed responses, predictors updating mirrors, and coverage collecting last samples.
A fixed drain window via phase.phase_done.set_drain_time(source, delay) adds a post-zero wait before phase end. It is not a replacement for functional checks; it is a buffer that allows trailing passive work to complete naturally.
[UVM] motivation for drain_time
last active sequence drops objection at T100ns
bus still has delayed response at T108ns
monitor publishes response at T109ns
scoreboard compares at T110ns
no drain_time:
run_phase may end near T100ns -> final compare missed
drain_time = 20ns:
phase waits until at least T120ns -> trailing compare includedAPI usage and placement
Set drain time from a stable owner (often test) early in run_phase or during setup. Keep ownership clear so later overrides are intentional.
task run_phase(uvm_phase phase);
// Fixed post-zero window for run phase
phase.phase_done.set_drain_time(this, 100ns);
phase.raise_objection(this, "execute scenario");
main_vseq.start(env.v_sqr);
phase.drop_objection(this, "scenario complete");
endtask// Optional utility for environment-level tuning
function void configure_drain(uvm_phase phase, time t);
if (phase.get_name() == "run")
phase.phase_done.set_drain_time(this, t);
endfunctionDrain time applies after objection total reaches zero.
If new objections are raised during the drain window, phase continues normally.
Use explicit comments describing why the selected delay exists (protocol latency, checker pipeline, etc.).
Timing diagram: drop, drain, end
The diagram below clarifies the event ordering that is frequently misunderstood.
[UVM] run-phase end timing
time ───────────────────────────────────────────────────────────►
objections:
count=2 count=1 count=0
│ │ │
▼ ▼ ▼
work A done work B done start drain timer (D)
│
├─ passive monitors/checkers still active
│
▼
if no new raise by T0 + D
│
▼
phase ends
If a new raise occurs during drain:
drain wait is interrupted by active objections;
end condition re-evaluates after those objections drop again.Drift between protocol latency and drain settings
If drain is too small, intermittent end-of-test misses appear under high latency.
If drain is too large, every test pays unnecessary idle time.
Measure worst-case tail latency from logs/waves before finalizing value.
Tuning strategy for farm-scale regressions
Drain-time tuning is an economics problem: enough time for correctness, minimal overhead for throughput.
Start with a conservative value in bring-up (e.g., 100ns or protocol-tail estimate).
Instrument end-of-phase logs: when did final monitor/checker event occur after last drop?
Gather distribution across stress tests; pick near worst-case percentile, not single run anecdote.
Revisit when protocol timing changes (clock, queue depth, arbitration updates).
[CHECK] drain tuning worksheet
observed tail (ns) across tests:
8, 12, 9, 11, 35, 10, 14, 13, 42
candidate drain:
50ns (covers spikes + margin)
regression impact:
+50ns * 10k tests = 0.5 ms simulated time
wall-time impact depends on simulator speed and idle overhead
if impact high:
reduce fixed drain and move special cases to phase_ready_to_end logicKey takeaways
set_drain_time protects trailing passive activity after final drop.
It is a fixed delay tool; keep value justified and measured.
Too small causes intermittent misses; too large wastes regression budget.
Use conditional extension for rare long tails rather than inflating global drain.
Common pitfalls
Using large drain as a blanket fix for unresolved scoreboard logic bugs.
Setting drain in multiple places with conflicting intentions.
Assuming drain alone guarantees functional completeness without checker-side conditions.