Part 8 · Checking & Coverage · Intermediate
PASS/FAIL, Max Quit Count, and Debug Playbook
report_phase PASS/FAIL from report server, quit limits, and regression triage steps.
PASS/FAIL workflow
UVM does not automatically print PASS/FAIL. Your test's report_phase must query the report server and print the result. The standard check: UVM_ERROR + UVM_FATAL == 0 → PASS; anything else → FAIL.
Legend: [UVM]
PASS/FAIL WORKFLOW
run_phase
│
├─ scoreboard mismatch → `uvm_error("SCB_MISMATCH", ...) → count++
├─ RAL mirror fail → `uvm_error("RAL_MIRROR", ...) → count++
├─ VIP benign error → catcher demotes to warning → no error count
└─ null vif → `uvm_fatal("NOVIF", ...) → count++ + sim stops
│
check_phase
│
└─ unmatched expected → `uvm_error("SCB", ...) → count++
│
report_phase
│
├─ svr.get_severity_count(UVM_ERROR) → N
├─ svr.get_severity_count(UVM_FATAL) → M
│
├─ N + M == 0 → `uvm_info("RESULT", "*** TEST PASSED ***", UVM_NONE)
└─ N + M > 0 → `uvm_info("RESULT", "*** TEST FAILED ***", UVM_NONE)
│
Regression tool reads RESULT line + exit code → batch PASS/FAILreport_phase implementation
function void report_phase(uvm_phase phase);
super.report_phase(phase);
uvm_report_server svr = uvm_report_server::get_server();
int errors = svr.get_severity_count(UVM_ERROR)
+ svr.get_severity_count(UVM_FATAL);
int warnings = svr.get_severity_count(UVM_WARNING);
`uvm_info("RESULT", $sformatf(
"Errors=%0d Warnings=%0d", errors, warnings), UVM_NONE)
if (errors == 0)
`uvm_info("RESULT", "*** TEST PASSED ***", UVM_NONE)
else
`uvm_info("RESULT", $sformatf("*** TEST FAILED (%0d errors) ***",
errors), UVM_NONE)
// Per-ID breakdown for triage
`uvm_info("RESULT", $sformatf("SCB_MISMATCH: %0d",
svr.get_id_count("SCB_MISMATCH")), UVM_NONE)
endfunction// Max quit count — stop sim after N errors (prevent log explosion)
function void build_phase(uvm_phase phase);
super.build_phase(phase);
set_report_max_quit_count(50);
endfunction
// Or: simv +UVM_MAX_QUIT_COUNT=100Debug playbook
Regression triage steps
Reproduce failing seed at UVM_MEDIUM — note error IDs and counts from RESULT line.
Query get_id_count("SCB_MISMATCH") — how many distinct failure types?
Raise verbosity on failing component only: +uvm_set_verbosity=...env.scb,_ALL_,UVM_HIGH,run.
Add strategic uvm_info at UVM_HIGH in scoreboard write_act — not global UVM_FULL.
check_phase: inspect unmatched expected count — DUT dropped responses?
report_phase: print match_count, coverage %, and per-ID error breakdown.
VIP noise: catcher for known IDs or set_report_id_verbosity(VIP_ID, UVM_NONE).
Fix root cause, re-run at UVM_MEDIUM to confirm PASS.
DEBUG DECISION TREE [UVM]
Test FAILED — where to look first?
│
├─ SCB_MISMATCH count > 0?
│ └─ Raise scb verbosity to UVM_HIGH, rerun single seed
│
├─ RAL_MIRROR count > 0?
│ └─ Check predictor wiring and auto_predict setting
│
├─ SCB count > 0 (unmatched expected)?
│ └─ check_phase drain — DUT dropped responses
│
├─ NOVIF / NOCONFIG fatal?
│ └─ config_db path mismatch — print in build_phase
│
└─ Zero errors but test looks wrong?
└─ Check for catchers demoting real errors to warningsKey takeaways
Never print PASS when UVM_ERROR count > 0.
check_phase errors count toward FAIL same as run_phase errors.
Print per-ID error breakdown in report_phase — essential for regression triage.
Common pitfalls
Custom pass flag (test_passed bit) ignoring report server counts.
Catchers demoting real bugs without review — test passes with DUT bugs.
UVM_FULL in regression — use UVM_HIGH on failing component only.
Printing PASS before report_phase — premature result before check_phase drain.