Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • Start Here4
  • UVM Foundations14
  • UVM Phases & Simulation Lifecycle26
    • The Phase System
      • Why Phases Exist
      • The Phase Schedule: Common and Runtime Phases
      • Traversal Order Rules
      • Function Phases vs Task Phases
      • Signatures, Super Calls, and Debug
      • Inside the Phaser: Nodes, Imps and Schedules
    • UVM Phases: Build, Connect, Elaborate and Run
    • Objections Deep Dive: Drain Time and Propagation
    • Phase Debugging and End-of-Test Signoff
  • Factory & Configuration15
  • Transaction-Level Modeling (TLM)13
  • UVM Sequences & Stimulus21
  • UVM Agents & Protocol VIP21
  • Environment & Test Classes11
  • Checking & Coverage in UVM21
  • UVM Register Abstraction Layer (RAL)22
  • Advanced UVM in Practice13
  • Debug & Regression10
  • Coding Practice47
  • Verification in Industry Practice10
  • Senior Prep: Architecture, Leadership and Interviews32
Loading lesson

‹The Phase System
  1. Topics
  2. UVM Verification
  3. UVM Phases & Simulation Lifecycle
  4. The Phase System
  5. The Phase Schedule: Common and Runtime Phases

Part 2 · Phases & Lifecycle · Intermediate

The Phase Schedule: Common and Runtime Phases

The nine common phases, the twelve runtime phases that run beside run_phase, and what each one is for.

