Chapter 7: SystemC 1666-2023 LRM

LRM Bridge: Reports, Tracing, and Introspection

Reporting severity, report handlers, VCD tracing, object hierarchy, attributes, version information, and diagnostics.

Diagnostics are a formalized part of the SystemC standard surface. Standardizing error reporting and trace generation ensures interoperability between different IP vendors and testbench infrastructures.

End-to-End Tracing and Reporting Example

This complete example demonstrates the SC_REPORT macros, custom message types, and generating a standard Value Change Dump (VCD) trace file.

#include <systemc>
 
SC_MODULE(DiagnosticsDemo) {
    sc_core::sc_in<bool> clk;
    sc_core::sc_signal<uint32_t> counter{"counter"};
 
    SC_CTOR(DiagnosticsDemo) {
        SC_THREAD(logic_thread);
        sensitive << clk.pos();
    }
 
    void logic_thread() {
        uint32_t val = 0;
        while(true) {
            wait();
            val++;
            counter.write(val);
            
            // Standard reporting
            SC_REPORT_INFO("DiagnosticsDemo", "Counter incremented.");
 
            if (val == 3) {
                // Warning with a custom message type ID
                SC_REPORT_WARNING("LIMIT_CHECK", "Counter reached 3. Approaching limit.");
            }
            if (val == 5) {
                // Error report. By default, SC_REPORT_ERROR will stop the simulation.
                SC_REPORT_ERROR("LIMIT_CHECK", "Counter overflowed the simulated limit!");
            }
        }
    }
};
 
int sc_main(int argc, char* argv[]) {
    sc_core::sc_clock clk("clk", 10, sc_core::sc_time_unit::SC_NS);
    
    DiagnosticsDemo demo("demo");
    demo.clk(clk);
 
    // 1. Create a VCD trace file
    sc_core::sc_trace_file* tf = sc_core::sc_create_vcd_trace_file("wave_trace");
    
    // 2. Trace signals
    sc_core::sc_trace(tf, clk, "System_Clock");
    sc_core::sc_trace(tf, demo.counter, "Counter_Value");
 
    std::cout << "Starting simulation. This will terminate automatically on SC_REPORT_ERROR." << std::endl;
    
    // 3. Start Simulation
    sc_core::sc_start(100, sc_core::SC_NS);
 
    // 4. Close the trace file gracefully
    sc_core::sc_close_vcd_trace_file(tf);
 
    return 0;
}

Reports and Handling Policies

Never use std::cout or printf for structural warnings or errors, and never call std::exit() from inside a reusable IP block.

Use the standard macros:

  • SC_REPORT_INFO(msg_type, msg)
  • SC_REPORT_WARNING(msg_type, msg)
  • SC_REPORT_ERROR(msg_type, msg): By default, throws an exception and halts the scheduler.
  • SC_REPORT_FATAL(msg_type, msg): Immediately aborts execution entirely.

Report Handlers

The simulation environment (often the sc_main testbench) can override the default actions for these reports using sc_report_handler. An application can configure all warnings of msg_type "LIMIT_CHECK" to be suppressed, or demote an SC_REPORT_ERROR to merely increment an internal counter rather than halting the simulation.

Tracing

Tracing records signal activity into a file.

auto* tf = sc_create_vcd_trace_file("wave");
sc_trace(tf, signal, "signal_name");

Trace files must be created before sc_start() is called, and gracefully closed (sc_close_vcd_trace_file) at the end of sc_main(). The generated .vcd files can be opened in tools like GTKWave.

Object Hierarchy

SystemC objects know their names and hierarchy. Hierarchy is how a large model remains navigable and debuggable. You can always query an object's location in the elaboration tree via this->name() (e.g., top.router_0.timer_1).

Comments and Corrections