UVM Verbosity and Reporting: uvm_info Levels, Severities and Real Logs

In short: Every uvm_info message carries a verbosity level. It prints only if its level is less than or equal to the current setting, which is UVM_MEDIUM by default. So **UVM_LOW prints more often than UVM_HIGH**: low means “important, always show me”. Change the setting at run time with +UVM_VERBOSITY=UVM_HIGH, or for one component with +uvm_set_verbosity. Warnings, errors and fatals ignore verbosity and always print.

The number-one confusion with UVM messages fits in one line: a lower level means more important, not less.

Once that clicks, the rest is easy.

Everything below was run on Synopsys VCS X-2025.06-SP1 with UVM 1.2, and every log is real.

Think of it like a news app

Your news app has a detail slider: Headlines, Standard, Everything.

  • Every story is tagged with the lowest slider setting where it still shows up. A war breaking out is tagged “Headlines”. A local bake sale is tagged “Everything”.
  • Set the slider to Standard and you see every story tagged Headlines or Standard. Bake sales stay hidden.
  • Alerts (an earthquake warning) skip the slider completely. They always pop up.

In UVM:

  • The slider is the verbosity setting (+UVM_VERBOSITY, default UVM_MEDIUM).
  • The tag is the level you write in uvm_info(id, msg, UVM_LOW).
  • The alerts are uvm_warning, uvm_error and uvm_fatal.

The six levels

LevelValuePrints at the default (UVM_MEDIUM)?Use it for
UVM_NONE0Yes, alwaysTest start, final pass/fail
UVM_LOW100YesBig milestones: “reset done”, “100 packets sent”
UVM_MEDIUM200YesOne line per transaction
UVM_HIGH300NoField-by-field detail
UVM_FULL400NoEverything, for deep debug
UVM_DEBUG500NoReserved for debugging UVM itself; don’t use it in your code

The rule: prints if message level ≤ setting.

Grid of six message levels against four verbosity settings: a message prints when its level is less than or equal to the setting; UVM_LOW prints more often than UVM_HIGH
Figure 1. The verbosity slider: a message prints if its level is at or below the setting.

Example 1: one component, every level, three settings

// A component that prints one message at every verbosity level
class talker extends uvm_component;
  `uvm_component_utils(talker)
  function new(string name, uvm_component parent); super.new(name, parent); endfunction

  function string expensive_dump();
    $display("   (expensive_dump() was called)");
    return "big dump";
  endfunction

  task run_phase(uvm_phase phase);
    `uvm_info("LVL", "UVM_NONE   message", UVM_NONE)
    `uvm_info("LVL", "UVM_LOW    message", UVM_LOW)
    `uvm_info("LVL", "UVM_MEDIUM message", UVM_MEDIUM)
    `uvm_info("LVL", "UVM_HIGH   message", UVM_HIGH)
    `uvm_info("LVL", "UVM_FULL   message", UVM_FULL)
    `uvm_info("LVL", "UVM_DEBUG  message", UVM_DEBUG)
    `uvm_info("DUMP", expensive_dump(), UVM_FULL)
  endtask
endclass

The test (verb_test) builds two of these, drv and mon, and runs for 1 ns.

Run 1, default: ./simv +UVM_TESTNAME=verb_test

UVM_INFO @ 0: reporter [RNTST] Running test verb_test...
UVM_INFO testbench.sv(16) @ 0: uvm_test_top.drv [LVL] UVM_NONE   message
UVM_INFO testbench.sv(17) @ 0: uvm_test_top.drv [LVL] UVM_LOW    message
UVM_INFO testbench.sv(18) @ 0: uvm_test_top.drv [LVL] UVM_MEDIUM message
UVM_INFO testbench.sv(16) @ 0: uvm_test_top.mon [LVL] UVM_NONE   message
UVM_INFO testbench.sv(17) @ 0: uvm_test_top.mon [LVL] UVM_LOW    message
UVM_INFO testbench.sv(18) @ 0: uvm_test_top.mon [LVL] UVM_MEDIUM message
...
** Report counts by id
[LVL]     6

Run 2, quieter: +UVM_VERBOSITY=UVM_LOW

