← Design Verification Interviews

Interview Question · Code Reading

Type and Instance Overrides Together

L1 JuniorL2 Mid-LevelL3 Senioruvmfactory

The Question

The interviewer asks

Three agents each create a bus_driver. The test registers these overrides. Which class does each agent's driver get?

systemverilog
// soc_env builds agt0, agt1 and agt2; each agent creates a bus_driver named drv.
function void build_phase(uvm_phase phase);    // in the test
  uvm_factory f = uvm_factory::get();
  bus_driver::type_id::set_inst_override(slow_driver::get_type(), "env.agt1.drv", this);
  f.set_inst_override_by_type(bus_driver::get_type(), slow_driver::get_type(), "env.agt2.drv");
  bus_driver::type_id::set_type_override(err_driver::get_type());
  env = soc_env::type_id::create("env", this);
endfunction
Reveal the Model Answer

agt0 gets err_driver from the type override. agt1 gets slow_driver, because a matching instance override beats a type override, whatever the order. agt2 also gets err_driver. The factory's own method takes a full path, so "env.agt2.drv" matched nothing. The type_id form is relative to this, which made "env.agt1.drv" correct.

What create() Asks the FactoryThe factory's decision for one create call. Arrows are the order of the checks.
What create() asks the factoryThe factory's decision for one `create` call. Arrows are the order of the checks. request create("drv") incr_driver atport_b.drv check Instanceoverrides In order added; firstmatch wins check Type override Only if no instancematch result Instance result err_driver forport_b result Type result Its override type result Requested type incr_driver forport_a type + full pathpath matchesno matchregisterednone
Read the diagram as text
  • create("drv"): incr_driver at port_b.drv
  • Instance overrides: In order added; first match wins
  • Type override: Only if no instance match
  • Instance result: err_driver for port_b
  • Type result: Its override type
  • Requested type: incr_driver for port_a
  • create("drv") → Instance overrides: type + full path
  • Instance overrides → Instance result: path matches
  • Instance overrides → Type override: no match
  • Type override → Type result: registered
  • Type override → Requested type: none

The order of the calls that added the overrides does not change this order of checks.

Self-Check

Tick each key point you covered in your answer.

What Interviewers Listen For (Junior)

A good junior answer gets agt0 and agt1 right. It explains that the factory checks instance overrides before type overrides.

Cross-Questions

Where the interviewer goes next. Open a node to practise that follow-up.

WhyWhat IfBreak ItCompareScale It

  1. Type and Instance Overrides Together
  2. WhyWhy Instance Overrides WinL2 Mid-Level

    Why does the factory check instance overrides before type overrides?

    Reveal the Model Answer

    An instance override is the more specific request: "this one component". A type override means "everywhere else". Checking the specific case first lets a test change all agents except one, without caring about the order of the calls.

    Self-Check

    Tick each key point you covered in your answer.

    Misconception

    "Instance overrides win because they are newer."

    Order does not decide it. Even a type override registered later loses to a matching instance override.

    Source Measured: the twin on dv.uvm.type-vs-instance-override (type override registered last), uvm-core 2020.3.1 on Verilator 5.052

  3. What IfAn Instance Override with the Wrong PathL2 Mid-Level

    What if the instance override path is written relative to the wrong scope?

    Reveal the Model Answer

    The component method set_inst_override_by_type() puts the caller's full name in front of the path. The factory method of the same name takes the path as written, from the top. Mix them up and the path matches nothing. The factory then builds the original type and reports nothing, so print the created type to check.

    Self-Check

    Tick each key point you covered in your answer.

    Tool as Truth

    "A wrong override path gives an error."

    A path is a pattern. If nothing matches, the factory builds the original type without a message.

    Source uvm-core 2020.3.1 (IEEE 1800.2 library) source, base/uvm_component.svh, set_inst_override_by_type

  4. Break ItA Wildcard Override That Beat a Specific OneL3 Senior

    How can an instance override for *.agt*.drv beat a later override for env.agt1.drv?

    Reveal the Model Answer

    Instance overrides are searched in the order they were registered, and the first match wins. If the wildcard comes first, it also matches agt1, and the specific override is never reached. Register specific instance overrides before general ones, often in a base test that derived tests call first.

    Self-Check

    Tick each key point you covered in your answer.

    Misconception

    "The most specific path always wins, like in CSS."

    The factory does not rank paths by how specific they are. It takes the first registered match.

    Source uvm-core 2020.3.1 (IEEE 1800.2 library) source, base/uvm_factory.svh, set_inst_override_by_name: "the first override match prevails"

  5. CompareOverrides by Type vs by NameL2 Mid-Level

    Asked if they mention command-line overrides

    Compare overriding by type with overriding by name, including from the command line.

    Reveal the Model Answer

    By type uses the proxies, so a misspelt class name fails to compile. By name uses strings, so a typo only fails when the factory looks the name up. Command-line plusargs such as +uvm_set_type_override are by name. They are handy for a quick experiment, but they move test intent out of the code where reviewers see it.

    Self-Check

    Tick each key point you covered in your answer.

    Half-Truth

    "By name and by type are interchangeable."

    They behave the same when correct. Only by type catches a misspelt class at compile time.

    Source uvm-core 2020.3.1 (IEEE 1800.2 library) source, base/uvm_factory.svh, set_type_override_by_name ("may be any arbitrary string")

  6. Scale ItProving Which Overrides Took EffectL2 Mid-LevelL3 Senior

    In a forty-agent environment, how do you prove which overrides took effect?

    Reveal the Model Answer

    Print the topology after build with uvm_top.print_topology(), which shows every component's class. Print the factory with uvm_factory::get().print() to list registered overrides. For one doubtful request, debug_create_by_type() explains which override would be chosen and why. A regression check can compare the topology against an expected list.

    Self-Check

    Tick each key point you covered in your answer.

    Delivery

    "Read the test code; the overrides are right there."

    Reading shows what was requested, not what matched. The twin on the root had a correct-looking path that matched nothing.

