Chapter 13: Modeling Best Practices

Modeling Best Practices: Source and Standard Traceability

How to connect model behavior to LRM rules, Accellera implementation files, examples, tests, and project documentation.

Modeling Best Practices: Source and Standard Traceability

For senior engineers, "because it works in my simulator" is not enough. SystemC models must outlive the specific compiler and simulator version they were written against.

Important model behavior should be explicitly traceable to a standard rule (IEEE 1666 LRM), an implementation detail (Accellera PoC), a specific test, or a documented internal project policy.

The Four Traceability Levels

When commenting code or discussing architectural decisions, classify the justification into one of these four levels:

  1. Standard: The behavior is mandated by the IEEE 1666 LRM. (e.g., "Ports must be bound before end_of_elaboration"). This code is 100% portable across all commercial simulators.
  2. Implementation: The behavior is derived from reading the Accellera open-source codebase. (e.g., "The Accellera kernel uses std::vector for event lists, so preserving order is cheap"). This code is mostly portable, but relies on implementation details.
  3. Project Policy: The behavior is a team convention. (e.g., "All our virtual platforms use uint32_t for memory rather than sc_bv<32> for performance").
  4. Tool Workaround: The behavior exists to bypass a bug in a specific tool or compiler. These should always be marked with a TODO or issue tracker link so they can be deleted later.

Example: Signal Update Semantics

Standard Traceability:

IEEE 1666 Section 6.4: The sc_signal::write() method shall submit an update request. The new value shall not be visible to readers until the update phase of the current delta cycle.

Project Policy Translation:

To prevent non-deterministic combinatorial loops, no IP block in this project shall attempt to read an sc_signal in the same evaluation phase it was written.

Complete Example: Documenting Traceable Code

This complete sc_main demonstrates how to write a SystemC module where every architectural decision is documented with its traceability level. This is the gold standard for industrial Virtual Platforms.

#include <systemc>
#include <tlm>
#include <tlm_utils/simple_target_socket.h>
#include <iostream>
 
SC_MODULE(TraceableIP) {
    // [Project Policy]: Sockets must use snake_case and end with '_socket'
    tlm_utils::simple_target_socket<TraceableIP> target_socket{"target_socket"};
 
    // [Standard]: SC_HAS_PROCESS is required when not using SC_CTOR. 
    // Reference: IEEE 1666 Section 5.2.7
    SC_HAS_PROCESS(TraceableIP);
 
    TraceableIP(const sc_core::sc_module_name& name) : sc_core::sc_module(name) {
        target_socket.register_b_transport(this, &TraceableIP::b_transport);
    }
 
    void b_transport(tlm::tlm_generic_payload& trans, sc_core::sc_time& delay) {
        // [Standard]: Target MUST set response status before returning.
        // Reference: IEEE 1666 Section 14.12
        trans.set_response_status(tlm::TLM_OK_RESPONSE);
 
        // [Implementation]: We accumulate delay locally to leverage the 
        // Accellera TLM quantum keeper optimization, reducing context switches.
        delay += sc_core::sc_time(10, sc_core::SC_NS);
 
        // [Tool Workaround]: Simulator X crashes if we print payload pointers directly,
        // so we cast to void* first. (Ticket: #1234)
        std::cout << "[TraceableIP] Handled payload at ptr: " 
                  << static_cast<void*>(&trans) << "\n";
    }
};
 
int sc_main(int argc, char* argv[]) {
    // [Project Policy]: All top-level signals must be explicitly named
    sc_core::sc_signal<bool> rst_n{"rst_n"};
 
    TraceableIP ip("ip_inst");
 
    // Dummy test payload
    tlm::tlm_generic_payload trans;
    sc_core::sc_time delay = sc_core::SC_ZERO_TIME;
    trans.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
 
    ip.target_socket->b_transport(trans, delay);
 
    return 0;
}

Why Traceability Matters

If a commercial simulator vendor updates their engine and your simulation suddenly hangs, traceability saves weeks of debugging.

If your comments cite the LRM (Level 1), you can file a bug against the vendor. If your comments rely on an Accellera implementation detail (Level 2), you know immediately that you wrote non-portable code and need to fix your architecture. If you used a Tool Workaround (Level 4), you know you can likely delete the workaround now that the tool was updated.

Comments and Corrections