Part 2 · Phases & Lifecycle · Intermediate
Phase Debug Case Studies: Three Worked Examples
Worked examples — overnight hang from fork objection leak, instant PASS from missing raise, silent override from signature typo.
Case study 1: overnight hang
Symptom
Regression farm reports simv still running after 8 hours. Waveforms show idle bus. No UVM_ERROR.
Investigation
OBJECTION_TRACE shows:
UVM_OBJECTION @ 100ns: RAISE count=1 reason="start traffic" comp=axi_driver
(... no further DROP ...)Root cause
task run_phase(uvm_phase phase);
phase.raise_objection(this, "start traffic");
fork
drive_forever();
join_none // driver runs forever, drop never reached
phase.drop_objection(this, "done");
endtaskFix
Use objection only around bounded work, or drop in a shutdown path. For perpetual drivers, raise/drop at test level, not inside forever loop without exit.
task run_phase(uvm_phase phase);
forever begin
seq_item_port.get_next_item(req);
drive(req);
seq_item_port.item_done();
end
endtask
// Objection raised/dropped by test or sequence, not driver forever loopCase study 2: instant PASS
Symptom
Test completes in 0.1 seconds. Log shows *** TEST PASSED ***. Coverage is 0%.
Investigation
PHASE_TRACE: run_phase START @ 0ns
PHASE_TRACE: run_phase END @ 0ns
(no OBJECTION RAISE entries)Root cause
Test run_phase called super but never raised an objection. Sequence had starting_phase disabled and no alternative raise.
Fix
task run_phase(uvm_phase phase);
phase.raise_objection(this, "test stimulus");
super.run_phase(phase); // or start sequences here
phase.drop_objection(this, "test stimulus done");
endfunction
function void check_phase(uvm_phase phase);
super.check_phase(phase);
if (env.txn_count == 0)
`uvm_error("CHECK", "zero transactions — instant pass bug")
endfunctionCase study 3: silent override failure
Symptom
Factory override of my_driver registered. Simulation still uses original driver behavior. No errors.
Investigation
Added PHASE_CHK log to my_driver::build_phase — log never appeared.
grep PHASE_CHK sim.log → no matches for my_driverRoot cause
// Typo in phase method name — not an override
function void buid_phase(uvm_phase phase);
super.build_phase(phase);
endfunctionFix
Correct spelling to build_phase. PHASE_CHK log appears. Override behavior confirmed.
function void build_phase(uvm_phase phase);
`uvm_info("PHASE_CHK", "my_driver::build_phase", UVM_HIGH)
super.build_phase(phase);
endfunctionKey takeaways
Hang case: fork/join_none + drop after = unreachable drop.
Instant pass: no raise + no check guard = silent false success.
Override case: signature typo = new method, not override.
Common pitfalls
Closing case study bugs without adding check_phase or PHASE_CHK guard.
Assuming farm timeout means RTL bug — often objection leak.
Lessons applied
[PHASE][UVM] case study prevention matrix
hang → OBJECTION_TRACE on every farm timeout
instant pass → zero-txn check_phase on every test
silent override → PHASE_CHK log during component bring-upShare case studies in team onboarding — they prevent repeat bugs.
Add farm policy: no timeout investigation without objection trace attached.
Retire PHASE_CHK logs to UVM_HIGH after bring-up, not UVM_NONE.