Chapter 4: TLM and Platforms

TLM Base Protocol Rules and Checker Patterns

How to review blocking and non-blocking TLM transactions for legal phases, response status, ownership, DMI, and debug behavior.

How to Read This Lesson

TLM lets you move fast because a transaction is just a C++ object passed through an interface. The cost of that speed is discipline: the protocol rules live in the payload fields, phases, timing annotations, and ownership conventions.

Source and LRM Trail

Use Docs/LRMs/SystemC_LRM_1666-2023.pdf for TLM-2.0 base protocol behavior. In source, inspect .codex-src/systemc/src/tlm_core/tlm_2/tlm_generic_payload, tlm_2_interfaces, tlm_sockets, and tlm_quantum.

Blocking Transport Review

In blocking transport, the initiator calls:

socket->b_transport(trans, delay);

The target must treat the payload as an in-progress transaction and set a meaningful response status before returning.

Review these fields:

  • command: read, write, or ignore
  • address: target-visible address
  • data pointer: valid storage for the access
  • data length: number of bytes requested
  • streaming width: wrapping semantics for streaming transfers
  • byte enable pointer: null means all bytes enabled
  • response status: must not remain incomplete after target completion
  • DMI allowed: target may hint that DMI is worth requesting

Non-Blocking Base Protocol

The base protocol uses four canonical phases:

BEGIN_REQ -> END_REQ -> BEGIN_RESP -> END_RESP

The tricky part is that nb_transport_fw and nb_transport_bw pass the phase by reference and return a status:

  • TLM_ACCEPTED: I accepted this phase and will respond later.
  • TLM_UPDATED: I changed the phase and delay before returning.
  • TLM_COMPLETED: transaction is complete now.

That gives the model flexibility, but it also creates review burden. A phase checker should verify that transitions are legal for the protocol style your project uses.

Checker Pattern

A simple checker can live beside an interconnect:

struct TxnState {
  bool request_seen = false;
  bool response_seen = false;
};
 
void check_phase(TxnState& s, tlm::tlm_phase phase) {
  if (phase == tlm::BEGIN_REQ) {
    if (s.request_seen) {
      SC_REPORT_ERROR("TLM_CHECK", "duplicate BEGIN_REQ");
    }
    s.request_seen = true;
  }
 
  if (phase == tlm::BEGIN_RESP) {
    if (!s.request_seen) {
      SC_REPORT_ERROR("TLM_CHECK", "response before request");
    }
    s.response_seen = true;
  }
}

Real checkers also track transaction identity, outstanding request limits, exclusion rules, and protocol-specific extensions.

How the Source Makes This Work

The Accellera TLM implementation does not magically know your bus protocol. It defines the base interfaces, payload, phases, sockets, and helper classes. Your model or protocol checker must enforce higher-level rules such as AXI ordering, ID handling, burst legality, and exclusive access semantics.

That distinction is important: TLM-2.0 gives you the transport framework. It does not make every transaction valid for your architecture.

DMI and Debug Review

DMI is a promise that direct pointer access is safe for an address range. If a target grants DMI, it must invalidate that pointer when the range becomes unsafe.

Debug transport is a promise that the access is for inspection and should not change modeled state in surprising ways. A debug read to a FIFO should not consume data. A debug write should be documented very carefully.

Review Checklist

  • Does every completed transaction set a response status?
  • Are data pointers and lengths valid for the access?
  • Are non-blocking phases legal for the chosen protocol?
  • Is payload ownership clear?
  • Are extensions copied, cloned, and released correctly?
  • Is DMI invalidated when memory maps or permissions change?
  • Is transport_dbg side-effect free?

Comments and Corrections