Chapter 6: Practice

Reports, Errors, and Debugging

Using SC_REPORT_INFO, warnings, errors, hierarchy names, assertions, and debug patterns.

Debuggability is part of the model. A virtual platform that fails with a vague C++ exception is harder to trust than one that reports the module, transaction, address, and simulated time. The IEEE 1666 LRM provides a comprehensive sc_report_handler utility for exactly this purpose.

End-to-End Reporting Example

Here is a full compilable example demonstrating SC_REPORT_INFO, SC_REPORT_WARNING, SC_REPORT_ERROR, named object tracking, and even configuring the global report handler to stop simulation on specific errors.

#include <systemc>
#include <iomanip>
#include <sstream>
 
using namespace sc_core;
 
SC_MODULE(UartModel) {
  SC_CTOR(UartModel) {
    SC_THREAD(run);
  }
 
  void run() {
    // 1. Basic Info
    SC_REPORT_INFO(name(), "UART Initialization Complete");
    wait(10, SC_NS);
 
    // 2. Warning with context
    SC_REPORT_WARNING(name(), "Buffer nearing capacity!");
    wait(10, SC_NS);
 
    // 3. Formatted Error using string stream
    uint32_t bad_address = 0xFFFFFFFF;
    std::ostringstream msg;
    msg << "Access to unmapped address 0x" 
        << std::hex << bad_address 
        << " at time " << sc_time_stamp();
        
    SC_REPORT_ERROR("AddressDecoder", msg.str().c_str());
  }
};
 
int sc_main(int argc, char* argv[]) {
  // Configure the report handler to abort simulation on the first error
  sc_report_handler::set_actions(SC_ERROR, SC_DISPLAY | SC_ABORT);
 
  UartModel uart("uart");
  sc_start(100, SC_NS);
 
  return 0;
}

SystemC Reports

SystemC provides standard report macros. Reports include severity (INFO, WARNING, ERROR, FATAL) and can include source location depending on configuration.

Use categories (the first argument to SC_REPORT_INFO) consistently so users can filter logs via sc_report_handler::set_actions().

Include Time and Path

Named hierarchy is one of SystemC's strengths. Use it. name() gives the hierarchical object name (e.g. top.bus.uart). This makes messages actionable in large systems.

Assertions

Prefer explicit SC_REPORT_ERROR or SC_REPORT_FATAL for model/user mistakes because they can carry context, time, and hierarchy strings. Plain assert() is acceptable for internal developer invariants, but it crashes the simulator abruptly, preventing graceful log flushes or user-defined intercepts.

Transaction Debugging

For TLM, log the complete transaction shape. This reveals whether a bug is in address decode, target behavior, timing, byte enables, or response propagation.

Delta-Cycle Debugging

If a signal-based model behaves one event late, print both sc_time_stamp() and relevant values before and after wait(SC_ZERO_TIME). Do not leave noisy debug logs enabled by default. Add a verbosity flag or compile-time switch.

Comments and Corrections