UVM_INFO @ 0: reporter [RNTST] Running test verb_test...
UVM_INFO testbench.sv(16) @ 0: uvm_test_top.drv [LVL] UVM_NONE   message
UVM_INFO testbench.sv(17) @ 0: uvm_test_top.drv [LVL] UVM_LOW    message
UVM_INFO testbench.sv(16) @ 0: uvm_test_top.mon [LVL] UVM_NONE   message
UVM_INFO testbench.sv(17) @ 0: uvm_test_top.mon [LVL] UVM_LOW    message
...
** Report counts by id
[LVL]     4

Run 3, louder: +UVM_VERBOSITY=UVM_FULL

UVM_INFO @ 0: reporter [RNTST] Running test verb_test...
UVM_INFO testbench.sv(16) @ 0: uvm_test_top.drv [LVL] UVM_NONE   message
UVM_INFO testbench.sv(17) @ 0: uvm_test_top.drv [LVL] UVM_LOW    message
UVM_INFO testbench.sv(18) @ 0: uvm_test_top.drv [LVL] UVM_MEDIUM message
UVM_INFO testbench.sv(19) @ 0: uvm_test_top.drv [LVL] UVM_HIGH   message
UVM_INFO testbench.sv(20) @ 0: uvm_test_top.drv [LVL] UVM_FULL   message
   (expensive_dump() was called)
UVM_INFO testbench.sv(22) @ 0: uvm_test_top.drv [DUMP] big dump
UVM_INFO testbench.sv(16) @ 0: uvm_test_top.mon [LVL] UVM_NONE   message
... (mon prints the same 5 lines and its own dump)
UVM_INFO .../uvm_objection.svh(1252) @ 1: reporter [TEST_DONE] All end-of-test objections have been dropped. Calling stop tasks
...
** Report counts by id
[DUMP]     2
[LVL]    10

(... marks lines I trimmed: start-up banners and UVM library paths.)

What the logs show:

  • **6, then 4, then 10 [LVL] lines.** The default printed NONE, LOW and MEDIUM for each component. UVM_LOW cut it to NONE and LOW. UVM_FULL added HIGH and FULL. UVM_DEBUG never printed, not even at FULL.
  • **(expensive_dump() was called) appears only in run 3.** In runs 1 and 2 the hidden DUMP message was never built, so the function never ran. That’s the macro checking the level first.
  • Run 3 printed one extra UVM line: “All end-of-test objections have been dropped”. UVM’s own messages sit on the same slider, which is why UVM_FULL logs get big fast.

Example 2: turn up one component, not the whole testbench

Run 4: +uvm_set_verbosity=uvm_test_top.drv,_ALL_,UVM_FULL,time,0

UVM_INFO testbench.sv(16) @ 0: uvm_test_top.drv [LVL] UVM_NONE   message
UVM_INFO testbench.sv(17) @ 0: uvm_test_top.drv [LVL] UVM_LOW    message
UVM_INFO testbench.sv(18) @ 0: uvm_test_top.drv [LVL] UVM_MEDIUM message
UVM_INFO testbench.sv(19) @ 0: uvm_test_top.drv [LVL] UVM_HIGH   message
UVM_INFO testbench.sv(20) @ 0: uvm_test_top.drv [LVL] UVM_FULL   message
   (expensive_dump() was called)
UVM_INFO testbench.sv(22) @ 0: uvm_test_top.drv [DUMP] big dump
UVM_INFO testbench.sv(16) @ 0: uvm_test_top.mon [LVL] UVM_NONE   message
UVM_INFO testbench.sv(17) @ 0: uvm_test_top.mon [LVL] UVM_LOW    message
UVM_INFO testbench.sv(18) @ 0: uvm_test_top.mon [LVL] UVM_MEDIUM message
...
** Report counts by id
[DUMP]     1
[LVL]     8
  • drv printed all five levels up to FULL plus its dump. mon stopped at MEDIUM, and its dump function never ran.
  • The four fields: which component (path, wildcards allowed), which message ID (_ALL_ for every ID), what level, and when (time,0 = from time 0, or a phase name like run).
  • On a big testbench this is the difference between a 50 MB log and one you can read.
Matrix of which messages printed for drv and mon in runs 1 to 4: default, UVM_LOW, UVM_FULL and per-component FULL on drv
Figure 2. What printed in runs 1 to 4 (VCS X-2025.06-SP1, UVM 1.2).

The four severities

