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:

diagram
UVM_OBJECTION @ 100ns: RAISE  count=1  reason="start traffic"  comp=axi_driver
(... no further DROP ...)

Root cause

systemverilog
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");
endtask

Fix

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.

systemverilog
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 loop

Case study 2: instant PASS

Symptom

Test completes in 0.1 seconds. Log shows *** TEST PASSED ***. Coverage is 0%.

Investigation

diagram
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

systemverilog
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")
endfunction

Case 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.

diagram
grep PHASE_CHK sim.log  no matches for my_driver

Root cause

systemverilog
// Typo in phase method name — not an override
function void buid_phase(uvm_phase phase);
  super.build_phase(phase);
endfunction

Fix

Correct spelling to build_phase. PHASE_CHK log appears. Override behavior confirmed.

systemverilog
function void build_phase(uvm_phase phase);
  `uvm_info("PHASE_CHK", "my_driver::build_phase", UVM_HIGH)
  super.build_phase(phase);
endfunction

Key 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

diagram
[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-up
  • Share 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.