UVM Report Catcher - Filtering and Modifying Messages

During verification, you often encounter expected errors or warnings that shouldn't cause test failures. The uvm_report_catcher class provides a powerful mechanism to intercept, filter, and modify UVM messages before they're processed - enabling you to demote expected errors, promote warnings, or completely suppress known issues.

What is uvm_report_catcher?

uvm_report_catcher is a callback mechanism that intercepts messages from the UVM reporting system. When a component calls `uvm_error, `uvm_warning, or other report macros, registered catchers can:

  • Modify severity: Demote errors to warnings/info, or promote warnings to errors
  • Change message content: Alter the message text, ID, or verbosity
  • Drop messages: Completely suppress specific reports
  • Pass through: Let messages continue to other catchers or handlers

Report Catcher Flow

flowchart LR
    A[uvm_error] --> B[Report Server]
    B --> C{Catchers Registered?}
    C -->|Yes| D[Call catch]
    D --> E{Action?}
    E -->|THROW| F[Next Catcher or Handler]
    E -->|CAUGHT| G[Message Dropped]
    C -->|No| F
    F --> H[Display/Log]

Implementation Example

Let's build a report catcher that demotes specific error messages based on regex patterns.

Custom Report Catcher Class

class report_catcher extends uvm_report_catcher;

   // Queue of message patterns to demote from ERROR to INFO
   local string demoted_messages[$];

   function new(string name);
      super.new(name);
   endfunction

   // Called for every report message
   function action_e catch();

      if(get_severity() == UVM_ERROR) begin
         string my_message = get_message();

         // Check if message matches any demoted pattern
         foreach(demoted_messages[msg]) begin
            if(uvm_re_match(demoted_messages[msg], my_message) == 0) begin
               $display("Demoting message: [%s]", my_message);
               set_severity(UVM_INFO);
            end
         end
      end

      return THROW; // Pass to next catcher or handler
   endfunction

   // Register a message pattern for demotion (supports regex)
   function void demote_message(string d_message);
      demoted_messages.push_back(d_message);
   endfunction

endclass

Test Using the Report Catcher

class test extends uvm_test;
   `uvm_component_utils(test)

   env m_env;
   report_catcher m_report_catcher;

   function new(string name, uvm_component parent);
      super.new(name, parent);
   endfunction

   function void build_phase(uvm_phase phase);
      m_env = env::type_id::create("m_env", this);
   endfunction

   task run_phase(uvm_phase phase);
      phase.raise_objection(this);
      
      // Create and configure report catcher
      m_report_catcher = new("m_report_catcher");
      
      // Demote errors matching this regex pattern
      m_report_catcher.demote_message("error message 2) from e.*");

      // Register catcher for specific component
      uvm_report_cb::add(m_env, m_report_catcher);
      
      #100;

      // Remove catcher when no longer needed
      uvm_report_cb::delete(m_env, m_report_catcher);
      
      #100;
      phase.drop_objection(this);
   endtask

endclass

Environment Generating Errors

class env extends uvm_env;
   `uvm_component_utils(env)

   function new(string name, uvm_component parent);
      super.new(name, parent);
   endfunction

   task run_phase(uvm_phase phase);
      #1;
      `uvm_error("MYENV", "error message 1) from env..")  // Not caught

      #50;
      `uvm_error("MYENV", "error message 2) from env..")  // Demoted to INFO

      #50;
      `uvm_error("MYENV", "error message 3) from env..")  // After catcher removed
   endtask

endclass

Return Actions

The catch() function returns an action_e value that controls message flow:

ActionBehaviorUse Case
THROWPass message to next handlerAfter modifying severity or content
CAUGHTSuppress message completelyExpected errors you don't want logged

Accessor Methods

Inside catch(), use these methods to inspect and modify the current message:

Getters

MethodReturns
get_severity()UVM_INFO, UVM_WARNING, UVM_ERROR, UVM_FATAL
get_id()Message ID string (e.g., "MYENV")
get_message()Message text
get_verbosity()Verbosity level (UVM_NONE, UVM_LOW, etc.)
get_fname()Source filename
get_line()Source line number
get_client()Reporting component handle

Setters

MethodPurpose
set_severity()Change message severity
set_id()Change message ID
set_message()Change message text
set_verbosity()Change verbosity level

Common Use Cases

1. Demote Expected Errors

function action_e catch();
   // Demote known timing violation during reset
   if(get_id() == "TIMING" && get_message().match("during reset"))
      set_severity(UVM_INFO);
   return THROW;
endfunction

2. Promote Warnings to Errors

function action_e catch();
   // Treat protocol warnings as errors in strict mode
   if(strict_mode && get_severity() == UVM_WARNING)
      if(get_id() == "PROTOCOL")
         set_severity(UVM_ERROR);
   return THROW;
endfunction

3. Count and Limit Messages

class limit_catcher extends uvm_report_catcher;
   int msg_count[string];
   int max_per_id = 10;

   function action_e catch();
      string id = get_id();
      
      msg_count[id]++;
      
      if(msg_count[id] > max_per_id) begin
         if(msg_count[id] == max_per_id + 1)
            `uvm_info("LIMIT", $sformatf("Suppressing further '%s' messages", id), UVM_NONE)
         return CAUGHT; // Suppress after limit
      end
      
      return THROW;
   endfunction
endclass

4. Log to Separate File

class file_logger_catcher extends uvm_report_catcher;
   int log_file;
   
   function new(string name, string filename);
      super.new(name);
      log_file = $fopen(filename, "w");
   endfunction

   function action_e catch();
      if(get_severity() >= UVM_ERROR)
         $fdisplay(log_file, "[%0t] %s: %s", $time, get_id(), get_message());
      return THROW;
   endfunction
endclass

Registration Methods

Per-Component Registration

// Add catcher to specific component
uvm_report_cb::add(m_env, m_report_catcher);

// Remove when done
uvm_report_cb::delete(m_env, m_report_catcher);

Global Registration

// Catch messages from all components
uvm_report_cb::add(null, m_report_catcher);

Temporary Disable

// Disable without removing
void'(m_report_catcher.callback_mode(0));

// Re-enable
void'(m_report_catcher.callback_mode(1));

Best Practices

  • Be specific: Match exact IDs and message patterns to avoid suppressing real issues
  • Document demotions: Comment why each message is being demoted
  • Use regex carefully: uvm_re_match() uses DPI regex - test patterns thoroughly
  • Scope appropriately: Register catchers on specific components, not globally, when possible
  • Remove when done: Delete catchers after the expected error window passes
  • Log demotions: Print when messages are demoted for debug visibility

Key Takeaways

  • uvm_report_catcher intercepts messages before they reach the report handler
  • Override catch() to inspect and modify message attributes
  • Return THROW to pass messages on, CAUGHT to suppress them
  • Register catchers per-component with uvm_report_cb::add()
  • Use regex patterns for flexible message matching
  • Essential for handling expected errors in negative tests and known issues

Report catchers are essential for robust testbenches - they let you handle expected errors gracefully while ensuring unexpected issues still cause test failures.


Part of the UVM Examples series. See also: UVM Barrier | UVM Heartbeat

Author
Mayur Kubavat
VLSI Design and Verification Engineer sharing knowledge about SystemVerilog, UVM, and hardware verification methodologies.

Comments (0)

Leave a Comment