Gem5ToTlmBridge and TlmToGem5Bridge perform real-time translation so components from both worlds can communicate seamlessly โ like two diplomats with an interpreter between them.
Table of Contents
Architecture Overview
The systemc module provides a complete SystemC/TLM 2.0 integration layer for gem5, enabling mixed-language simulation. It contains three main components: the TLM bridge for bidirectional transaction translation, a SystemC kernel implementation that schedules SC processes within gem5's event-driven framework, and port wrappers that adapt gem5's port model to SystemC interfaces.
flowchart LR
subgraph gem5["gem5 Domain"]
CPU["CPU / Device"]
RP["ResponsePort"]
RQP["RequestPort"]
end
subgraph Bridge["Translation Layer"]
G2T["Gem5ToTlmBridge"]
T2G["TlmToGem5Bridge"]
end
subgraph SC["SystemC Domain"]
IS["Initiator Socket"]
TS["Target Socket"]
SCM["SC Module"]
end
CPU --> RP
RP --> G2T
G2T --> IS
IS --> SCM
SCM --> TS
TS --> T2G
T2G --> RQP
RQP --> CPU
The architecture enables four key use cases: (1) gem5 CPU accessing SystemC memory/peripherals, (2) SystemC initiators accessing gem5 memory, (3) mixed SystemC/gem5 Cache Hierarchy | gem5 Wiki" href="../mem_doc/cache/index.html">cache hierarchies, and (4) co-simulation with external SystemC IP blocks.
TLM Bridge Layer
The TLM bridge provides bidirectional translation between gem5's packet-based memory protocol and SystemC's TLM 2.0 generic payload protocol. Two template classes handle the two directions:
flowchart TD
subgraph G2T["Gem5ToTlmBridge<BITWIDTH>"]
BRP["BridgeResponsePort\n(gem5::ResponsePort)"]
Conv1["packet2payload()"]
SIS["simple_initiator_socket"]
end
subgraph T2G["TlmToGem5Bridge<BITWIDTH>"]
STS["simple_target_socket"]
Conv2["payload2packet()"]
BRQP["BridgeRequestPort\n(gem5::RequestPort)"]
end
PKT["gem5::PacketPtr"] --> BRP
BRP --> Conv1
Conv1 --> GP["tlm_generic_payload"]
GP --> SIS
GP2["tlm_generic_payload"] --> STS
STS --> Conv2
Conv2 --> PKT2["gem5::PacketPtr"]
PKT2 --> BRQP
| Bridge | Direction | Input | Output |
|---|---|---|---|
Gem5ToTlmBridge<BITWIDTH> | gem5 โ SystemC | gem5 System | gem5 Wiki" class="xref">Packet | TLM Generic Payload |
TlmToGem5Bridge<BITWIDTH> | SystemC โ gem5 | TLM Generic Payload | gem5 Packet |
Both bridges are parameterized by BITWIDTH, which specifies the address bus width. The conversion is extensible via addPacketToPayloadConversionStep() and addPayloadToPacketConversionStep(), allowing custom address translation, command mapping, and data transformation hooks.
Conversion Pipeline
sequenceDiagram
participant G as gem5 CPU
participant BP as BridgeResponsePort
participant G2T as Gem5ToTlmBridge
participant SC as SystemC Target
G->>BP: sendTimingReq(PacketPtr)
BP->>G2T: recvTimingReq(PacketPtr)
G2T->>G2T: packet2payload(pkt)
Note over G2T: Map MemCmd โ TLM command
Note over G2T: Copy address, data, size
Note over G2T: Run conversion steps
G2T->>SC: nb_transport_fw(payload, phase, delay)
SC-->>G2T: TLM_ACCEPTED / TLM_COMPLETED
G2T->>G2T: payload โ response packet
G2T->>BP: sendTimingResp(PacketPtr)
BP->>G: recvTimingResp
Command Mapping
| gem5 MemCmd | TLM Command | Notes |
|---|---|---|
ReadReq | TLM_READ_COMMAND | Standard read transaction |
WriteReq | TLM_WRITE_COMMAND | Standard write transaction |
ReadExReq | TLM_READ_COMMAND | Exclusive read (coherence) |
WritebackDirty | TLM_WRITE_COMMAND | Cache writeback |
| Other | TLM_IGNORE_COMMAND | Unmapped commands |
Key Classes
| Class | Parent | File | Description |
|---|---|---|---|
Gem5ToTlmBridgeBase | sc_core::sc_module | tlm_bridge/gem5_to_tlm.hh | Base class for gem5โTLM bridge; non-template common logic |
Gem5ToTlmBridge<BW> | Gem5ToTlmBridgeBase | tlm_bridge/gem5_to_tlm.hh | Template bridge: gem5 Packet โ TLM payload via initiator socket |
TlmToGem5BridgeBase | sc_core::sc_module | tlm_bridge/tlm_to_gem5.hh | Base class for TLMโgem5 bridge; non-template common logic |
TlmToGem5Bridge<BW> | TlmToGem5BridgeBase | tlm_bridge/tlm_to_gem5.hh | Template bridge: TLM payload โ gem5 Packet via request port |
ScPortWrapper<IF> | gem5::Port | sc_port_wrapper.hh | Wraps sc_port for gem5 port binding system |
ScInterfaceWrapper<IF> | gem5::Port | sc_port_wrapper.hh | Wraps SC interface for gem5 binding |
ScExportWrapper<IF> | gem5::Port | sc_port_wrapper.hh | Wraps SC export for bidirectional binding |
Process | sc_process_b | core/process.hh | SC process execution: threads and methods |
Scheduler | โ | core/scheduler.hh | Delta-cycle scheduler coordinating SC processes and events |
Channel | โ | core/channel.hh | SC value channel implementation (signals, FIFOs) |
sc_signal | โ | channel/sc_signal.cc | Signal channel for inter-process communication |
sc_clock | โ | channel/sc_clock.cc | Clock signal generator |
sc_mutex | โ | channel/sc_mutex.cc | Mutual exclusion primitive |
Deep Dive: Bridge Mechanics
Gem5ToTlmBridge Internals
The Gem5ToTlmBridge contains an inner BridgeResponsePort that receives gem5 packets. On each timing request:
- The response port calls
packet2payload()to convert the gem5 Packet to a TLM generic payload - Address, data pointer, data length, and command are mapped to TLM equivalents
- Custom conversion steps are applied (registered via
addPacketToPayloadConversionStep()) - The payload is sent via
nb_transport_fw()on the Atomic and Timing Simple CPUs โ gem5 Wiki" href="../cpu_doc/simple/index.html">simple initiator socket - On response, the payload is converted back and sent via
sendTimingResp()
TlmToGem5Bridge Internals
The reverse bridge uses a simple_target_socket to receive TLM transactions and a BridgeRequestPort to inject gem5 packets:
- Incoming TLM transactions arrive at
nb_transport_fw()callback payload2packet()creates a gem5 Packet with proper MemCmd and data- A
RequestorIDis assigned for gem5's coherence tracking - The packet is sent via
sendTimingReq()on the request port - Responses trigger
nb_transport_bw()with TLM completion phase
Extensible Conversion
Both bridges support a pipeline of conversion steps, enabling custom protocol extensions:
// Register a custom conversion step
bridge->addPacketToPayloadConversionStep(
[](PacketPtr pkt, tlm_generic_payload &trans) {
// Custom address remapping
trans.set_address(pkt->getAddr() - base_offset);
// Add extension data
auto *ext = new MyExtension(pkt->req->contextId());
trans.set_auto_extension(ext);
}
);
Deep Dive: SystemC Kernel
The core/ subdirectory implements a complete SystemC kernel that runs within gem5's event-driven simulation engine. This enables native SystemC modules to execute alongside gem5 components.
Scheduler Phases
flowchart TD
INIT["Initialization Phase"]
EVAL["Evaluate Phase"]
UPD["Update Phase"]
DELTA["Delta Notification"]
TIME["Timed Notification"]
CHECK{More deltas?}
INIT --> EVAL
EVAL --> UPD
UPD --> DELTA
DELTA --> CHECK
CHECK -->|"Yes"| EVAL
CHECK -->|"No"| TIME
TIME --> EVAL
| Phase | Description |
|---|---|
| Initialization | Execute SC_METHOD/SC_THREAD initialization, perform channel updates, process delta notifications |
| Evaluate | Run all runnable processes (methods and threads), collect channel update requests |
| Update | Apply pending channel updates atomically (signal new values, FIFO writes) |
| Delta Notification | Process zero-delay event notifications, may trigger new evaluations |
| Timed Notification | Advance to next timed event; integrates with gem5 tick via sc_time โ Tick conversion |
Process Model
The Process class manages SC_THREAD and SC_METHOD execution using gem5's Fiber-based context switching. Key state management:
needsStart()โ process hasn't been started yetsuspended()/resume()โ manual suspend/resume controldisable()/enable()โ sensitivity disable/enablekill()/reset()โ process termination and restart- Reference counting via
incref()/decref()for safe lifecycle management
Deep Dive: Port Wrappers
The port wrapper layer adapts SystemC's port/export/interface model to gem5's Port base class, enabling the gem5 port binding system to connect to SystemC components.
classDiagram
class Port {
<<gem5::Port>>
+bind(Port)
+unbind()
}
class ScPortWrapper~IF~ {
-sc_port~IF~ &port
+bind(Port)
}
class ScInterfaceWrapper~IF~ {
-IF &interface
+bind(Port)
}
class ScExportWrapper~IF~ {
-sc_export~IF~ &exp
+bind(Port)
}
Port <|-- ScPortWrapper
Port <|-- ScInterfaceWrapper
Port <|-- ScExportWrapper
The binding rules enforce type safety:
ScPortWrappercan bind toScPortWrapper(port-to-port) orScInterfaceWrapper(port-to-interface)ScExportWrappercan bind toScPortWrapper(export-to-port)- Unbinding panics โ SystemC does not support port unbinding at runtime
Cross-Module Interactions
| Dependency | Module | Purpose |
|---|---|---|
| Memory protocol | mem | Packet, RequestPort, ResponsePort, Backdoor, RequestorID |
| Simulation core | sim | EventQueue, Port base class, tick management |
| Context switching | base/fiber | Fiber-based coroutines for SC_THREAD implementation |
| SystemC standard | systemc/ext | IEEE 1666 headers: core, TLM, channels, data types |
| Logging | base | Types, logging, trace, panic/fatal |
| Python config | python | Tlm.py SimObject configuration wrapper |
Directory Map
Configuration Parameters
| Parameter | Class | Description |
|---|---|---|
tlm_bridge_bitwidth | Gem5ToTlmBridge / TlmToGem5Bridge | Address bus width template parameter (32, 64) |
system | TlmBridge | Reference to parent System object |
cpu_side_port | Gem5ToTlmBridge | gem5 ResponsePort for incoming requests |
mem_side_port | TlmToGem5Bridge | gem5 RequestPort for outgoing requests |
addr_ranges | Both bridges | Address ranges handled by this bridge instance |
Python Configuration Example
from m5.objects import Gem5ToTlmBridge64, TlmToGem5Bridge64
# Create bridge from gem5 CPU to SystemC memory
g2t_bridge = Gem5ToTlmBridge64()
g2t_bridge.cpu_side_port = system.membus.mem_side_ports
# Create bridge from SystemC DMA to gem5 memory
t2g_bridge = TlmToGem5Bridge64()
t2g_bridge.mem_side_port = system.membus.cpu_side_ports
Code Examples
Gem5-to-TLM Packet Conversion
// tlm_bridge/gem5_to_tlm.cc โ Convert gem5 packet to TLM payload
template <unsigned int BITWIDTH>
void Gem5ToTlmBridge<BITWIDTH>::packet2payload(
PacketPtr pkt, tlm_generic_payload &trans)
{
trans.set_address(pkt->getAddr());
// Map gem5 command to TLM command
if (pkt->isRead())
trans.set_command(tlm::TLM_READ_COMMAND);
else if (pkt->isWrite())
trans.set_command(tlm::TLM_WRITE_COMMAND);
else
trans.set_command(tlm::TLM_IGNORE_COMMAND);
// Set data pointer and length
trans.set_data_ptr(pkt->getPtr<unsigned char>());
trans.set_data_length(pkt->getSize());
trans.set_streaming_width(pkt->getSize());
// Run registered conversion steps
for (auto &step : conversionSteps)
step(pkt, trans);
}
Port Wrapper Binding
// sc_port_wrapper.hh โ Type-safe port adapter
template <typename IF>
class ScPortWrapper : public gem5::Port
{
sc_core::sc_port<IF> &port_;
public:
ScPortWrapper(sc_core::sc_port<IF> &p, const std::string &name)
: gem5::Port(name), port_(p) {}
void bind(Port &peer) override
{
// Bind to another ScPortWrapper or ScInterfaceWrapper
auto *iface = dynamic_cast<ScInterfaceWrapper<IF>*>(&peer);
if (iface) {
port_.bind(iface->interface());
return;
}
auto *other = dynamic_cast<ScPortWrapper<IF>*>(&peer);
if (other) {
port_.bind(other->port());
return;
}
gem5::fatal("Incompatible port binding");
}
void unbind() override { gem5::panic("Cannot unbind sc_port"); }
};
SystemC Process Lifecycle
// core/process.hh โ Process state management
class Process : public sc_core::sc_process_b
{
public:
bool needsStart() const; // Not yet started
bool dynamic() const; // Dynamically spawned
bool scheduled() const; // In runnable list
void suspend(bool inc_kids);
void resume(bool inc_kids);
void disable(bool inc_kids);
void enable(bool inc_kids);
void kill(bool inc_kids);
void reset(bool inc_kids);
// Reference counting for safe lifecycle
void incref() { refCount++; }
void decref() { if (--refCount == 0) delete this; }
// Reset signal handling
void signalReset(bool active, bool async);
void syncResetOn(bool inc_kids);
void syncResetOff(bool inc_kids);
};