Every UVM component inherits from uvm_report_object (see UVM Introduction), so it already has functions and macros for printing messages with a severity, an ID and a verbosity level. This article covers the four UVM reporting functions, the reporting macros that wrap them, and how verbosity decides what gets printed.
7 min read | Intermediate Level
What You'll Learn
- Use
uvm_report_info,uvm_report_warning,uvm_report_erroranduvm_report_fatal - Why the
`uvm_infofamily of macros is preferred over the functions - How a message's verbosity is compared with the component's threshold
- Choose good message IDs and avoid common macro pitfalls
Syntax
// Functions
uvm_report_info (ID, MESSAGE, VERBOSITY = UVM_MEDIUM, FILENAME = "", LINE = 0);
uvm_report_warning (ID, MESSAGE, VERBOSITY = UVM_NONE, FILENAME = "", LINE = 0);
uvm_report_error (ID, MESSAGE, VERBOSITY = UVM_NONE, FILENAME = "", LINE = 0);
uvm_report_fatal (ID, MESSAGE, VERBOSITY = UVM_NONE, FILENAME = "", LINE = 0);
// Macros (preferred) - no trailing semicolon needed
`uvm_info (ID, MESSAGE, VERBOSITY)
`uvm_warning (ID, MESSAGE)
`uvm_error (ID, MESSAGE)
`uvm_fatal (ID, MESSAGE)
ID- a short string that names the message type, used for filtering and in the end-of-test summary (required)MESSAGE- the text to print, usually built with$sformatf(required)VERBOSITY- the detail level of the message. It is optional for the functions and required for`uvm_infoFILENAME/LINE- source location to print. The macros fill these in automatically (optional)
Calling Functions
There are four basic reporting functions, one per severity. They all take an ID, a message and an optional verbosity level.
uvm_report_* ("TAG", $sformatf ("[Enter the display message]"), VERBOSITY_LEVEL);
Here * can be info, warning, error or fatal. UVM defines six verbosity levels, each represented by an integer.
typedef enum {
UVM_NONE = 0,
UVM_LOW = 100,
UVM_MEDIUM = 200,
UVM_HIGH = 300,
UVM_FULL = 400,
UVM_DEBUG = 500
} uvm_verbosity;
Verbosity really matters only for uvm_report_info, which defaults to UVM_MEDIUM if you leave it out. Warnings, errors and fatals default to UVM_NONE, so they are always printed. A call to uvm_report_fatal ends the simulation after printing the report summary.
uvm_report_info (get_type_name (), $sformatf ("None level message"), UVM_NONE);
uvm_report_info (get_type_name (), $sformatf ("Low level message"), UVM_LOW);
uvm_report_info (get_type_name (), $sformatf ("Medium level message"), UVM_MEDIUM);
uvm_report_info (get_type_name (), $sformatf ("High level message"), UVM_HIGH);
uvm_report_info (get_type_name (), $sformatf ("Full level message"), UVM_FULL);
uvm_report_info (get_type_name (), $sformatf ("Debug level message"), UVM_DEBUG);
uvm_report_warning (get_type_name (), $sformatf ("Warning level message"));
uvm_report_error (get_type_name (), $sformatf ("Error level message"));
uvm_report_fatal (get_type_name (), $sformatf ("Fatal level message"));
The functions do not know where they were called from. To print the file name and line number, pass the compiler directives `__FILE__ and `__LINE__ as the last two arguments. This helps a lot during debug.
uvm_report_info (get_type_name (), $sformatf ("None level message - Display File/Line"), UVM_NONE, `__FILE__, `__LINE__);
File and line printing can be turned off for the reporting macros by defining UVM_REPORT_DISABLE_FILE_LINE at compile time, for example with +define+UVM_REPORT_DISABLE_FILE_LINE. This is a compile-time define, not a run-time plusarg.
Calling Macros
The UVM reporting macros print the file and line automatically, so there is no need to pass `__FILE__ and `__LINE__.
`uvm_info (get_type_name (), $sformatf ("[Driver] None level message"), UVM_NONE)
`uvm_info (get_type_name (), $sformatf ("[Driver] Low level message"), UVM_LOW)
`uvm_info (get_type_name (), $sformatf ("[Driver] Medium level message"), UVM_MEDIUM)
`uvm_info (get_type_name (), $sformatf ("[Driver] High level message"), UVM_HIGH)
`uvm_info (get_type_name (), $sformatf ("[Driver] Full level message"), UVM_FULL)
`uvm_info (get_type_name (), $sformatf ("[Driver] Debug level message"), UVM_DEBUG)
`uvm_warning (get_type_name (), $sformatf ("[Driver] Warning level message"))
`uvm_error (get_type_name (), $sformatf ("[Driver] Error level message"))
`uvm_fatal (get_type_name (), $sformatf ("[Driver] Fatal level message"))
The macros have a second, less obvious advantage: they check verbosity before building the message. In simplified form, `uvm_info expands to:
begin
if (uvm_report_enabled (VERBOSITY, UVM_INFO, ID)) // Cheap check first
uvm_report_info (ID, MESSAGE, VERBOSITY, `uvm_file, `uvm_line);
end
With a function call, the $sformatf string is built every time, even if the message is then filtered out. With the macro, a filtered message costs only the verbosity check. In a driver or monitor that runs millions of transactions, this saves real simulation time.
Prefer the macros in all new code. Use the functions only when you need an argument the macros do not offer, such as passing a different file and line.
Reading a Message Line
Each printed message follows the same format, which makes logs easy to search. For example:
UVM_INFO testbench.sv(41) @ 10: uvm_test_top.m_env.m_drv [DRV] Drive packet with addr=0x0
| Part | Example | Meaning |
|---|---|---|
| Severity | UVM_INFO | Info, warning, error or fatal |
| File and line | testbench.sv(41) | Where the message was issued |
| Time | @ 10 | Simulation time |
| Hierarchy path | uvm_test_top.m_env.m_drv | The component that reported it |
| ID | [DRV] | The ID passed as the first argument |
| Message | Drive packet with addr=0x0 | The text you provided |
Where Does the Message Format Help?
Regression scripts rely on this fixed format. They search for lines starting with UVM_ERROR or UVM_FATAL to decide pass or fail, and group failures by ID to spot the same bug across hundreds of seeds.
Verbosity Levels
Verbosity controls whether a uvm_report_* call or `uvm_* macro is printed. Each component has a verbosity threshold, and a message is printed only if its verbosity is less than or equal to that threshold. The default threshold is UVM_MEDIUM.
For the six uvm_report_info calls above, the threshold decides which lines appear:
| Threshold | Info messages printed |
|---|---|
UVM_LOW | None, Low |
UVM_MEDIUM (default) | None, Low, Medium |
UVM_HIGH | None, Low, Medium, High |
UVM_DEBUG | All six |
The warning, error and fatal messages are printed at every threshold.
Change the threshold for the whole testbench without recompiling, using the plusarg +UVM_VERBOSITY=UVM_HIGH. To change it for one part of the hierarchy, see Reporting Classes.
Quick Check
Q: A component calls uvm_report_info("MON", msg) without a verbosity argument. Is the message printed when the simulation runs with +UVM_VERBOSITY=UVM_LOW?
Show Answer
No. The verbosity defaults to UVM_MEDIUM (200), which is above the UVM_LOW threshold (100).
Reporting from Sequences and Modules
The same macros work outside components:
- Sequences and sequence items: messages are routed through the sequencer the sequence runs on, so they follow that sequencer's verbosity and actions.
- Modules and interfaces: with
uvm_pkgimported and the macros included, the macros call global versions of the reporting functions. These report through the top of the UVM hierarchy.
Where are Verbosity Levels Used?
A typical convention is UVM_LOW for test milestones, UVM_MEDIUM for one line per transaction, and UVM_HIGH or above for field-by-field dumps. Regressions run at UVM_LOW to keep logs small, and engineers raise the level only when rerunning a failing seed.
Common Mistakes
Mistake #1: Using a macro with a semicolon in an if-else without begin-end
Wrong:
if (ok) `uvm_info ("CHK", "pass", UVM_LOW); else `uvm_error ("CHK", "fail")
Right: drop the semicolon after the macro, or wrap each branch in begin ... end
Why? `uvm_info expands to a begin ... end block. With the semicolon, the compiler sees end; else, and the else no longer belongs to the if, which causes a syntax error.
Mistake #2: Putting changing values in the ID
Wrong: `uvm_info ($sformatf ("ADDR_%0h", addr), "write done", UVM_HIGH)
Right: `uvm_info ("WR_DONE", $sformatf ("write done addr=0x%0h", addr), UVM_HIGH)
Why? The ID is meant to identify a message type. If it changes with every transaction, ID-based filtering and actions cannot target it, and the end-of-test summary lists hundreds of one-off IDs.
Mistake #3: Building expensive strings with the function form in hot code
Calling uvm_report_info(..., $sformatf(...), UVM_HIGH) inside a monitor loop builds the string on every transaction, even in regressions where UVM_HIGH messages are filtered out. Use `uvm_info, which skips the formatting when the message would not print.
Practice Exercise
Challenge: Clean Up a Monitor's Messages
The monitor code below works, but its messages are hard to filter and slow in regressions. Rewrite it using macros, a fixed ID, and verbosity UVM_HIGH for the per-transaction dump.
// Original monitor code
uvm_report_info ($sformatf ("PKT_%0d", count), $sformatf ("addr=0x%0h data=0x%0h", pkt.addr, pkt.data));
if (pkt.parity_err)
uvm_report_error ("MON", "parity error");
Hint
Move count from the ID into the message, pass the verbosity explicitly, and remember that macros need no semicolon.
Solution
// Fixed ID, count moved into the message, string built only when UVM_HIGH is enabled
`uvm_info ("MON_PKT", $sformatf ("pkt %0d: addr=0x%0h data=0x%0h", count, pkt.addr, pkt.data), UVM_HIGH)
if (pkt.parity_err)
`uvm_error ("MON_PARITY", $sformatf ("parity error on pkt %0d", count)) // Always printed and counted
Using a separate ID for the parity error lets a test that injects parity errors on purpose demote just that ID, while all other errors still fail the test.
Summary
In this tutorial, you learned:
- The four reporting functions are
uvm_report_info,uvm_report_warning,uvm_report_erroranduvm_report_fatal - Info messages default to
UVM_MEDIUMverbosity, while warnings, errors and fatals default toUVM_NONEand always print - The
`uvm_*macros add file and line automatically and skip building the message when it would be filtered - A message prints only if its verbosity is less than or equal to the component's threshold,
UVM_MEDIUMby default +UVM_VERBOSITYchanges the threshold at run time, whileUVM_REPORT_DISABLE_FILE_LINEis a compile-time define- Good IDs are short and fixed, and macros should not be followed by a semicolon in an if-else