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.

diagram
[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 activity
  • run_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.

systemverilog
// 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
diagram
[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 overrides

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

systemverilog
// 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
diagram
[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 starts

Decision matrix and migration

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

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