Chapter 5: Source Internals

SystemC Source Map & LRM Alignment

A guided map of the official source tree: kernel, communication, datatypes, TLM, and utilities.

SystemC Source Map & LRM Alignment

The official SystemC implementation is worth reading because it explains the API design. You do not need to read it linearly. Read it as a map of responsibilities, aligned directly with the IEEE 1666 Language Reference Manual (LRM).

The public repository is accellera-official/systemc. Directory names can move across releases, but the conceptual areas remain stable. Understanding how these conceptual areas map to the C++ implementation is the key to deep SystemC mastery.

1. Kernel (LRM Section 4: Elaboration and Simulation)

The kernel area contains the scheduler, simulation context, process classes, events, time, reports, and object hierarchy. Names you will encounter include:

  • sc_simcontext: the central simulation context. It holds the event queues and Delta Cycle loop.
  • sc_object: the base class for hierarchical objects.
  • sc_module: structural hierarchy and process registration support.
  • sc_event: event notification and wait support.
  • sc_process_b, sc_method_process, sc_thread_process: implementation of methods and coroutines.

Read this area when you want to understand sc_start(), delta cycles, process readiness, and why wait() is legal in an SC_THREAD but throws an exception in an SC_METHOD.

2. Communication (LRM Section 6 & 7: Channels and Interfaces)

The communication area contains ports, exports, interfaces, primitive channels, signals, FIFOs, mutexes, semaphores, and clocks.

  • sc_interface: Pure virtual base class.
  • sc_port: The mechanism for a module to call an interface.
  • sc_signal: The fundamental channel implementing request-update semantics.

This is where the object model becomes a network. Ports do not merely hold C++ pointers. They participate in binding policy, interface checking, and simulation setup.

3. Datatypes (LRM Section 7: Data Types)

SystemC includes hardware-friendly datatypes such as:

  • Arbitrary precision integers (sc_bigint, sc_biguint)
  • Bit vectors (sc_bv)
  • Logic vectors (sc_lv, sc_logic)
  • Fixed-point types (sc_fixed)

These types exist because plain C++ integer behavior cannot model hardware realities like four-state logic ('0', '1', 'Z', 'X') or precise bit-width truncation.

4. TLM (LRM Section 10-16: TLM-2.0)

The TLM area includes generic payloads, phases, sockets, target and initiator interfaces, and utility helpers. Sockets are not a separate universe. They package standard SystemC ports, exports, callbacks, and interfaces into a highly optimized bus-modeling form.

Bringing it All Together: Complete Example

To illustrate how these four main quadrants of the SystemC source map (Kernel, Communication, Datatypes, TLM) synthesize into a single LRM-compliant model, here is a complete executable example.

#include <systemc>
#include <tlm>
#include <tlm_utils/simple_initiator_socket.h>
#include <tlm_utils/simple_target_socket.h>
#include <iostream>
 
using namespace sc_core;
using namespace sc_dt; // Datatypes
 
// ---------------------------------------------------------
// A module demonstrating Kernel processes, Communication 
// channels, Datatypes, and TLM-2.0 Sockets.
// ---------------------------------------------------------
SC_MODULE(SourceMapDemo) {
  // --- COMMUNICATION ---
  sc_in<bool> clk{"clk"}; 
  
  // --- COMMUNICATION & DATATYPES ---
  // A primitive channel wrapping a 4-bit unsigned integer
  sc_signal<sc_uint<4>> counter{"counter"}; 
  
  // --- TLM ---
  tlm_utils::simple_initiator_socket<SourceMapDemo> init_socket{"init_socket"}; 
  
  SC_CTOR(SourceMapDemo) {
    // --- KERNEL ---
    // Registering a clocked thread with the simulation context
    SC_CTHREAD(clocked_thread, clk.pos()); 
  }
  
  void clocked_thread() {
    // Initialization
    counter.write(0);
 
    while (true) {
      // Kernel: Yield execution back to the scheduler
      wait(); 
      
      // Datatypes: Read, manipulate, and write the 4-bit type
      sc_uint<4> val = counter.read() + 1;
      counter.write(val);
      
      std::cout << "[Demo] Clock ticked. Counter: " << val << "\n";
 
      // TLM: Generate a transaction when the counter overflows (4-bit overflow)
      if (val == 0) {
        std::cout << "[Demo] Counter overflowed! Sending TLM transaction.\n";
        
        tlm::tlm_generic_payload trans;
        sc_time delay = SC_ZERO_TIME;
        
        trans.set_command(tlm::TLM_WRITE_COMMAND);
        trans.set_address(0x100);
        trans.set_data_length(4);
        trans.set_streaming_width(4);
        trans.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
 
        // Blocking transport call
        init_socket->b_transport(trans, delay); 
        
        if (trans.is_response_ok()) {
            std::cout << "[Demo] TLM transaction completed successfully.\n";
        }
      }
    }
  }
};
 
// Target to satisfy the TLM binding
SC_MODULE(DummyTarget) {
  tlm_utils::simple_target_socket<DummyTarget> target_socket{"target_socket"};
  
  SC_CTOR(DummyTarget) {
    target_socket.register_b_transport(this, &DummyTarget::b_transport);
  }
  
  void b_transport(tlm::tlm_generic_payload& trans, sc_time& delay) {
    std::cout << "  -> [Target] Received transaction at address 0x" 
              << std::hex << trans.get_address() << "\n";
    trans.set_response_status(tlm::TLM_OK_RESPONSE);
  }
};
 
// Top Level
int sc_main(int argc, char* argv[]) {
  // Kernel: Clock generation
  sc_clock clk("clk", 10, SC_NS);
  
  SourceMapDemo demo("demo");
  DummyTarget tgt("tgt");
  
  // Communication: Structural binding during Elaboration Phase
  demo.clk(clk);
  demo.init_socket.bind(tgt.target_socket);
  
  std::cout << "Starting Simulation...\n";
  // Kernel: Enter Simulation Phase
  sc_start(170, SC_NS); 
  std::cout << "Simulation Complete.\n";
  
  return 0;
}

Explanation of the Execution

When you run this simulation, the sc_clock drives the SC_CTHREAD. The sc_uint<4> datatype safely rolls over from 15 to 0. When it hits 0, it triggers the TLM-2.0 socket, bridging the cycle-accurate RTL abstraction with the Loosely Timed VP abstraction.

By understanding how these source map quadrants interact, you can read any SystemC codebase with confidence.

Comments and Corrections