Part 2 · Phases & Lifecycle · Intermediate
The Common Phase List: Nine Phases and Their Jobs
The complete list of nine common UVM phases, what each is for, function vs task classification, and typical content per callback.
The nine phases in order
build_phase — construct children via factory; config_db gets (top-down).
connect_phase — TLM port/export/imp wiring (bottom-up).
end_of_elaboration_phase — structural sanity, topology print (bottom-up).
start_of_simulation_phase — banners, last config, arm watchdogs (top-down).
run_phase — time-consuming stimulus and checking (parallel task).
extract_phase — harvest counters, coverage snapshots (bottom-up).
check_phase — evaluate pass/fail predicates (bottom-up).
report_phase — format and print summary (bottom-up).
final_phase — close files, flush DBs (top-down).
[UVM][PHASE] common list mnemonic
BUILD block (function):
build -> connect -> end_of_elab -> start_of_sim
RUN block (task):
run_phase (+ 12 runtime sub-phases in parallel)
CLEANUP block (function):
extract -> check -> report -> finalOnly run_phase and the runtime sub-phases consume simulation time. The other eight are
zero-time function phases.
Key takeaways
Memorize the list as three blocks: build, run, cleanup.
Each phase has a narrow, well-defined job — mixing jobs breaks methodology.
end_of_elaboration is the last safe moment for structural debug prints.
Common pitfalls
Driving pins in start_of_simulation — still zero-time; use run_phase.
Connecting TLM in extract_phase — far too late.
Skipping check_phase because report 'looks fine'.
Typical content per phase
build_phase
function void build_phase(uvm_phase phase);
super.build_phase(phase);
if (!uvm_config_db#(my_cfg)::get(this, "", "cfg", cfg))
`uvm_fatal("NOCFG", "cfg missing")
mon = my_monitor::type_id::create("mon", this);
if (cfg.is_active)
drv = my_driver::type_id::create("drv", this);
endfunctionconnect_phase
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
if (cfg.is_active)
drv.seq_item_port.connect(sqr.seq_item_export);
mon.ap.connect(scb.analysis_imp);
endfunctioncheck / report / final
function void check_phase(uvm_phase phase);
super.check_phase(phase);
scb.compare_ok();
endfunction
function void report_phase(uvm_phase phase);
super.report_phase(phase);
`uvm_info("RPT", $sformatf("checked=%0d errors=%0d",
scb.checked, scb.errors), UVM_LOW)
endfunction
function void final_phase(uvm_phase phase);
super.final_phase(phase);
cov_db.flush();
endfunction[PHASE] allowed actions quick reference
build: create, config get, override setup
connect: TLM connect, virtual sqr handles
end_of_elab: topology print, structural asserts
start_of_sim: banners, final cfg tweaks
run: time, events, sequences, objections
extract: sample counts, coverage grab
check: pass/fail tests
report: human-readable summary
final: file/DB cleanupKey takeaways
If an action's phase is unclear, ask which dependency it satisfies.
check aggregates; report presents; final releases resources.
run_phase owns all time-consuming behavior.
Common pitfalls
Heavy computation in report_phase that should be in extract.
Creating components in check_phase when scoreboard needs them earlier.
Using final_phase for pass/fail — too late, use check_phase.