What People Get Wrong

Common wrong answers and why they fail. Run It shows the wrong belief failing on a real simulator.

Misconception

"Both instance-override calls take the same relative path."

The type_id form adds the parent's full name; the factory method does not. The twin's "env.agt2.drv" matched nothing, and nothing warned.

Run It

The interview's overrides, with a line per agent that reports its driver class.

RUNVerilator + UVM 2020.3.1 · simulator service
Edit the code, then run it
Expected among the UVM messages: agt0.drv is a err_driver agt1.drv is a slow_driver agt2.drv is a err_driver FAIL: the factory's instance path is a full path; env.agt2.drv matched nothing and nothing warned
See the Fix
`timescale 1ns/1ns
`include "uvm_macros.svh"
import uvm_pkg::*;
class bus_driver extends uvm_driver #(uvm_sequence_item);
  `uvm_component_utils(bus_driver)
  function new(string name, uvm_component parent); super.new(name, parent); endfunction
endclass
class err_driver extends bus_driver;
  `uvm_component_utils(err_driver)
  function new(string name, uvm_component parent); super.new(name, parent); endfunction
endclass
class slow_driver extends bus_driver;
  `uvm_component_utils(slow_driver)
  function new(string name, uvm_component parent); super.new(name, parent); endfunction
endclass
class bus_agent extends uvm_agent;
  `uvm_component_utils(bus_agent)
  bus_driver drv;
  function new(string name, uvm_component parent); super.new(name, parent); endfunction
  function void build_phase(uvm_phase phase); drv = bus_driver::type_id::create("drv", this); endfunction
endclass
class soc_env extends uvm_env;
  `uvm_component_utils(soc_env)
  bus_agent agt0, agt1, agt2;
  function new(string name, uvm_component parent); super.new(name, parent); endfunction
  function void build_phase(uvm_phase phase);
    agt0 = bus_agent::type_id::create("agt0", this);
    agt1 = bus_agent::type_id::create("agt1", this);
    agt2 = bus_agent::type_id::create("agt2", this);
  endfunction
endclass
class mix_test extends uvm_test;
  `uvm_component_utils(mix_test)
  soc_env env;
  function new(string name, uvm_component parent); super.new(name, parent); endfunction
  function void build_phase(uvm_phase phase);
    uvm_factory f = uvm_factory::get();
    // Relative to this test: matches uvm_test_top.env.agt1.drv.
    bus_driver::type_id::set_inst_override(slow_driver::get_type(), "env.agt1.drv", this);
    // The factory itself takes a full path.
    f.set_inst_override_by_type(bus_driver::get_type(), slow_driver::get_type(), "uvm_test_top.env.agt2.drv");
    // A type override, registered last.
    bus_driver::type_id::set_type_override(err_driver::get_type());
    env = soc_env::type_id::create("env", this);
  endfunction
  function void end_of_elaboration_phase(uvm_phase phase);
    $display("agt0.drv is a %s", env.agt0.drv.get_type_name());
    $display("agt1.drv is a %s", env.agt1.drv.get_type_name());
    $display("agt2.drv is a %s", env.agt2.drv.get_type_name());
    if (env.agt2.drv.get_type_name() != "slow_driver") $display("FAIL: the factory's instance path is a full path; env.agt2.drv matched nothing and nothing warned");
    else $display("PASS: the full path matched agt2.drv");
  endfunction
endclass
module tb;
  initial run_test("mix_test");
endmodule

Prints: agt2.drv is a slow_driver PASS: the full path matched agt2.drv

Misconception

"The override registered last wins."

The type override here was registered last and still lost on agt1. Instance overrides are checked first.

Source IEEE 1800.2-2020 §8.3.1.4.2 (uvm-core uvm_factory.svh: type override applies "provided no instance override applies")

Missed Corner

"A wrong override path gives a warning."

An unmatched instance override is never an error: it simply never matches a create request. Print the factory to check.

Source Measured: the twin on this question (UVM_WARNING : 0 for the override), uvm-core 2020.3.1 on Verilator 5.052

Learn It, Then Prove It