abstraction
LT vs AT
2026 · 9 min read
Every TLM 2.0 modeling project starts with the same fork: loosely-timed or approximately-timed. Most teams pick by instinct — fast or accurate. The real question is different: what do you need the model to be able to say?
The two interfaces, mechanically
LT (loosely-timed) models use the blocking
interface: b_transport(payload, delay). The caller
hands over a transaction and doesn't get control back until
it's done. One call, one delay parameter, no intermediate
states. The transaction is atomic from the initiator's point of
view.
AT (approximately-timed) models use the non-blocking
interfaces: nb_transport_fw and
nb_transport_bw, passing transactions through the
four phases of the TLM 2.0 base protocol — BEGIN_REQ,
END_REQ, BEGIN_RESP, END_RESP. Each phase transition is a
separate call, annotated with its own point in time. The
transaction is a state machine, not an atomic operation.
That mechanical difference is the whole story. Everything else — pipelining, timing accuracy, throughput — follows from it.
What LT can and cannot do
LT's atomicity is a superpower for the right workload. Because a transaction completes in one call, an LT model of a CPU can execute an instruction — or a hundred — without the memory system needing to know how long anything took. The delay parameter is a bookkeeping convention, not a scheduling commitment. This is why LT platforms boot operating systems at hundreds of MIPS: nothing in the interconnect is spending simulation time on protocol choreography.
But atomicity has a structural consequence: an LT initiator can have exactly one transaction in flight per socket. Not "usually one" — one, by construction, because the initiator is blocked inside the call. If your question is "what happens when this CPU issues a read while three other reads are still walking the interconnect," an LT model cannot represent the question, let alone answer it.
The standard's answer to this is the DMI and debug escape hatches — and they're the right answer. LT platforms that need speed get it by bypassing the interconnect entirely for memory accesses, not by making the interconnect faster.
What AT buys, and what it costs
AT exists for the questions LT can't ask: overlap. A request that hasn't been accepted yet. A response that's on its way while the next request is already queued. An interconnect with a fixed number of outstanding transactions per port, exerting backpressure when it's full. These are the behaviors that decide real performance — and they are invisible to a blocking model.
The cost is proportionate. Every transaction becomes a state machine. Every phase transition needs a time annotation and a scheduling decision. The model now has to answer questions LT never asked: when does the target accept the request? When does it choose to respond? What happens when two transactions are in overlapping phases at the same target? Each answer is a modeling decision that has to be correlated against something — RTL, or a spec, or a defensible assumption.
And that's the honest trade: AT doesn't make the model more accurate. It makes the model more answerable — and every new answerable question is a new place to be wrong. An AT model that hasn't been correlated is a hypothesis generator with extra steps.
The decision procedure we use
When we scope an engagement, the abstraction level is the first architectural decision, and we make it against a checklist, not a vibe:
- Who consumes the model? Software teams bring-up firmware want LT — they need miles, not timing. Architects sizing buffers want AT — they need overlap, not miles.
- What's the question? "Does the code run?" is LT. "How fast does it run, and where does it stall?" is AT.
- What's the correlation target? If there's RTL to correlate against, AT has something to check itself. If there's only a spec, AT's timing assumptions are unanchored — and that needs to be said out loud.
- What's the traffic? One initiator that mostly waits on memory: LT loses almost nothing. Multiple initiators contending for one target: LT can't see the contention that dominates the real system.
The answer is often "both, in layers" — and that's not a cop-out, it's the point of the standard. A common shape: LT functional models for the blocks, an AT interconnect between them, so the platform boots fast and the interconnect — where the performance questions live — models overlap honestly. The boundary between the two abstraction levels is itself an architectural decision, and it deserves the same scrutiny as the levels themselves.
The failure mode we keep seeing
The most expensive mistake in this space isn't picking the wrong level. It's picking a level and then asking the model the other level's questions. The LT platform that gets used to "validate" a performance fix. The AT model whose timing assumptions came from nowhere, presented with AT's credibility. Both fail quietly — the model produces numbers, the numbers look plausible, and nobody notices that the abstraction level had already decided the answer before the question was asked.
The abstraction level isn't a technical detail of the model. It's the boundary of what the model can know. Pick it like that, and it's the cheapest decision in the project. Pick it like a tool preference, and it's the most expensive one.