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
  • Factory & Configuration15
  • Transaction-Level Modeling (TLM)13
  • UVM Sequences & Stimulus21
  • UVM Agents & Protocol VIP21
  • Environment & Test Classes11
    • Environment Architecture
    • Tests: Base Classes, Selection and Startup
      • Base Test Pattern: One Contract for Every Scenario
      • Scenario Inheritance: Specialize Intent, Not Infrastructure
      • Factory Overrides in Tests: Explicit, Local, Reviewable
      • Shared run_phase: One End-of-Test Policy for Every Test
      • +UVM_TESTNAME and Plusargs: Runtime Test Selection
      • Top Module and run_test Startup
      • Designing a Test Library
  • 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

‹Tests: Base Classes, Selection and Startup
  1. Topics
  2. UVM Verification
  3. Environment & Test Classes
  4. Tests: Base Classes, Selection and Startup
  5. +UVM_TESTNAME and Plusargs: Runtime Test Selection

Part 7 · Environment & Tests · Intermediate

+UVM_TESTNAME and Plusargs: Runtime Test Selection

One compiled bench, every test: how +UVM_TESTNAME picks the class, what INVTST and repeated plusargs do, typed knobs with $value$plusargs or uvm_cmdline_processor parsed once in build, and the bundle that makes a failure replayable.