MacroVerbosity filter?What happensNews-app picture
uvm_infoYesPrints if level ≤ settingA story, shown by the slider
uvm_warningNo, always printsPrints and is countedA weather alert
uvm_errorNo, always printsPrints, counted, test fails; sim stops at the quit countA breaking-news alert
uvm_fatalNo, always printsPrints and ends the simulation at onceThe app shuts down

Every message takes the same trip, and it helps to picture it as a newsroom: a reporter files the story, the slider decides if it’s shown, an editor can relabel it or spike it, then it goes out and gets counted in the end-of-day digest.

Flow of a UVM message: macro, verbosity check (dropped if hidden), report catcher (can relabel or drop), action (print, count, quit, exit), report summary
Figure 3. The journey of one message, pictured as a newsroom.

Example 3: severities and the quit count

class sev_test extends uvm_test;
  `uvm_component_utils(sev_test)
  function new(string name, uvm_component parent); super.new(name, parent); endfunction
  task run_phase(uvm_phase phase);
    phase.raise_objection(this);
    `uvm_info   ("SCB", "packet 1 matched", UVM_LOW)
    `uvm_warning("SCB", "packet 2 arrived late")
    #10 `uvm_error("SCB", "packet 3 mismatch: exp 0x12, got 0x13")
    #10 `uvm_error("SCB", "packet 4 mismatch: exp 0x20, got 0x00")
    #10 `uvm_error("SCB", "packet 5 mismatch: exp 0x7f, got 0x7e")
    #10 `uvm_fatal("CFG", "no config found, cannot continue")
    `uvm_info("SCB", "this line never prints", UVM_NONE)
    phase.drop_objection(this);
  endtask
endclass

Run 5, as is: ./simv +UVM_TESTNAME=sev_test

UVM_INFO testbench.sv(46) @ 0: uvm_test_top [SCB] packet 1 matched
UVM_WARNING testbench.sv(47) @ 0: uvm_test_top [SCB] packet 2 arrived late
UVM_ERROR testbench.sv(48) @ 10: uvm_test_top [SCB] packet 3 mismatch: exp 0x12, got 0x13
UVM_ERROR testbench.sv(49) @ 20: uvm_test_top [SCB] packet 4 mismatch: exp 0x20, got 0x00
UVM_ERROR testbench.sv(50) @ 30: uvm_test_top [SCB] packet 5 mismatch: exp 0x7f, got 0x7e
UVM_FATAL testbench.sv(51) @ 40: uvm_test_top [CFG] no config found, cannot continue
--- UVM Report Summary ---
** Report counts by severity
UVM_INFO :    3
UVM_WARNING :    1
UVM_ERROR :    3
UVM_FATAL :    1

Run 6, stop at the 2nd error: +UVM_MAX_QUIT_COUNT=2,NO

UVM_INFO @ 0: reporter [MAXQUITSET] '+UVM_MAX_QUIT_COUNT=2,NO' provided on the command line is being applied.
UVM_INFO testbench.sv(46) @ 0: uvm_test_top [SCB] packet 1 matched
UVM_WARNING testbench.sv(47) @ 0: uvm_test_top [SCB] packet 2 arrived late
UVM_ERROR testbench.sv(48) @ 10: uvm_test_top [SCB] packet 3 mismatch: exp 0x12, got 0x13
UVM_ERROR testbench.sv(49) @ 20: uvm_test_top [SCB] packet 4 mismatch: exp 0x20, got 0x00
--- UVM Report Summary ---
Quit count reached!
Quit count :     2 of     2
** Report counts by severity
UVM_INFO :    4
UVM_WARNING :    1
UVM_ERROR :    2
UVM_FATAL :    0

Run 7, demote SCB errors from the command line: +uvm_set_severity=uvm_test_top,SCB,UVM_ERROR,UVM_WARNING

UVM_INFO testbench.sv(46) @ 0: uvm_test_top [SCB] packet 1 matched
UVM_WARNING testbench.sv(47) @ 0: uvm_test_top [SCB] packet 2 arrived late
UVM_WARNING testbench.sv(48) @ 10: uvm_test_top [SCB] packet 3 mismatch: exp 0x12, got 0x13
UVM_WARNING testbench.sv(49) @ 20: uvm_test_top [SCB] packet 4 mismatch: exp 0x20, got 0x00
UVM_WARNING testbench.sv(50) @ 30: uvm_test_top [SCB] packet 5 mismatch: exp 0x7f, got 0x7e
UVM_FATAL testbench.sv(51) @ 40: uvm_test_top [CFG] no config found, cannot continue
--- UVM Report Summary ---
** Report counts by severity
UVM_INFO :    3
UVM_WARNING :    4
UVM_ERROR :    0
UVM_FATAL :    1
  • Run 5: three errors at 10, 20 and 30 ns, then the fatal ends the run at 40 ns. “this line never prints” never printed.
  • Run 6: VCS confirms the switch ([MAXQUITSET]), stops right after the 2nd error at 20 ns, and the summary says “Quit count reached! 2 of 2”. Packet 5 and the fatal never happen. Useful in regressions: no point burning CPU after the test has already failed.
  • Run 7: the same three mismatches print as UVM_WARNING, with no code change. Errors: 0. The fatal still ends the run, because only SCB errors were demoted.
  • Read the report summary at the bottom of each run. It counts messages by severity and by ID, and it’s the fastest way to see how a run went.
Timeline of runs 5 to 7: as is ends with a fatal at 40 ns, the quit count stops at the 2nd error at 20 ns, and set_severity turns the 3 errors into warnings
Figure 4. Same test, three command lines (runs 5, 6 and 7).

Example 4: reshape messages in code

// A report catcher: turn one known error into a warning
class known_issue_catcher extends uvm_report_catcher;
  `uvm_object_utils(known_issue_catcher)
  function new(string name = "known_issue_catcher"); super.new(name); endfunction
  function action_e catch();
    if (get_severity() == UVM_ERROR && get_id() == "SCB" &&
        uvm_is_match("*0x13*", get_message())) begin
      set_severity(UVM_WARNING);
      set_message({"[known issue JIRA-123] ", get_message()});
    end
    return THROW;
  endfunction
