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 an MMIFMaster.
  • 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.