Tuesday, 12 August 2014

How to stop the simulation on `UVM_ERROR

Below is a good article which shows how to control simulation flow with different types of errors.

The default behavior of `uvm_error is to continue the simulation once the message is reported. Although one can argue over Accelera’s default choice, there are ways to stop the simulation on `uvm_error. I’ve tested them with UVM 1.1d and UVM 1.2 releases.

Using Simulator Arguments

Major simulators support the +uvm_set_action command-line argument to set a custom action for report messages:
+uvm_set_action=<comp>,<id>,<severity>,<action>
For example, to stop the simulation on `uvm_error(“MY_ERROR”, “message”), use the following argument when invoking the simulator:
+uvm_set_action="uvm_test_top.*,MY_ERROR,UVM_ERROR,UVM_STOP"
You can use _ALL_ instead of MY_ERROR to set the action for all errors, regardless of their id.

Using the uvm_component API

Call uvm_component.set_report_id_action_hier (string id,uvm_action action), for example after elaboration:
class basic_test extends uvm_test;
    function void end_of_elaboration_phase(uvm_phase phase);
        super.end_of_elaboration_phase(phase);
        set_report_id_action_hier("MY_ERROR", UVM_STOP);
    endfunction
endclass

Pay Attention: objects vs. components vs. sequence items

To my surprise, the above configuration does not apply to `uvm_error calls from within an uvm_object, for example for config objects, even if created under the “uvm_test_top.*” or “basic_test” hierarchy…
For `uvm_error calls from within an uvm_sequence_item, the message is delegated to the enclosing sequencer, hence it is not behaving like an uvm_object. The component path is enhanced with the enclosing sequencer and the sequence hierarchy path.
My recommendation is to use a generous star path pattern (“*”) when working with simulator arguments:
+uvm_set_action="*,MY_ERROR,UVM_ERROR,UVM_STOP"

or use the uvm_root component when working with the uvm_component API:
class basic_test extends uvm_test;
    function void end_of_elaboration_phase(uvm_phase phase);
        uvm_root top = uvm_root::get();
        super.end_of_elaboration_phase(phase);
        top.set_report_id_action_hier("MY_ERROR", UVM_STOP);
    endfunction
endclass

Underground Details for the Curious

The `uvm_error macro is defined as:
`define uvm_error(ID,MSG) \
   begin \
     if (uvm_report_enabled(UVM_NONE,UVM_ERROR,ID)) \
       uvm_report_error (ID, MSG, UVM_NONE, `uvm_file, `uvm_line); \
   end

That is the macro call is delegated to a uvm_report_error() function call. The function that is actually called depends on the context where the macro is used.
There are three relevant uvm_report_error() function definitions in the UVM library:
  1. uvm_report_object.uvm_report_error(). An uvm_component inherits from uvm_report_object.
  2. Global uvm_report_error() which delegates the call to uvm_root.uvm_report_error()
  3. uvm_sequence_item.uvm_report_error() which delegates the call to its sequencer, if it exists or to uvm_root.

No comments:

Post a Comment