Part 2 · Phases & Lifecycle · Intermediate
Phase Method Debug: Finding Silent Override and Type Bugs
Systematic workflow for phase method bugs — signature verification, super audit, function-vs-task placement, and trace-driven triage.
Triage order for 'my phase code did not run'
Verify exact method name ends with _phase.
Verify return kind: function void vs task.
Verify uvm_phase phase argument present.
Verify super.<phase>_phase(phase) called.
Verify +UVM_PHASE_TRACE shows entry.
Only then debug functional logic inside the callback.
[UVM][PHASE] method debug flowchart
symptom: expected code never runs
-> signature match? NO -> fix name/type/arg
-> super called? NO -> add super
-> trace shows phase? NO -> override not registered / wrong type
-> YES -> logic bug inside callback
symptom: hang in run
-> objection trace
-> fork join completeness
symptom: compile error on override
-> function vs task mismatchfunction void build_phase(uvm_phase phase);
`uvm_info("PH_DBG", $sformatf("%s::build_phase", get_type_name()), UVM_NONE)
super.build_phase(phase);
endfunctionKey takeaways
Method bugs cluster at signature and super — check those first.
PH_DBG entry print is the cheapest override verification.
Phase trace confirms scheduler actually invoked your callback.
Common pitfalls
Rewriting functional logic while override never ran.
Enabling full UVM_FULL verbosity before signature proof.
Fixing waves while build_phase override is misspelled.
Function-vs-task placement audit
Illegal time control scan
Search function phases for #, @, wait, and
blocking TLM. Any hit is a methodology violation to relocate to run_phase.
// WRONG — time in function phase
function void start_of_simulation_phase(uvm_phase phase);
super.start_of_simulation_phase(phase);
@(posedge vif.rst_n); // MOVE to run_phase
endfunction
// RIGHT
task run_phase(uvm_phase phase);
super.run_phase(phase);
@(posedge vif.rst_n);
phase.raise_objection(this, "post-reset");
seq.start(sqr);
phase.drop_objection(this, "done");
endtaskLint-style review checklist
Every function phase: super first, no time statements.
run_phase: super, raise, work, drop on all paths.
No objections outside task phases.
Sequence start only in task phases.
[PHASE] CI-friendly static checks (manual or scripted)
grep function phases for "@(posedge" -> must be empty
grep build_phase for "#" -> must be empty
grep run_phase for "raise_objection" without "drop_objection" -> review
grep for "function void run_phase" -> must be emptyRegression artifact
function void report_phase(uvm_phase phase);
super.report_phase(phase);
`uvm_info("PHASE_AUDIT",
$sformatf("type=%s super_ok=1 sig_ok=1", get_type_name()), UVM_NONE)
endfunctionKey takeaways
Placement audit catches #delay-in-build before it reaches silicon TB bring-up.
Simple greps are high leverage for large VIP repos.
PHASE_AUDIT report lines document override health per regression.
Common pitfalls
Disabling audit logs in CI to reduce noise — keep UVM_NONE one-liners.
Moving time control to run_phase without objections — early end risk.
Fixing signature but leaving illegal time control in another phase.