uvm_report_catcher/uvm_error demoter Example

In short: A uvm_report_catcher lets you inspect every report message before it is acted on, and change it. The most common use is an error demoter: you catch a known, harmless UVM_ERROR and lower it to a UVM_WARNING or UVM_INFO so it does not fail an otherwise passing test. You write a class that extends uvm_report_catcher, override catch(), and register it with uvm_report_cb::add.

Sometimes a test triggers a known error you cannot remove right away, for example an error from a third-party VIP that you have already reviewed. Instead of editing that code, you can catch the message and lower its severity. A report catcher gives you one clean place to do this.

A simple way to picture it

Think of a mail sorting room. Every letter passes through a sorter before delivery. The sorter can read the address, stamp it, redirect it, or drop it in the bin. A uvm_report_catcher is that sorter for report messages: each message passes through catch(), where you can change its severity, edit its text, or throw it away, before it reaches the report server.

What is uvm_report_catcher?

uvm_report_catcher is a callback class. You extend it, override the catch() method, and register an instance so UVM runs your catch() for every message. Inside catch() you read the message with helper methods, decide what to do, and return either THROW (keep processing it) or CAUGHT (stop it here).

MethodWhat it gives you
get_severity()The current severity, such as UVM_ERROR
get_id()The message ID string
get_message()The message text
set_severity()Change the severity, this is how demotion works
set_message()Rewrite the message text
THROW / CAUGHTReturn value: pass it on, or stop it here

An error demoter: full working example

Here is a catcher that demotes a specific error by ID. It only touches messages whose ID is ADDR_RANGE and whose severity is UVM_ERROR. Everything else passes through unchanged.

class err_demoter extends uvm_report_catcher;
  `uvm_object_utils(err_demoter)

  function new(string name = "err_demoter");
    super.new(name);
  endfunction

  // catch() runs for every report message
  virtual function action_e catch();
    if (get_severity() == UVM_ERROR && get_id() == "ADDR_RANGE") begin
      set_severity(UVM_WARNING);                 // demote the error
      set_message({"[demoted] ", get_message()});// tag the text
    end
    return THROW;   // keep processing the (now changed) message
  endfunction
endclass

The key line is set_severity(UVM_WARNING). After this, the report server treats the message as a warning, so it no longer counts toward the error total that fails the test. Returning THROW means the message still prints, now as a warning. If you wanted to drop it entirely, you would return CAUGHT.

Registering the catcher

Create the catcher and add it with uvm_report_cb::add. Passing null as the first argument means it applies to every component. You usually do this in the test build_phase.

class my_test extends uvm_test;
  `uvm_component_utils(my_test)
  err_demoter demoter;

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

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    demoter = err_demoter::type_id::create("demoter");
    uvm_report_cb::add(null, demoter);   // apply to all components
  endfunction
endclass

To limit the catcher to one component, pass that component handle instead of null. This is handy when only one agent produces the known error and you do not want to hide the same ID elsewhere.

Other things a catcher can do

Demotion is the common case, but the same hook has more uses.

  • Promote a warning to an error when a specific warning must not be ignored.
  • Drop a noisy message by returning CAUGHT so it never prints.
  • Rewrite unclear text with set_message() to add context.
  • Count how many times a specific ID fired, for a custom check.

Demote versus other ways to handle known errors

ApproachWhen to useDownside
Report catcher demoteA known error you have reviewed and acceptHides a real error if the ID is too broad
set_report_severity_id_overrideSimple, per-component severity changeLess flexible, no text edit or logic
Fix the sourceAlways best when you own the codeNot possible for third-party VIP
Raise the error count limitNever recommendedMasks every error, not just the known one

A catcher is the right tool when you need logic: match on ID and severity, edit the text, and leave everything else untouched. For a plain severity change on one component, set_report_severity_id_override is simpler.

Common mistakes to avoid

  • Matching too broadly, for example demoting every UVM_ERROR, which hides real failures.
  • Forgetting to return a value from catch(), or returning CAUGHT when you still wanted the message to print.
  • Registering the catcher after the errors already fired; add it in build_phase.
  • Leaving a demoter in place permanently instead of removing it once the underlying issue is fixed.
  • Demoting by text match instead of ID, which is fragile if the message wording changes.

Keep learning

Report handling ties in with UVM messaging. Read more about UVM reporting, macros, severity and verbosity, see the typical UVM testbench architecture, and browse the UVM category and interview questions.

Frequently asked questions

What is a uvm_report_catcher used for?

It is a callback that runs for every report message before the report server acts on it. You can change severity, edit text, drop the message, or count it. The most common use is demoting a known error to a warning.

How do I demote a UVM_ERROR to a warning?

Extend uvm_report_catcher, override catch(), and when the message matches your ID and severity call set_severity(UVM_WARNING). Return THROW so the message still prints as a warning.

How do I register a report catcher?

Create the catcher with the factory, then call uvm_report_cb::add(null, catcher) in the test build_phase. Passing null applies it to all components; pass a component handle to limit its scope.

What is the difference between THROW and CAUGHT?

THROW passes the message on for further processing, including printing. CAUGHT stops the message right there, so it never reaches the report server or the log.

Should I match on ID or on message text?

Match on the message ID. It is stable, while the text can change. Matching on text is fragile and can silently stop working when the wording is updated.

Is demoting errors a good idea?

Only for a known, reviewed error that you cannot fix right away, such as one from third-party code. Keep the match narrow by ID and severity, and remove the demoter once the real issue is resolved.

Similar Posts