Part 2 · Phases & Lifecycle · Intermediate

Runtime Sub-Phase Use Cases: SoC, RAL, VIP, and Shutdown

Production scenarios where runtime sub-phases shine — multi-clock SoC bring-up, RAL configuration flows, reusable VIP lifecycle, and coordinated shutdown.

Use case 1: Multi-clock SoC bring-up

A SoC with multiple clock domains and a power-sequencing controller needs all agents to wait for their respective clocks before reset, and all to finish reset before configuration:

systemverilog
// CPU agent: wait for CPU clock
task pre_reset_phase(uvm_phase phase);
  phase.raise_objection(this, "wait CPU clock");
  wait (cpu_clk_stable);
  phase.drop_objection(this, "CPU clock ready");
endtask

// DDR agent: wait for DDR clock (different timing)
task pre_reset_phase(uvm_phase phase);
  phase.raise_objection(this, "wait DDR clock");
  wait (ddr_clk_stable);
  phase.drop_objection(this, "DDR clock ready");
endtask

// Both agents: reset_phase waits for shared SoC reset release
task reset_phase(uvm_phase phase);
  phase.raise_objection(this, "SoC reset");
  drive_idle();
  wait (soc_reset_n === 1'b1);
  phase.drop_objection(this, "SoC reset released");
endtask
diagram
[PHASE][RUN] SoC bring-up timeline

  pre_reset:  CPU clk ready ──┐
  pre_reset:  DDR clk ready ──┤ parallel, both must drop
  pre_reset:  IO clk ready  ──┘
       │
  reset:      all agents idle + wait soc_reset_n (parallel)
       │
  post_reset: all agents settle N cycles (parallel)
       │
  configure:  RAL programming begins (ONLY after reset group done)
  • pre_reset handles per-domain clock readiness in parallel.

  • reset_phase synchronizes on shared reset release.

  • Cross-domain coordination is automatic via group objections.


Use case 2: RAL configuration flow

systemverilog
class soc_env extends uvm_env;
  ral_block_soc regmodel;
  reg2bus_adapter adapter;

  task configure_phase(uvm_phase phase);
    soc_cfg_seq cfg;
    fork super.configure_phase(phase); join_none
    phase.raise_objection(this, "SOC register config");

    // Reset mirror to hardware reset values
    regmodel.reset();

    // Frontdoor configure via adapter
    cfg = soc_cfg_seq::type_id::create("cfg");
    cfg.regmodel = regmodel;
    cfg.start(reg_sequencer);

    // Verify critical mode bits
    regmodel.ctrl.mode.read(status, .path(UVM_FRONTDOOR));
    if (regmodel.ctrl.mode.get() != EXPECTED_MODE)
      `uvm_error("CFG", "mode register mismatch after config")

    phase.drop_objection(this, "SOC register config done");
  endtask
endclass
diagram
[PHASE][RUN][UVM] RAL configure flow

  configure_phase:
    regmodel.reset()
    frontdoor writes (mode, clock enables, interrupt masks)
    readback verify critical registers
    drop  main_phase can begin traffic
  • configure_phase is the canonical home for RAL frontdoor sequences.

  • regmodel.reset() in configure_phase establishes known mirror state.

  • Readback verify before main_phase catches config errors early.


Use case 3: Reusable VIP lifecycle

A reusable AXI VIP packages its lifecycle into runtime sub-phases so integrators get correct behavior without manual coordination:

systemverilog
class axi_vip_agent extends uvm_agent;
  // VIP documents: override nothing in run_phase — use sub-phases

  task reset_phase(uvm_phase phase);
    phase.raise_objection(this, "AXI VIP reset");
    drv.drive_reset_state();
    mon.wait_reset_done();
    phase.drop_objection(this, "AXI VIP reset done");
  endtask

  task configure_phase(uvm_phase phase);
    phase.raise_objection(this, "AXI VIP config");
    apply_cfg_to_vip();  // burst length, ID width, etc.
    phase.drop_objection(this, "AXI VIP config done");
  endtask

  task main_phase(uvm_phase phase);
    // default_sequence auto-starts traffic if configured
    super.main_phase(phase);
  endtask

  task shutdown_phase(uvm_phase phase);
    phase.raise_objection(this, "AXI VIP shutdown");
    drv.drain_and_idle();
    phase.drop_objection(this, "AXI VIP shutdown done");
  endtask
endclass
diagram
[UVM][PHASE] VIP integration contract

  integrator env:
    build:   create axi_vip_agent, pass cfg via config_db
    connect: wire analysis ports
    (no run_phase override needed)

  VIP handles: reset  configure  main  shutdown internally
  • VIP runtime sub-phases are the integration contract — integrator stays thin.

  • Document which phases the VIP overrides and which it expects from the env.

  • shutdown_phase in VIP ensures clean bus state for next test or power-down.


Use case 4: Coordinated multi-interface shutdown

systemverilog
class soc_test extends uvm_test;
  task post_main_phase(uvm_phase phase);
    phase.raise_objection(this, "stop all traffic");
    global_stop_ev.trigger();
    #(cfg.post_main_drain_ns);
    phase.drop_objection(this, "traffic stopped");
  endtask
endclass

// Each agent drains in shutdown_phase
class generic_agent extends uvm_agent;
  task shutdown_phase(uvm_phase phase);
    phase.raise_objection(this, "drain");
    wait (drv.inflight_count == 0);
    wait (mon.pipeline_empty);
    drv.drive_idle();
    phase.drop_objection(this, "drained");
  endtask
endclass
diagram
[PHASE][RUN] coordinated shutdown

  post_main:     global stop event + drain delay
  pre_shutdown:  verify no new items accepted
  shutdown:      each agent drains inflight (parallel)
  post_shutdown: verify all interfaces idle
       │
       ▼ clean state  extract_phase

Key takeaways

  • SoC bring-up: pre_reset per clock domain, reset_phase for shared reset sync.

  • RAL configuration belongs in configure_phase with readback verify.

  • VIP sub-phases are the reusable integration contract for integrators.

  • Coordinated shutdown via events + shutdown_phase prevents truncated transactions.

Common pitfalls

  • RAL config in test run_phase while agents use configure_phase — ordering race.

  • VIP that only implements main_phase — integrator must handle reset manually.

  • Shutdown without inflight counter — drain completes before transactions finish.

  • Different drain times per agent — fastest agent drops while others still busy.