Derived interfaces
A derived interface is a transaction pattern layered on a primitive. It has no
kind_of_endpoint kind of its own, because there is no port kind to give it.
The source already says so. derive_internal_edges describes an AckedStreamIF as “two FIFOs that
a module wants to talk about as one thing”, which is the definition of derived: one name, one set of
methods, and underneath it the primitives that actually reach the boundary.
How a derived interface decomposes
Every interface here is built from primitives, but they differ in how they hand you the primitive underneath — and that difference is worth knowing before you wire one up.
| how it composes | |
|---|---|
| Credit Stream | declares two StreamIFs and exposes them; wiring is automatic |
| Acked Stream | declares two StreamIFs and exposes them; wiring is automatic |
| AXI-MM Command Queue | a protocol over an MMIFMaster — the ring lives in the transactions, not in a new channel |
The two reverse channels declare their composition, so a walk over the design finds the underlying streams without help:
from waveflow.hw.reverse_stream import CreditStreamIF, AckedStreamIF
for cls in (CreditStreamIF, AckedStreamIF):
print(f"{cls.__name__:16s} {cls.physical_interfaces.__doc__.splitlines()[0]}")
CreditStreamIF Two ordinary streams. Nothing here lowers to a new kind of edge.
AckedStreamIF Two ordinary streams. In hardware there is no acked stream — there are two FIFOs.
The queue is the odd one: it is a protocol over an MMIFMaster rather than a new channel, so the
ring lives in the transactions and there is nothing extra to bind.
The two reverse channels
Both are a forward stream plus a second stream running the other way, and they are not two flavours of one mechanism:
| Credit | Acked | |
|---|---|---|
| answers | “May I send? Is there room?” | “What became of what I sent?” |
| arrives | before the send | after the send |
| who could possibly know | the channel | only the consumer |
| carries | cumulative words consumed | one outcome per marked item |
| could a FIFO do this? | yes — TREADY is credit, one unit at a time at the moment of use |
no: a dropped TX sample is a missed deadline, delivered perfectly and simply late |
They live in one module because the rules underneath them are genuinely shared — and so is the masked-counter arithmetic, which is the one thing most likely to be got wrong in exactly one of two copies.
Pages
- AXI-MM Command Queue — the in-memory command ring (
AXIMMQueue): control moved off the stream and into shared memory, over anMMIFMaster. - Credit Stream — the receiver’s reverse channel: cumulative words consumed, so a producer that cannot be stalled can ask about room before it commits.
- Acked Stream — the transmitter’s reverse channel: one outcome per marked item, with positional token recovery and no id on the wire.
Table of contents
- Credit Stream - CreditStreamIF — a forward stream plus a reverse credit channel, so a producer knows there is room before it commits. Built from two ordinary StreamIFs. Use it only when the producer cannot abandon a transaction partway; if it can simply block, a plain StreamIF is better and cheaper.
- Acked Stream - AckedStreamIF — a forward stream plus a reverse status channel, so a producer learns what became of what it sent. Built from two ordinary StreamIFs. Use it when the consumer is the only party that can know an outcome: a missed deadline on a transmit path is delivered perfectly and simply late, which no FIFO can report.
- AXI-MM Command Queue - The in-memory command queue — AXIMMQueue, a host-driven ring buffer over an MMIFMaster. Documented because examples/vmac is built on it, but NOT the pattern to reach for first: a memory queue cannot notify, so the consumer must poll, and the polling costs bandwidth.