endclass

class override_test extends uvm_test;
  `uvm_component_utils(override_test)
  function new(string name, uvm_component parent); super.new(name, parent); endfunction
  function void start_of_simulation_phase(uvm_phase phase);
    known_issue_catcher c = new();
    uvm_report_cb::add(null, c);                                     // catch for everyone
    set_report_severity_id_override(UVM_WARNING, "LATE", UVM_INFO);  // LATE warnings become info
  endfunction
  task run_phase(uvm_phase phase);
    phase.raise_objection(this);
    `uvm_warning("LATE", "packet 2 arrived late")
    `uvm_error  ("SCB",  "packet 3 mismatch: exp 0x12, got 0x13")
    `uvm_error  ("SCB",  "packet 4 mismatch: exp 0x20, got 0x00")
    phase.drop_objection(this);
  endtask
endclass

Run 8: ./simv +UVM_TESTNAME=override_test

UVM_INFO testbench.sv(82) @ 0: uvm_test_top [LATE] packet 2 arrived late
UVM_WARNING testbench.sv(83) @ 0: uvm_test_top [SCB] [known issue JIRA-123] packet 3 mismatch: exp 0x12, got 0x13
UVM_ERROR testbench.sv(84) @ 0: uvm_test_top [SCB] packet 4 mismatch: exp 0x20, got 0x00
--- UVM Report catcher Summary ---
Number of demoted UVM_ERROR reports  :    1
(all other demoted and caught counts: 0)
--- UVM Report Summary ---
** Report counts by severity
UVM_INFO :    5
UVM_WARNING :    1
UVM_ERROR :    1
UVM_FATAL :    0
  • The LATE warning came out as UVM_INFO: set_report_severity_id_override changes one ID’s severity.
  • Only the error with 0x13 became a warning, tagged with the ticket number. The 0x00 error stayed an error.
  • UVM even adds a catcher summary: “Number of demoted UVM_ERROR reports: 1”. Handy proof in a review that a known issue was demoted on purpose.
  • The catcher returns THROW (“pass it on”). Returning CAUGHT would swallow the message completely.
  • Picture it: an editor who reads every alert before it goes out, and quietly relabels the one everybody already knows about.
Run 8: LATE warning becomes info by ID override, the 0x13 error becomes a warning via the report catcher, the 0x00 error stays an error
Figure 5. Run 8: what went in, what came out.

Common mistakes (and the fix for each)

These come from real Verification Academy threads, retold in my own words with links.

