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.

diagram
[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_phase
  • extract_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.

systemverilog
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
systemverilog
// 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
endclass

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

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

Key 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

diagram
[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.