On this page

    The nightly regression reports 100% passing. In the morning someone notices that dma_smoke_tst is on the list, a typo that has been there for a week, and that it passed every night. The test it names does not exist. How can a test that does not exist pass, and what should the regression script have checked?

    Answering that needs the whole path from the command line to the test object. This lesson follows it, then adds typed knobs, and ends with what a failure report must contain so anyone can replay it.

    The idea: the test is chosen by name, at run time

    Compiling the bench takes minutes; running one test takes seconds. So a regression compiles once and runs the same binary many times, each time with a different test. That works because run_test creates the test by name: it asks the factory for a component whose registered type name matches a string, and gives it the instance name uvm_test_top. The string comes from the +UVM_TESTNAME= plusarg if there is one, and otherwise from the argument to run_test. The plusarg wins; run_test and timeouts is the home of that rule.

    A theatre with a repertory company works this way. The stage, the lights and the actors are the same every night (the compiled binary). The poster outside (the plusarg) says which play is on. If the poster names a play the company does not know, the show is cancelled at the door, which is exactly what happens to a misspelled test.

    The picture

    Flowchart: if +UVM_TESTNAME is given it is used, otherwise the run_test argument; if the factory knows the name, uvm_test_top is created and RNTST is printed, otherwise a BDTYP warning and an INVTST fatal end the run at time 0.
    How run_test picks the test. The name is looked up in the factory, so only classes with a registration macro can be selected.

    Build it

    Selecting the test

    The bench's top calls run_test("dma_smoke_test"), so running the binary with no plusarg runs the smoke test. Everything else is a plusarg:

    Diagram
    ./simv +UVM_TESTNAME=dma_rand_test
    ./simv +UVM_TESTNAME=dma_vseq_test +UVM_VERBOSITY=UVM_MEDIUM
    ./simv +UVM_TESTNAME=dma_backpressure_test +UVM_VERBOSITY=UVM_MEDIUM
    • The name must be the registered name, which uvm_component_utils(T) sets to the class name T. A class without the macro cannot be selected.

    • Given twice, the first +UVM_TESTNAME is used. A library built with its DPI support also prints a MULTTST warning listing them all; the course's Verilator runs are built without DPI, so they use the first one silently.

    • If an override for the test's own type is registered before run_test creates it, the RNTST line says via factory override for test "...". That is rare, but it explains a confusing log.

    Typed knobs, parsed once

    Test selection is one string. Scenario knobs, such as how many jobs dma_rand_test runs, need typed values. SystemVerilog's own $value$plusargs covers most cases; UVM's uvm_cmdline_processor adds lookups that return every match, which helps when a knob may be given several times. Either way, parse in one place, the base test's build_phase, before anything is built from the value, and log the effective values so the log alone can reproduce the run.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // snippet
    // In the base test (or a derived test's build_phase), before the env is created.
    function void read_knobs();
      uvm_cmdline_processor clp = uvm_cmdline_processor::get_inst();
      string val;
      void'($value$plusargs("DMA_JOBS=%d", n_jobs));          // plain SystemVerilog
      if (clp.get_arg_value("+DMA_MAX_LEN=", val))            // UVM's processor
        max_len = val.atoi();
      `uvm_info("KNOBS", $sformatf("n_jobs=%0d max_len=%0d", n_jobs, max_len), UVM_LOW)
    endfunction

    Two details save debugging time. $test$plusargs and $value$plusargs match by prefix: $test$plusargs("DMA_FAST") is also true for +DMA_FAST_RESET. Keep the = in value formats, and pick flag names that are not prefixes of each other. And knobs that change what gets built (agent modes, which scoreboard) must be read in build_phase; reading them in run_phase is too late, because the components were built from the old value.

    Built-in plusargs worth knowing

    Plusarg

    Does

    Note

    +UVM_TESTNAME=<name>

    Selects the test

    Beats the run_test argument.

    +UVM_VERBOSITY=UVM_MEDIUM

    Sets the default verbosity

    The bench's IRQ and BP lines need MEDIUM.

    +UVM_TIMEOUT=<time>,<YES|NO>

    Global timeout

    Time in the UVM package's unit; NO locks it against set_timeout.

    +UVM_MAX_QUIT_COUNT=<n>,<YES|NO>

    Stop after n counted errors

    Keeps a failed test from writing a huge log.

    +uvm_set_type_override=<a>,<b>

    Factory override for one run

    Forms in Command-line overrides.

    +uvm_set_config_int=<path>,<field>,<value>

    A config value

    Stored as uvm_bitstream_t, so config_db#(int)::get does not see it.

    +UVM_CONFIG_DB_TRACE, +UVM_OBJECTION_TRACE, +UVM_PHASE_TRACE

    Debug traces

    Turn on for one failing run, never for a regression.

    The random seed is not a UVM plusarg: each simulator has its own switch (+ntb_random_seed= on VCS, -sv_seed on Questa, -svseed on Xcelium). Regression tools wrap it.

    The replay bundle

    A failure report is only useful if someone else can rerun it exactly. It must carry the test name, the seed, every plusarg, the build identity (commit or tag, and the UVM library version) and the simulator version. Logging the knobs in build_phase, as above, means the log itself carries most of the bundle.

    Watch it run: the test that does not exist

    Here is the real log of the bench run with the typo from the opening, trimmed:

    Diagram
    UVM_WARNING @ 0: reporter [BDTYP] Cannot create a component of type 'dma_smoke_tst' because it is not registered with the factory.
    UVM_FATAL @ 0: reporter [INVTST] Requested test from command line +UVM_TESTNAME=dma_smoke_tst not found.
    --- UVM Report Summary ---
    ** Report counts by severity
    UVM_INFO :    2
    UVM_WARNING :    2
    UVM_ERROR :    0
    UVM_FATAL :    1
    • BDTYP comes from the factory: no class is registered under that name.

    • INVTST ends the run at time 0 and says where the bad name came from: the command line or the run_test argument.

    • `UVM_ERROR : 0`. That line is the whole story of the opening.

    What breaks: the regression that only counted errors

    The team's pass criterion was a single grep: the log contains UVM_ERROR : 0. The typo'd test died at time 0 with a fatal, and the summary still printed zero errors, so the script marked it as passing, every night. Nobody saw it because a test that runs for zero seconds does not stand out in a regression of thousands.

    The fix had three parts. Pass requires both UVM_ERROR : 0 and UVM_FATAL : 0. Pass also requires the line Running test <expected name>, which proves the intended test ran. And pass requires a positive sign of work, the scoreboard's words matched line with a non-zero count, because a test that compared nothing proves nothing. The third check also catches the test that ends at time 0 because it never raised an objection.

    Interview

    "How does +UVM_TESTNAME work, and what if run_test also has an argument?"

    A weak answer: "It selects the test. If run_test has a name, that one is used." The second sentence is backwards.

    A strong answer: "run_test looks for +UVM_TESTNAME; if present it replaces the argument, so the argument is only a default. It asks the factory to create that type name as uvm_test_top, so only registered classes can run; an unknown name is a BDTYP warning and an INVTST fatal at time 0. That's why one compile serves a whole regression. Knobs come in as plusargs too, parsed once in the base test's build_phase and logged, and the regression judges pass on zero errors and zero fatals plus proof that the intended test ran and checked something."

    Follow-ups: Why does a test class need its registration macro to be selectable? (selection is a factory lookup by string). What does +uvm_set_config_int store, and who can read it? (a uvm_bitstream_t: config_db of that type and field-macro auto-config, not config_db#(int)).

    Check yourself The top calls run_test("dma_smoke_test") and you run with +UVM_TESTNAME=dma_rand_test +UVM_TESTNAME=dma_vseq_test. Which test runs?

    dma_rand_test. The plusarg beats the argument, and when it is given more than once the first is used (a DPI-enabled library also warns with MULTTST). The RNTST line confirms it: Running test dma_rand_test....

    Check yourself A test reads +DMA_OUT_ACTIVE=1 in run_phase to make the output agent active. Why does nothing change?

    The agent decided whether to build a driver in its build_phase, long before run_phase. A knob that changes topology must be read before the component is built, in the test's build_phase, and passed down through config_db or a config object before the env is created.

    Next: the test is chosen; the stage it runs on is built by 40 lines nobody reviews. Top Module and run_test Startup reads them.

    Related topics

    • run_test and timeouts

    • Command-line overrides

    • Custom plusargs

    • Top Module and run_test Startup

    Previous

    123 / 280

    Next: Top Module and run_test Startup

    Up next

    Up nextTop Module and run_test Startup

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Base Test Pattern: One Contract for Every Scenario
    • Scenario Inheritance: Specialize Intent, Not Infrastructure
    • Factory Overrides in Tests: Explicit, Local, Reviewable