On this page

    Your run_phase objections have all dropped. The objection trace shows the test's last drop at 2 ms. Yet the simulation keeps going, and check_phase does not start until 5 ms. Nothing is hung; something is still busy. The question is where, and the answer is a part of the schedule many engineers have never drawn: a second set of phases running beside run_phase.

    The idea: two tracks that meet at extract

    UVM has two families of phases. The nine common phases (build through final) run on every component in every testbench. The twelve runtime phases (pre_reset through post_shutdown) are optional, finer steps for the time-consuming middle. They do not come after run_phase, and they are not inside it. They run on a parallel track that starts when run_phase starts.

    Picture two railway tracks leaving the same station at the same moment. One train (run_phase) goes straight through. The other stops at twelve small stations on the way. Both must arrive at the next junction, extract_phase, before anything after it can happen. If the stopping train is held at one of its stations, the junction waits, even though the express arrived long ago.

    In library terms, these tracks are domains. run_phase and the other common phases belong to the common domain. The twelve runtime phases belong to the uvm domain (or to a user-defined domain), which is joined to the common domain so that it starts with run_phase and must finish before extract. Phase Domains and Sync covers user domains.

    The picture: the full UVM phase schedule

    Diagram: build, connect, end_of_elaboration and start_of_simulation in sequence, then run_phase in parallel with the uvm domain's twelve runtime phases in four groups, both feeding extract, check, report and final.
    The UVM phase schedule. The four setup phases and the four cleanup phases are zero-time functions. run_phase (common domain) and the twelve runtime phases (uvm domain) are tasks that start together and both must finish before extract_phase.

    Keep this picture. Almost every phase question in an interview, and almost every end-of-test bug, is answered by finding the right box in it.

    The nine common phases and what lives in each

    Phase

    Kind

    Walk

    Job

    In the DMA bench

    build_phase

    function

    top-down

    Create children through the factory, read configuration.

    dma_env creates three agents and the scoreboard.

    connect_phase

    function

    bottom-up

    Wire ports, forward handles.

    Agents set ap = mon.ap; the env connects them to sb.

    end_of_elaboration_phase

    function

    bottom-up

    Audit the finished structure.

    dma_base_test prints the topology.

    start_of_simulation_phase

    function

    bottom-up

    Banners and last setup before time moves.

    Not used.

    run_phase

    task

    parallel

    Drive, monitor, check over time.

    Drivers and monitors loop; the test runs the scenario under an objection.

    extract_phase

    function

    bottom-up

    Collect final numbers.

    Not used.

    check_phase

    function

    bottom-up

    Pass or fail on settled data.

    dma_scoreboard reports leftovers and empty runs.

    report_phase

    function

    bottom-up

    Print summaries.

    dma_scoreboard prints the match count.

    final_phase

    function

    top-down

    Close files, release resources.

    Not used.

    Eight of the nine are functions, so they run in zero simulated time: the first four at time 0, the last four at the moment the run phases end. Only run_phase can wait. The walk column is explained in Traversal Order Rules.

    The twelve runtime phases

    Group

    Phases

    Typical use

    Reset

    pre_reset_phase, reset_phase, post_reset_phase

    Apply and release reset.

    Configure

    pre_configure_phase, configure_phase, post_configure_phase

    Program registers before traffic.

    Main

    pre_main_phase, main_phase, post_main_phase

    The primary stimulus.

    Shutdown

    pre_shutdown_phase, shutdown_phase, post_shutdown_phase

    Let in-flight work drain.

    All twelve are tasks and run in order among themselves. Each has its own objection, so a phase ends only when no one objects to it. When nobody raises an objection in them, as in the DMA bench, they all pass through at time 0. Runtime Sub-Phases explains when to use them and why drivers stay in run_phase.

    Build it: one component, every common phase

    The skeleton below shows each common phase method with its exact signature. A real component overrides only the ones it needs. There is no objection here on purpose: raising and dropping belongs to the test or a sequence, never to a generic component.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    // snippet
    class phase_demo extends uvm_component;
      `uvm_component_utils(phase_demo)
    
      function new(string name, uvm_component parent);
        super.new(name, parent);
      endfunction
    
      function void build_phase(uvm_phase phase);
        super.build_phase(phase);              // create children, read config
      endfunction
      function void connect_phase(uvm_phase phase);
        super.connect_phase(phase);            // wire ports, forward handles
      endfunction
      function void end_of_elaboration_phase(uvm_phase phase);
        super.end_of_elaboration_phase(phase); // audit the structure
      endfunction
      function void start_of_simulation_phase(uvm_phase phase);
        super.start_of_simulation_phase(phase);// banners
      endfunction
      task run_phase(uvm_phase phase);         // the only common task phase
        super.run_phase(phase);
      endtask
      function void extract_phase(uvm_phase phase);
        super.extract_phase(phase);            // collect numbers
      endfunction
      function void check_phase(uvm_phase phase);
        super.check_phase(phase);              // decide pass or fail
      endfunction
      function void report_phase(uvm_phase phase);
        super.report_phase(phase);             // print summaries
      endfunction
      function void final_phase(uvm_phase phase);
        super.final_phase(phase);              // close files
      endfunction
    endclass

    Three more callbacks exist on every component and are called for every phase, common and runtime: phase_started, phase_ready_to_end and phase_ended. They are how you hook the schedule itself; Inside the Phaser shows them in use.

    Watch it run: both tracks in one log

    This log comes from a copy of the smoke test that overrides phase_started and phase_ended to print each phase's full name (the ended line is printed only for run, main and post_shutdown):

    Diagram
    UVM_INFO dma_tb.sv(...) @ 0: uvm_test_top [PH] started common.build
    UVM_INFO dma_tb.sv(...) @ 0: uvm_test_top [PH] started common.connect
    UVM_INFO dma_tb.sv(...) @ 0: uvm_test_top [PH] started common.end_of_elaboration
    UVM_INFO dma_tb.sv(...) @ 0: uvm_test_top [PH] started common.start_of_simulation
    UVM_INFO dma_tb.sv(...) @ 0: uvm_test_top [PH] started common.run
    UVM_INFO dma_tb.sv(...) @ 0: uvm_test_top [PH] started uvm.uvm_sched.pre_reset
       ... reset through pre_main, all @ 0 ...
    UVM_INFO dma_tb.sv(...) @ 0: uvm_test_top [PH] started uvm.uvm_sched.main
    UVM_INFO dma_tb.sv(...) @ 0: uvm_test_top [PH] ended   uvm.uvm_sched.main
       ... post_main through shutdown, all @ 0 ...
    UVM_INFO dma_tb.sv(...) @ 0: uvm_test_top [PH] started uvm.uvm_sched.post_shutdown
    UVM_INFO dma_tb.sv(...) @ 655000: uvm_test_top [PH] ended   common.run
    UVM_INFO dma_tb.sv(...) @ 655000: uvm_test_top [PH] ended   uvm.uvm_sched.post_shutdown
    UVM_INFO dma_tb.sv(...) @ 655000: uvm_test_top [PH] started common.extract
    UVM_INFO dma_tb.sv(...) @ 655000: uvm_test_top [PH] started common.check
    UVM_INFO dma_tb.sv(...) @ 655000: uvm_test_top [PH] started common.report
    UVM_INFO dma_tb.sv(411) @ 655000: uvm_test_top.env.sb [SB] 8 words matched, 0 mismatched
    UVM_INFO dma_tb.sv(...) @ 655000: uvm_test_top [PH] started common.final
    • common.run and uvm.uvm_sched.pre_reset start at the same time, 0. The prefix is the domain (and schedule) each phase belongs to.

    • No one objects in the runtime phases, so main starts and ends at time 0. The DMA traffic all happens in run_phase.

    • post_shutdown started at 0 but ended at 655000, together with run. The last runtime phase is held until run_phase is ready to end too, which is how the two tracks meet before extract.

    • Extract, check, report and final all run at 655000, the time the run phases ended, not at time 0.

    What breaks: the shutdown sequence nobody stopped

    Back to the opening. A block team had added a background sequence that polls a status register, started from the test's shutdown_phase with its own objection "so the DUT is idle before we check". The poll loop waited for a FIFO-empty bit that, on one configuration, never set. The run_phase objections dropped on time, so the objection trace for run looked clean, and the team spent a day looking at the wrong phase.

    The clue was in the schedule: extract waits for both tracks. A phase trace (+UVM_PHASE_TRACE) showed shutdown started and never ended, and the objection trace for that phase named the polling sequence. The fix was a bounded poll with an error on timeout. The lesson for debugging is to ask "which phase is still executing?" before asking "who holds the run objection?".

    Common pitfall

    "main_phase runs after run_phase" is the most common wrong answer about the schedule. main_phase runs during run_phase. A driver that drives in both run_phase and main_phase drives the same bus from two threads at once.

    Interview

    "Where does main_phase run relative to run_phase, and what has to happen before extract_phase starts?"

    A weak answer: "main_phase is one of the sub-phases of run, so it runs inside run_phase, after reset and configure." The ordering inside the runtime group is right, but "inside run" suggests run_phase waits for it in some nested way.

    A strong answer: "run_phase is in the common domain; the twelve runtime phases are in the uvm domain. Both start right after start_of_simulation and run in parallel. Within the uvm domain the twelve run in order, each with its own objection. extract_phase starts only when run_phase and post_shutdown have both finished, so an objection held in any runtime phase delays extract even when run's objections are all dropped."

    Follow-ups: All run objections are dropped but the simulation continues: why? (a runtime phase is still held) and Why do most teams keep drivers in run_phase? (a runtime phase kills its threads when it ends; see Runtime Sub-Phases).

    Check yourself A scoreboard must confirm its expected queue is empty at the end of the test. Which phase, and why not at the end of run_phase?

    check_phase. It runs only after run_phase and every runtime phase have ended, so no monitor can still be writing. Code at the end of a component's run_phase races the last transactions, and in a forever-looping component it never runs at all.

    Check yourself At what simulated time does start_of_simulation_phase run? And report_phase?

    start_of_simulation runs at time 0, like build: every phase before run is a zero-time function, later in order but not in time. report_phase runs at the time the run phases ended (655000 ps in the smoke test), also in zero time.

    Check yourself A test raises an objection in main_phase and drops it after 3 µs, and raises nothing in run_phase. The DMA traffic is all in drivers' run_phase. When does run_phase end?

    At about 3 µs (plus any drain time). run_phase is ready to end at time 0 because nobody objects to it, but the end of the uvm domain is synchronised with run: run cannot pass extract until post_shutdown is done, and post_shutdown cannot start until main has ended. So the main_phase objection holds the whole run window open.

    Next: the schedule says which phase runs; Traversal Order Rules says in what order the phaser visits the components inside one phase.

    Related topics

    • Traversal Order Rules

    • Runtime Sub-Phases

    • Phase Domains and Sync

    Previous

    20 / 280

    Next: Traversal Order Rules

    Up next

    Up nextTraversal Order Rules

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Function Phases vs Task Phases
    • Signatures, Super Calls, and Debug
    • Inside the Phaser: Nodes, Imps and Schedules