1. A UVM_LOW message that never prints

  • What happened: an engineer’s uvm_info(..., UVM_LOW) never showed up, while $display in the same spot did (Verification Academy).
  • Why: the run had +UVM_VERBOSITY=UVM_NONE. UVM_LOW (100) is above UVM_NONE (0), so it’s hidden. Slider on “Headlines only”.
  • Fix: drop the switch (default is UVM_MEDIUM), or tag the message UVM_NONE if it must always print.

2. Thinking verbosity changes what the testbench does

  • What happened: in 2020 someone asked whether switching to +UVM_VERBOSITY=UVM_MEDIUM changes how a sequence runs (Verification Academy, 2020).
  • Why: verbosity only filters printing. One catch, shown in example 1: the message string isn’t built when the message is hidden, so a function call inside it (like expensive_dump()) doesn’t run either.
  • Fix: never put side effects (counters, randomize calls) inside a message argument.

3. +UVM_VERBOSITY ignored by a config object

  • What happened: in 2021 a config class extended uvm_report_object, and its UVM_MEDIUM messages still printed with +UVM_VERBOSITY=UVM_NONE (Verification Academy, 2021).
  • Why: the command-line setting reaches components and plain objects, not a hand-made uvm_report_object.
  • Fix: extend uvm_object instead (Dave Rich’s answer), or set its level in code with set_report_verbosity_level.

4. Demoting errors one ID at a time

  • What happened: in 2022 an engineer wanted every error under one agent turned into a warning, not just one ID (Verification Academy, 2022).
  • Fix: +uvm_set_severity=uvm_test_top.env0.*,_ALL_,UVM_ERROR,UVM_WARNING on the command line, like run 7 but with a wildcard path.

5. Hiding a message by raising its verbosity in a catcher

  • What happened: someone’s report catcher bumped UVM_NONE messages to UVM_HIGH to hide them. They still printed (Verification Academy).
  • Why: the catcher runs after the verbosity check. By then the slider has already said yes.
  • Fix: return CAUGHT from catch() to drop the message.

6. Several +uvm_set_verbosity switches, and UVM_DEBUG

  • What happened: in 2024 an engineer passed several +uvm_set_verbosity switches and set two components to UVM_DEBUG (Verification Academy, 2024).
  • Why: Dave Rich noted that multiple +uvm_set_verbosity switches are broken in UVM 1.2 and earlier, and that UVM_DEBUG is meant for debugging the UVM library itself.
  • Fix: use one switch with a wildcard path where you can, and stop at UVM_FULL.

Every idea on this page, in one picture

IdeaPicture it as
Verbosity settingThe news app’s detail slider
Message levelThe lowest slider setting where the story still shows
UVM_LOW vs UVM_HIGHHeadline vs small local story
Warning, error, fatalAlerts that skip the slider
+uvm_set_verbosityA separate slider for one channel
Hidden message costs nothingThe app doesn’t download stories you won’t see
Quit count“After 2 breaking-news alerts, stop the show”
Report catcherAn editor who relabels or drops alerts before they go out
Report summaryThe end-of-day digest

FAQ

What is the default UVM verbosity?

UVM_MEDIUM. Messages tagged UVM_NONE, UVM_LOW and UVM_MEDIUM print; UVM_HIGH and above don’t.

Does UVM_HIGH print more or fewer messages than UVM_LOW?

As a setting, UVM_HIGH prints more. As a message tag, UVM_HIGH prints less often. That’s the whole confusion in one question.

How do I change verbosity from the command line?

+UVM_VERBOSITY=UVM_HIGH for everything, +uvm_set_verbosity=<path>,<id>,<level>,<phase or time> for one component.

Does verbosity affect uvm_error?

No. Warnings, errors and fatals always print. Change them with severity overrides or a report catcher.

How do I stop the simulation after N errors?

+UVM_MAX_QUIT_COUNT=N,NO, like run 6.

References

  • IEEE 1800.2-2020, UVM standard: the report object, report server and report catcher clauses, and the command-line processor (+UVM_VERBOSITY, +uvm_set_verbosity, +uvm_set_severity, +UVM_MAX_QUIT_COUNT).
  • Verification Academy forum threads linked in the mistakes section (accessed 11 Nov 2026).
  • All 8 runs on Synopsys VCS X-2025.06-SP1 with UVM 1.2, 11 Nov 2026.

What to read next