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. Signatures, Super Calls, and Debug

Part 2 · Phases & Lifecycle · Intermediate

Signatures, Super Calls, and Debug

The exact phase signatures, the old no-argument hooks, the super chain, and how to prove a phase method runs.

On this page

    You add a log line to a component's build, rerun, and it is not there. The component is in the topology, the test compiles cleanly, other components' messages appear. After an hour you notice the method is called buid_phase. Nobody told you, because from SystemVerilog's point of view nothing is wrong: you declared a new method, and nobody calls it.

    The idea: the phaser calls a virtual method by name

    The phaser does not know your class. It holds a uvm_component handle and calls, for example, comp.build_phase(phase). Because the base class declares build_phase as virtual, the call reaches your override, but only if your method has exactly the same name, kind (function or task) and argument list. It is like a dispatcher calling out a call sign over the radio: misspell your call sign and you never hear your call, while the base class quietly answers in your place.

    The picture

    Decision diagram: the phaser's virtual call reaches an exact override, falls back to the base method for a misspelled name, or fails to compile for a wrong kind or arguments.
    How a phase call reaches your code. A misspelled name compiles and is silently ignored; a wrong kind or argument list does not compile at all.

    Build it: the exact declarations

    Phase

    Exact declaration

    build

    function void build_phase(uvm_phase phase);

    connect

    function void connect_phase(uvm_phase phase);

    end of elaboration

    function void end_of_elaboration_phase(uvm_phase phase);

    start of simulation

    function void start_of_simulation_phase(uvm_phase phase);

    run

    task run_phase(uvm_phase phase);

    extract, check, report, final

    function void extract_phase(uvm_phase phase); and the same shape for check_phase, report_phase, final_phase

    the twelve runtime phases

    task main_phase(uvm_phase phase); and the same shape for the other eleven

    Three ways to get it wrong, and what each one does:

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // bad-example
    function void buld_phase(uvm_phase phase);     // compiles, never called: a brand-new method
      `uvm_info("BUILD", "custom build", UVM_LOW)
    endfunction
    
    function void run_phase(uvm_phase phase);      // compile error: the base run_phase is a task
      `uvm_info("RUN", "cannot override a task with a function", UVM_LOW)
    endfunction
    
    function void build(uvm_phase phase);          // compile error: clashes with the old build() hook
      `uvm_info("BUILD", "wrong argument list for build()", UVM_LOW)
    endfunction

    Only the first is silent. A function overriding the virtual task run_phase is illegal SystemVerilog, so it fails at compile time. The third clashes with an older method you may not know exists.

    The old no-argument hooks

    Before UVM had _phase methods, OVM components overrode build(), connect(), run() and so on, with no argument. The library still declares them, and the base phase methods call them: uvm_component::build_phase calls build(), connect_phase calls connect(), run_phase calls run(), and likewise for end_of_elaboration, start_of_simulation, extract, check and report. That is true in UVM 1.2 and in the Accellera library for IEEE 1800.2.

    Two consequences. A method declared as function void connect(); in your class does run, through the base connect_phase, even though it looks like a typo. And build() is not just an old name: it is where the base class applies automatic configuration, which is the subject of What super.build_phase() Really Does. Never write new code against the old hooks; recognise them when you inherit them.

    The super chain

    Every phase method in your class should start with super.<phase>_phase(phase). The reason is not the empty base bodies of today; it is that your parent class may not be the library class tomorrow. In a three-level hierarchy, each super call runs one level up, so a single missing call in the middle silently drops everything above it for every class below it.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // snippet
    class base_agent extends uvm_agent;          // team-wide base: shared setup
      `uvm_component_utils(base_agent)
      function new(string name, uvm_component parent);
        super.new(name, parent);
      endfunction
      function void build_phase(uvm_phase phase);
        super.build_phase(phase);                // uvm_agent: config, is_active
        // shared monitor, coverage, checkers
      endfunction
    endclass
    
    class apb_agent_v2 extends base_agent;
      `uvm_component_utils(apb_agent_v2)
      function new(string name, uvm_component parent);
        super.new(name, parent);
      endfunction
      function void build_phase(uvm_phase phase);
        super.build_phase(phase);                // runs base_agent, which runs uvm_agent
        // APB-specific children
      endfunction
    endclass

    There is one deliberate exception to "super first": a test that registers factory overrides for components its parent creates. Those lines must come before super.build_phase. Why build_phase Is Top-Down explains exactly when "before" matters.

    Watch it run: prove the method is called

    When a phase method seems to do nothing, separate "not called" from "called but wrong" before reading any logic. Put a log line as the method's first statement, then rerun:

    design.sv
    1
    2
    3
    4
    5
    6
    // snippet
    function void build_phase(uvm_phase phase);
      `uvm_info("TRACE", $sformatf("%s entered %s", get_full_name(), phase.get_name()), UVM_NONE)
      super.build_phase(phase);
      // ...
    endfunction
    Diagram
    UVM_INFO dma_tb.sv(...) @ 0: uvm_test_top.env.in_agt [TRACE] uvm_test_top.env.in_agt entered build
    • Line present: the method runs; the bug is in what it does.

    • Line absent, component in the topology: a signature problem. Compare the name letter by letter with the table above.

    • Line absent, component missing from the topology: the component was never created, or was created as a different type. Print the factory (uvm_factory::get().print()) and look for overrides.

    • +UVM_PHASE_TRACE on the command line makes the phaser log every phase transition, which helps when the question is "did this phase run at all?" rather than "did my method run?".

    Tip

    A typo check is cheap to automate. List every method in your code whose name ends in _phase and takes a uvm_phase argument, and compare the names against the twenty-one phase names: anything else is either a custom phase you meant to add or a method the phaser will never call. Several lint tools ship this rule; a ten-line script in the regression flow does the same job.

    The same reasoning applies to the three phase callbacks. phase_started, phase_ready_to_end and phase_ended are virtual functions with one uvm_phase argument, and a misspelled phase_ready_to_ends is just as silent as a misspelled build. Because those callbacks run for every phase, a log line in them is noisy; filter on the phase name before printing.

    What breaks: the report that vanished in a refactor

    A team renamed every report() method in their VIP to report_phase(uvm_phase phase) while removing OVM leftovers, and did the same for check(). One scoreboard's check_phase stopped flagging leftovers. Its author had renamed the method to check_phase but typed function void check_phase(); with no argument. That would not have compiled, so someone "fixed" the compile error by renaming it to chk_phase(uvm_phase phase). The method was never called again, and for three weeks the scoreboard could not fail a test.

    Their fix had two parts: restore the exact signature, and add a self-test that runs one deliberately broken transaction and expects exactly one error. A checker that has never been seen failing has not been tested.

    Interview

    "Your phase method compiles but never runs. What do you check, in order?"

    A weak answer: "I'd check the objections and the phase trace." Objections have nothing to do with a function phase method that is never called.

    A strong answer: "First I prove it isn't called: a log line as its first statement. If the line is missing, it's a signature problem, and the only signature problem that compiles is a wrong name, because a wrong kind or argument list won't override a virtual method and fails to compile. So I compare the name against the base declaration. If the line is there, it's logic. I also check the super chain if the behaviour I'm missing comes from a base class."

    Follow-ups: Why does `function void connect();` with no argument still run? (the base connect_phase calls the old connect() hook) and When is it right to call super last? (factory overrides before super in a test).

    Check yourself A component defines task run_phase(uvm_phase phase); and also task run();. Which run?

    Both, if the component's run_phase calls super.run_phase(phase): the base run_phase calls run(). If run_phase does not call super, only run_phase runs. This is a good reason to delete old hooks when you find them.

    Check yourself A mid-level base class stops calling super.build_phase. Which classes are affected?

    Every class that extends it, directly or indirectly. Each super call runs one level up, so the chain stops at the missing call: uvm_agent's is_active lookup and the library's automatic configuration never run for any agent built on that base.

    Check yourself Is function void run_phase(uvm_phase phase); in a component a silent bug or a compile error?

    A compile error. run_phase is a virtual task in uvm_component, and a function cannot override a task. The silent case is a misspelled name, which simply declares a new method.

    Next: so far the phaser has been a black box that calls your methods. Inside the Phaser opens it, which is what you need to debug the callbacks that run around your phase methods.

    Related topics

    • Inside the Phaser: Nodes, Imps and Schedules

    • What super.build_phase() Really Does

    • Ordering Bugs and Silent Overrides

    Previous

    23 / 280

    Next: Inside the Phaser: Nodes, Imps and Schedules

    Up next

    Up nextInside the Phaser: Nodes, Imps and Schedules

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Why Phases Exist
    • The Phase Schedule: Common and Runtime Phases
    • Traversal Order Rules