Part 2 · Phases & Lifecycle · Intermediate

Phase Scheduler Overview: uvm_phase and Global Orchestration

How the UVM phase scheduler, uvm_phase objects, and the component tree cooperate to execute the common phase list across every node.

Scheduler responsibilities

The phase scheduler is the orchestration engine inside UVM. It owns the phase graph, traversal order, parallel runtime scheduling, and synchronization between domains.

  1. Iterate the fixed common-phase list in order.

  2. For each phase, walk the component hierarchy in the correct direction.

  3. Invoke the matching callback on every component.

  4. For task phases, wait until all parallel branches and objections resolve.

  5. Advance — no user code manually 'calls next phase'.

diagram
[UVM][PHASE] scheduler loop (conceptual)

phase = build
  traverse_top_down(root, build_phase)
phase = connect
  traverse_bottom_up(root, connect_phase)
...
phase = run
  fork all run_phase tasks + runtime sub-phases
  wait objection_count == 0 (+ drain_time)
phase = extract
  traverse_bottom_up(root, extract_phase)
...

Key takeaways

  • The scheduler is global — individual components never drive phase progression.

  • uvm_phase argument gives access to raise_objection/drop_objection in tasks.

  • Task phases block scheduler advance until completion conditions are met.

Common pitfalls

  • Calling phase.jump() without understanding domain impact — advanced, risky.

  • Expecting build_phase on sibling A before sibling B — not guaranteed.

  • Mixing module initial blocks with UVM phase schedule for TB bring-up.


uvm_phase object: what you get in callbacks

Every phase callback receives uvm_phase phase. In task phases it is the handle for objections, phase state queries, and (in advanced usage) domain control.

systemverilog
task run_phase(uvm_phase phase);
  super.run_phase(phase);
  phase.raise_objection(this, "start traffic");
  main_sequence.start(sequencer);
  wait_for_quiescence();
  phase.drop_objection(this, "traffic done");
endtask

Scheduler vs component boundaries

diagram
[PHASE] ownership split

scheduler owns:
  phase order
  tree traversal direction
  waiting for task completion
  objection accounting (with components)

component owns:
  what to build in build_phase
  what to connect in connect_phase
  what stimulus to run in run_phase
  what to check in check_phase
  • Components implement callbacks; scheduler invokes them.

  • Objections are the distributed handshake that ends run-time.

  • Phase trace prints scheduler decisions for debug.

Key takeaways

  • Treat uvm_phase as the run-time control handle in task phases.

  • Clear ownership split prevents 'integrator scripts' from reappearing.

  • raise/drop must balance on every stimulus path.

Common pitfalls

  • Dropping objections in a branch that not every path executes.

  • Raising objections in function phases — not supported.

  • Ignoring super.run_phase — may skip library bookkeeping.