Part 7 · Environment & Tests · Intermediate

Virtual Sequencer Debug: Symptom-First Triage and Recovery Runbook

Diagnose null handles, deadlocks, bad ordering, and premature completion with deterministic instrumentation and staged recovery.

Symptom Matrix

Classify failure symptoms before changing code. Each symptom maps to a specific boundary and reduces random debugging.

diagram
[TEST][UVM] symptom matrix

symptom                                 likely boundary
----------------------------------------------------------------
null handle fatal                       env connect/mode mapping
vseq started, no child traffic          wrong handle target or blocked child sqr
intermittent order mismatch             missing/weak barrier synchronization
hang after partial progress             unbounded wait or undropped objection
time-0 pass                             objection not raised / vseq not started
diagram
[TEST][UVM] triage order

1) verify startup profile and mode config
2) verify mapped handle snapshot
3) verify vseq checkpoint timeline
4) verify event trigger/wait pairs
5) verify objection lifecycle and closure gates

Key takeaways

  • Symptom-first debugging narrows search scope immediately.

  • Fixed triage order prevents noisy, non-repeatable investigation.

  • Boundary-focused logs outperform ad hoc waveform hunting.

Common pitfalls

  • Patching code before proving handle map correctness.

  • Investigating full-stress profile before minimal reproducer.

  • Relying on one-time debug prints not present in CI runs.


Instrumentation Baseline

systemverilog
class soc_virtual_sequencer extends uvm_sequencer #(uvm_sequence_item);
  int unsigned start_cnt;
  int unsigned wait_cnt;
  int unsigned timeout_cnt;
  string checkpoint_q[$];

  function void mark(string cp);
    checkpoint_q.push_back(cp);
    `uvm_info("VSQR_CP", cp, UVM_MEDIUM)
  endfunction
endclass
systemverilog
task wait_event_or_fatal(uvm_event ev, time tmo, string name);
  p_sequencer.wait_cnt++;
  p_sequencer.mark($sformatf("WAIT_%s_BEGIN", name));
  if (!ev.try_wait_trigger(tmo)) begin
    p_sequencer.timeout_cnt++;
    `uvm_fatal("VSQR_WAIT", $sformatf("timeout waiting %s", name))
  end
  p_sequencer.mark($sformatf("WAIT_%s_DONE", name));
endtask
diagram
[TEST][UVM][ENV] mandatory debug payload

seed, test, profile
required handles
mapped handles
checkpoint timeline
wait/timeout counters
objection raise/drop times
scenario closure metrics
  • Keep debug payload low overhead and always-on.

  • Capture checkpoints around every wait and branch start.

  • Print a compact final summary for quick triage in CI logs.


Applied Patterns

diagram
[TEST][UVM][VSEQ] recovery runbook

step 1:
  freeze seed and exact command line

step 2:
  run minimal profile that still reproduces

step 3:
  disable optional interfaces and re-enable one by one

step 4:
  compare checkpoint timelines between pass and fail

step 5:
  convert discovered assumption into permanent guardrail
systemverilog
function void final_phase(uvm_phase phase);
  `uvm_info("VSQR_FINAL",
    $sformatf("start=%0d waits=%0d timeouts=%0d cps=%0d",
      env.v_sqr.start_cnt,
      env.v_sqr.wait_cnt,
      env.v_sqr.timeout_cnt,
      env.v_sqr.checkpoint_q.size()),
    UVM_LOW)
endfunction
  • Use reduction-and-rebuild to isolate orchestration bugs quickly.

  • Promote every fixed bug into a guardrail or assertion.

  • Prefer deterministic checks over manual log inspection.