Part 2 · Phases & Lifecycle · Intermediate
run_phase vs Runtime Schedule: Choosing the Right Model
When plain run_phase suffices, when the 12 runtime sub-phases add value, and why mixing both in one component causes confusion.
Two parallel schedules exist
UVM provides run_phase as a single bucket for all time-consuming activity. It also provides 12 runtime sub-phases (reset, configure, main, shutdown groups) that run in parallel with run_phase. These are alternative organizational models — not layers to combine in one component.
[PHASE][RUN] two schedules, same time window
SCHEDULE A (plain run_phase):
test.run_phase ──► raise → stimulus → drop
SCHEDULE B (runtime sub-phases):
reset_phase ──► configure_phase ──► main_phase ──► shutdown_phase
(each with own objections, sequential across groups)
BOTH run in parallel with each other at the UVM scheduler level
PICK ONE per component — do not override both for same activityrun_phase and runtime sub-phases occupy the same simulation time window.
Each runtime sub-phase has its own objection count — independent end triggers.
Components that use runtime sub-phases typically leave run_phase as super-only.
When plain run_phase is enough
Good fit
Simple block-level testbench: reset, traffic, done.
Single interface or loosely coupled agents.
No cross-agent agreement needed on intermediate stages.
Quick bring-up tests and unit-level environments.
// Simple test — run_phase only, no runtime sub-phases anywhere
class simple_test extends uvm_test;
task run_phase(uvm_phase phase);
fork super.run_phase(phase); join_none
phase.raise_objection(this);
wait_reset(); // inline reset wait
basic_seq::type_id::create("seq").start(env.sqr);
phase.drop_objection(this);
endtask
endclass[RUN] simple flow in one run_phase
raise → wait reset → run seq → drop
all agents use super.run_phase only
no reset_phase / main_phase overridesWhen runtime sub-phases add value
Good fit
SoC-level: multiple agents must finish reset before any configuration.
RAL register programming must complete before main traffic on all interfaces.
Coordinated shutdown to drain in-flight transactions across agents.
Reusable VIP with well-defined bring-up/shutdown contracts.
// Agent uses runtime sub-phases — run_phase is super-only
class axi_driver extends uvm_driver #(axi_item);
task run_phase(uvm_phase phase);
super.run_phase(phase); // no activity here
endtask
task reset_phase(uvm_phase phase);
phase.raise_objection(this, "idle during reset");
drive_idle();
wait (vif.aresetn === 1'b1);
phase.drop_objection(this, "reset done");
endtask
task main_phase(uvm_phase phase);
phase.raise_objection(this, "main traffic");
forever begin
seq_item_port.get_next_item(req);
drive(req);
seq_item_port.item_done();
end
endtask
endclass[PHASE] runtime sub-phase groups
RESET: pre_reset → reset → post_reset
CONFIGURE: pre_configure → configure → post_configure
MAIN: pre_main → main → post_main
SHUTDOWN: pre_shutdown → shutdown → post_shutdown
each group completes (objections drain) before next group startsDecision matrix and migration
[PHASE][UVM] decision matrix
Question run_phase runtime sub-phases
───────────────────────────────────────── ───────── ──────────────────
Single agent, simple flow ✓ preferred overkill
Multi-agent reset coordination manual ✓ preferred
RAL configure before traffic manual ✓ preferred
Graceful multi-interface shutdown manual ✓ preferred
Quick sanity / unit test ✓ preferred unnecessary
Reusable VIP with staged lifecycle avoid ✓ preferredMigrating from run_phase to runtime sub-phases: move reset-wait logic to reset_phase, register programming to configure_phase, stimulus loop to main_phase, and drain logic to shutdown_phase. Leave run_phase as super-only.
Key takeaways
run_phase and 12 runtime sub-phases are alternative models — pick one per component.
Plain run_phase suits simple flows; runtime sub-phases suit multi-agent coordination.
Runtime groups (reset/configure/main/shutdown) map to real bring-up stages.
Each runtime sub-phase has independent objections — same raise/drop rules apply.
Common pitfalls
Stimulus in both run_phase and main_phase in the same driver — double-driving.
Register config in reset_phase — breaks staged ordering (belongs in configure_phase).
Only some agents use runtime sub-phases while test uses run_phase raise — timing mismatch.
Assuming runtime sub-phases replace run_phase globally — they run in parallel, not instead.