Part 2 · Phases & Lifecycle · Intermediate
extract_phase Role: Gathering Results Bottom-Up
How extract_phase propagates counters, coverage, and status from children to parents before check_phase evaluates invariants.
What extract_phase does
The extract_phase callback runs after all run-time activity ends. Its job is to pull final numbers out of leaf components (scoreboards, coverage collectors, counters) and make them visible to parent components. Traversal is bottom-up : every child extracts before its parent, so parents see settled child state.
[PHASE][UVM] extract_phase traversal
leaf agent scoreboard
extract: mismatch_count, txn_count
│
▼
env scoreboard wrapper (if any)
extract: merge child totals
│
▼
tb_env
extract: copy into env-level fields for check_phaseextract_phase is read-only aggregation — do not start new simulation activity.
Copy or reference settled counters; do not re-run compare logic here.
Always call super.extract_phase(phase) so children extract first.
Reference implementation
A typical env extracts scoreboard and coverage statistics into fields that check_phase and report_phase consume.
class my_env extends uvm_env;
`uvm_component_utils(my_env)
axi_env axi;
scoreboard scb;
real cov_pct;
int mismatches, exp_count, act_count;
function void extract_phase(uvm_phase phase);
super.extract_phase(phase); // children extract first (bottom-up)
mismatches = scb.mismatch_count;
exp_count = scb.expected_count;
act_count = scb.actual_count;
if (!uvm_config_db#(real)::get(this, "", "axi_cov_pct", cov_pct))
cov_pct = 0.0;
`uvm_info("EXTRACT", $sformatf(
"mismatches=%0d exp=%0d act=%0d cov=%0.1f%%",
mismatches, exp_count, act_count, cov_pct), UVM_MEDIUM)
endfunction
endclass// Leaf scoreboard: source of truth for compare totals
class my_scoreboard extends uvm_scoreboard;
int mismatch_count, expected_count, actual_count;
function void extract_phase(uvm_phase phase);
super.extract_phase(phase);
// Optional: snapshot coverage subscriber totals here too
`uvm_info("SCB_EXTRACT", $sformatf(
"final mismatch=%0d txn=%0d", mismatch_count, actual_count), UVM_HIGH)
endfunction
endclassCoverage extraction pattern
Coverage percentages are often computed in a subscriber or coverage component during run_phase. extract_phase is the right place to read the final bucket hit rates via config_db or a direct handle.
function void extract_phase(uvm_phase phase);
super.extract_phase(phase);
cov_collector.get_coverage(cov_pct);
uvm_config_db#(real)::set(this, "", "env_cov_pct", cov_pct);
endfunctionKey takeaways
extract_phase is bottom-up aggregation — children settle before parents read.
Pull final counters and coverage here; leave invariant evaluation to check_phase.
Log extracted totals at UVM_MEDIUM so regressions show signoff inputs.
Common pitfalls
Running stimulus or waiting on clocks in extract_phase — it is a zero-time function phase.
Skipping super.extract_phase and reading child counters before they are finalized.
Re-implementing scoreboard compare logic in extract instead of copying totals.
Debug checklist
[PHASE][UVM] extract validation
□ super.extract_phase called in every override
□ child counters non-zero after known-good traffic test
□ coverage percentage read after simulation drain completes
□ extracted values logged once (avoid duplicate spam per hierarchy level)If check_phase sees zeros, verify extract ran and super was called.
Use +UVM_PHASE_TRACE to confirm extract_phase order across the tree.