Batcher Protocol Combiner
For building batcher super-frames in software from individual Rogue stream
frames, Rogue provides rogue.protocols.batcher.CombinerV1 and
CombinerV2. These are the software equivalents of the firmware batcher and
the inverse of the splitter classes.
Use a combiner when you need to produce batched super-frames in software, for example to emulate firmware batching in test setups, or to generate controlled inputs for CI regression testing of the unbatcher (splitter) classes.
Version Selection
Use
CombinerV1to produce batcher v1 super-frames.Use
CombinerV2to produce batcher v2 super-frames.
How Combining Works
The combiner operates in two phases:
Queue – Individual frames are accepted via the stream slave interface (
acceptFrame()). Each frame’s payload, channel, firstUser, and lastUser are preserved in the queue.Batch – Calling
sendBatch()builds a single batcher super-frame containing all queued frames, writes the appropriate super-header and per-record tails, and emits the super-frame downstream.
CombinerV1 writes the width-dependent header and tail padding required by
the v1 protocol. The width constructor parameter controls the AXI stream
width encoding (0 = 16-bit through 5 = 512-bit).
CombinerV2 writes the fixed 2-byte header and 7-byte per-record tails
defined by the v2 protocol.
Round-Trip Guarantee
A combiner followed by the matching splitter reproduces the original frames:
Payload bytes are identical.
Channel, firstUser, and lastUser metadata are preserved.
This makes the combiner useful as a test fixture for CI regression testing of the splitter and inverter classes.
Python Examples
V1
import rogue.protocols.batcher
import rogue.interfaces.stream
# Build a batcher v1 super-frame from individual frames.
combiner = rogue.protocols.batcher.CombinerV1(2) # width=2 -> 64-bit
# Downstream splitter to verify round-trip.
splitter = rogue.protocols.batcher.SplitterV1()
dst = MyRecordSink()
# Connect a stream source to the combiner, then to the splitter/sink.
src = MyFrameSource()
src >> combiner
combiner >> splitter >> dst
# src sends frames into the combiner via the stream interface,
# which queues them internally. Then sendBatch() builds and emits
# the super-frame downstream.
combiner.sendBatch()
V2
import rogue.protocols.batcher
import rogue.interfaces.stream
# Build a batcher v2 super-frame from individual frames.
combiner = rogue.protocols.batcher.CombinerV2()
# Downstream splitter to verify round-trip.
splitter = rogue.protocols.batcher.SplitterV2()
dst = MyRecordSink()
# Connect a stream source to the combiner, then to the splitter/sink.
src = MyFrameSource()
src >> combiner
combiner >> splitter >> dst
# src sends frames into the combiner via the stream interface,
# which queues them internally. Then sendBatch() builds and emits
# the super-frame downstream.
combiner.sendBatch()
C++ Example
#include <rogue/protocols/batcher/CombinerV1.h>
#include <rogue/protocols/batcher/SplitterV1.h>
namespace rpb = rogue::protocols::batcher;
int main() {
// Width=2 -> 64-bit AXI stream.
auto combiner = rpb::CombinerV1::create(2);
auto splitter = rpb::SplitterV1::create();
auto dst = MyRecordSink::create();
*(*combiner >> splitter) >> dst;
// After queuing frames via the stream interface:
combiner->sendBatch();
return 0;
}
Threading And Lifecycle
The combiner classes do not create worker threads. Frame queueing runs
synchronously inside acceptFrame(), and batch building runs
synchronously inside sendBatch().
API Reference
Python: CombinerV1 CombinerV2
C++: CombinerV1 CombinerV2