Part 2 · Phases & Lifecycle · Intermediate
Motivation Case Studies: When Phases Earn Their Keep
Real integration stories — multi-protocol env assembly, reset-before-stimulus ordering, and scoreboard wiring — showing where phases prevent production failures.
Case 1: AXI + APB + memory in one env
Three protocol VIPs, one scoreboard, two clock domains. Without phases, the integrator must manually sequence twelve construction steps and eight connects . With phases, each VIP owns its callbacks.
[UVM][PHASE] multi-protocol integration
manual approach pain:
- reorder VIP init when passive APB added
- scoreboard imp null when monitor created late
- factory override for error injector missed
phased approach win:
test.build sets cfg + overrides
env.build creates all agents + scb
env.connect wires mon.ap -> scb.imps
run_phase sequences start after reset sub-phasesclass soc_env extends uvm_env;
function void build_phase(uvm_phase phase);
super.build_phase(phase);
axi = axi_agent::type_id::create("axi", this);
apb = apb_agent::type_id::create("apb", this);
mem = mem_model ::type_id::create("mem", this);
scb = soc_scb ::type_id::create("scb", this);
endfunction
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
axi.mon.ap.connect(scb.axi_imp);
apb.mon.ap.connect(scb.apb_imp);
mem.ap.connect(scb.mem_imp);
endfunction
endclassKey takeaways
Adding a passive agent should not rewrite the integrator's initial block.
Scoreboard wiring belongs in env connect_phase after all monitors exist.
Factory overrides belong in test build before env build.
Common pitfalls
Hard-wiring scoreboard connects inside VIPs — breaks reuse.
Creating memory model in run_phase when scoreboard connects in connect.
Mixing protocol config and structural create across multiple phases.
Case 2: Reset before stimulus
Reset sequencing is a behavioral synchronization problem. Runtime sub-phases (covered later) and run_phase parallelism exist so reset completes before main stimulus without ad-hoc delays.
[PHASE][RUN] reset story
without schedule:
fork driver + monitor at t=0
reset deassert at t=100ns (maybe)
first beat corrupted -> debug spiral
with schedule:
pre_reset/reset/post_reset sub-phases
main/test sequences start in main
objections hold run until traffic drainstask run_phase(uvm_phase phase);
super.run_phase(phase);
wait_reset_deasserted(); // in agent run, not build
phase.raise_objection(this, "stimulus");
seq.start(sqr);
phase.drop_objection(this, "stimulus done");
endtaskCase 3: Premature $finish vs objections
Burst test ends at 10us by timeout while AXI outstanding transactions remain.
Scoreboard reports pass because checks were skipped on truncated traffic.
Objection-balanced run_phase plus check_phase zero-txn guard catches the false pass.
[UVM] completion contrast
magic delay:
#10us; $finish;
-> false pass risk
objections:
raise before seq.start
drop after drain + idle
-> end tracks real quiescenceKey takeaways
Case studies map directly to structural, behavioral, and completion sync axes.
Reset and main ordering is a phase-schedule problem, not a longer #delay.
Objections align simulation end with traffic reality.
Common pitfalls
Using start_of_simulation to drive reset — still zero-time function phase.
Assuming fork/join in test replaces agent-level reset discipline.
Declaring pass in run_phase before check_phase aggregation.