UVM Reporting Facility
Master the UVM messaging system. Learn how to log information, warnings, errors, and filter messages based on verbosity.
SystemC provides standard std::cout and the native sc_report_handler for printing messages. However, when working in a large verification environment, you need much more control. You need to be able to filter messages by severity, origin, or verbosity, and you might want errors to automatically terminate the simulation.
The UVM Reporting Facility provides a consistent, configurable message-reporting mechanism as defined in the IEEE 1800.2 standard.
UVM Severities
Every message in UVM is assigned a severity. The severity indicates the nature of the message and dictates the default action the simulator will take:
UVM_INFO: Informative message. Does not affect simulation execution.UVM_WARNING: Indicates a potential problem. Simulation continues, but the warning counter is incremented.UVM_ERROR: Indicates a real problem. Simulation continues, but the error counter is incremented. If the error count reaches a maximum threshold (max_quit_count), the simulation aborts.UVM_FATAL: Indicates a critical problem from which the simulation cannot recover. The simulation is terminated immediately (UVM_EXIT).
UVM Verbosity
While Severities describe what the message is, Verbosity describes how important it is to print. Verbosity levels allow you to leave thousands of debug prints in your code but only print them when you explicitly ask for them.
The standard verbosity levels are:
UVM_NONE(always printed)UVM_LOWUVM_MEDIUM(default)UVM_HIGHUVM_FULL
When you issue a message, you assign it a verbosity. If that verbosity is less than or equal to the configured verbosity of the component (or the global uvm_top), the message is printed.
Complete Reporting Example
Below is a complete, compilable sc_main example that demonstrates reporting macros, modifying verbosity, changing default actions, setting quit counts, and using a report catcher to demote errors.
#include <systemc>
#include <uvm>
// 1. Define a Report Catcher to intercept and modify messages
class my_catcher : public uvm::uvm_report_catcher {
public:
action_e do_catch() override {
// If we see an expected error, demote it to an INFO message
if (get_severity() == uvm::UVM_ERROR && get_id() == "EXPECTED_ERR") {
set_severity(uvm::UVM_INFO);
set_message("Error was expected and demoted: " + get_message());
}
// Always return THROW to let the message proceed to the output
return THROW;
}
};
class my_test : public uvm::uvm_test {
public:
UVM_COMPONENT_UTILS(my_test);
my_test(uvm::uvm_component_name name) : uvm::uvm_test(name) {}
void build_phase(uvm::uvm_phase& phase) override {
uvm::uvm_test::build_phase(phase);
// Change verbosity for this component and its children
this->set_report_verbosity_level_hier(uvm::UVM_HIGH);
// Force the simulation to exit on ANY warning from this component
// (Commented out so we can see the rest of the simulation)
// this->set_report_severity_action(uvm::UVM_WARNING, uvm::UVM_DISPLAY | uvm::UVM_EXIT);
// Abort simulation after 5 UVM_ERRORs
uvm::uvm_coreservice_t* cs = uvm::uvm_coreservice_t::get();
uvm::uvm_report_server* svr = cs->get_report_server();
svr->set_max_quit_count(5);
}
void run_phase(uvm::uvm_phase& phase) override {
phase.raise_objection(this);
// Standard Info messages with varying verbosities
UVM_INFO("TEST_LOW", "This is a UVM_LOW message.", uvm::UVM_LOW);
UVM_INFO("TEST_HIGH", "This is a UVM_HIGH message. It prints because we changed the verbosity level.", uvm::UVM_HIGH);
// This will not print, because UVM_FULL > UVM_HIGH
UVM_INFO("TEST_FULL", "This is a UVM_FULL message and will be hidden.", uvm::UVM_FULL);
// Warning
UVM_WARNING("TEST_WARN", "Timeout value is suspiciously low.");
// Error that gets caught and demoted by our catcher
UVM_ERROR("EXPECTED_ERR", "This payload mismatch was expected in this test!");
// Real Error (increments error count)
UVM_ERROR("REAL_ERR", "An actual error occurred.");
phase.drop_objection(this);
}
};
int sc_main(int argc, char* argv[]) {
// Register the custom report catcher globally
my_catcher* catcher = new my_catcher();
uvm::uvm_report_cb::add(nullptr, catcher);
uvm::run_test("my_test");
return 0;
}Using UVM's reporting mechanism guarantees that your testbench logs are consistent, easily parsable by external scripts, and highly configurable at runtime without recompiling code.
Comments and Corrections