Skip to main content
Softwareadvancedtlmsystemctransactionmodelingsimulationtiming

TLM-2.0 Transaction-Level Modeling

Comprehensive guide to SystemC TLM-2.0 for high-level system modeling and communication.

15 min read
Updated 9/8/2024
2 prerequisites

Prerequisites

Make sure you're familiar with these concepts before diving in:

SystemC Fundamentals
C++ Fundamentals and Performance

Learning Objectives

By the end of this topic, you will be able to:

Master TLM-2.0 sockets and payload structures
Understand timing models: LT and AT
Implement transaction-level communication
Apply temporal decoupling techniques

Table of Contents

TLM-2.0 Transaction-Level Modeling

TLM-2.0 (Transaction-Level Modeling) is a SystemC standard for high-level system modeling that focuses on communication between components rather than detailed implementation.

1. Sockets

1.1 Socket Types

Initiator Socket - Used by masters to send transactions:

tlm_utils::simple_initiator_socket<Module> initiator_socket;

Target Socket - Used by targets (slaves) to receive transactions:

tlm_utils::simple_target_socket<Module> target_socket;

1.2 Socket Binding

Initiator sockets connect to target sockets to build the interconnect graph:

master.initiator_socket.bind(slave.target_socket);

2. Payload - tlm::tlm_generic_payload

2.1 Payload Fields

  • Command: READ or WRITE operation
  • Address: Target memory address
  • Data pointer + length: Payload data and size
  • Streaming width: Data transfer width
  • Byte enables: Which bytes are valid
  • DMI hint: Direct Memory Interface suggestion
  • Response status: Transaction completion status

2.2 Payload Usage

  • Reused along path: No copies made during transaction
  • Target updates: Response status and data buffer (for reads)
  • Shared resource: Must be handled carefully in concurrent environments

3. Timing Models

3.1 Loosely-Timed (LT)

Characteristics:

  • One blocking call: b_transport(payload, delay)
  • Add latency to delay parameter
  • Call returns when transaction is "done" at target level

Temporal Decoupling:

tlm_utils::tlm_quantumkeeper qk;
// Initiator accumulates local time
qk.inc(local_delay);
// Sync to SystemC time when quantum reached
if (qk.need_sync()) qk.sync();

Benefits:

  • Fast simulation
  • Simple to implement
  • Good for software development

3.2 Approximately-Timed (AT)

Characteristics:

  • Non-blocking four-phase handshake
  • Uses nb_transport_fw/bw and tlm_phase
  • Time annotation without blocking

Four-Phase Protocol:

  1. Forward path (initiator→target):
    • BEGIN_REQ: Start request
    • END_RESP: End response
  2. Backward path (target→initiator):
    • END_REQ: End request
    • BEGIN_RESP: Begin response

Implementation Pattern:

// Forward path
tlm_sync_enum nb_transport_fw(tlm_generic_payload& trans, 
                              tlm_phase& phase, 
                              sc_time& t) {
    if (phase == BEGIN_REQ) {
        // Process request, schedule response
        phase = END_REQ;
        return TLM_UPDATED;
    }
    return TLM_COMPLETED;
}
 
// Backward path  
tlm_sync_enum nb_transport_bw(tlm_generic_payload& trans,
                              tlm_phase& phase,
                              sc_time& t) {
    if (phase == BEGIN_RESP) {
        // Handle response
        phase = END_RESP;
        return TLM_COMPLETED;
    }
    return TLM_ACCEPTED;
}

Scheduling:

  • Use PEQ (Payload Event Queue) for production code
  • Simple phase scheduling with annotated delays for prototypes

3.3 Direct Memory Interface (DMI)

Purpose:

  • Bypass target via direct pointer access
  • Significant performance improvement
  • Optional optimization technique

Usage:

  • Target provides direct memory access
  • Initiator caches pointer for repeated access
  • Invalidation mechanism for coherency

4. Implementation Guidelines

4.1 LT Model Example

void b_transport(tlm_generic_payload& trans, sc_time& delay) {
    // Extract command, address, data
    tlm_command cmd = trans.get_command();
    uint64_t addr = trans.get_address();
    unsigned char* data = trans.get_data_ptr();
    
    // Process transaction
    if (cmd == TLM_READ_COMMAND) {
        // Read from memory[addr] to data
        memcpy(data, &memory[addr], trans.get_data_length());
    } else if (cmd == TLM_WRITE_COMMAND) {
        // Write from data to memory[addr]
        memcpy(&memory[addr], data, trans.get_data_length());
    }
    
    // Add processing delay
    delay += sc_time(10, SC_NS);
    
    // Set successful response
    trans.set_response_status(TLM_OK_RESPONSE);
}

4.2 AT Model Considerations

  • Payload Event Queue: Manage transaction scheduling
  • Time annotation: Precise timing without blocking
  • Phase management: Careful state tracking
  • Concurrent transactions: Handle multiple outstanding requests

5. Best Practices

5.1 Performance

  • LT for speed: Use for fast functional simulation
  • AT for accuracy: Use when timing precision matters
  • DMI optimization: Implement for frequently accessed memory

5.2 Design

  • Payload reuse: Don't copy, modify in place
  • Error handling: Check and set response status
  • Memory management: Initiator owns payload lifecycle
  • Thread safety: Consider concurrent access patterns

5.3 Debugging

  • Transaction tracing: Log payload contents and phases
  • Timing analysis: Monitor delay accumulation
  • Protocol compliance: Verify phase sequences

TLM-2.0 enables efficient system-level modeling by abstracting communication details while preserving timing relationships and functional behavior.