CIRCT 23.0.0git
Loading...
Searching...
No Matches
Functions
esiaccel.components.channel_arbiter Namespace Reference

Functions

List[int] _select_reg_levels (int num_inputs, Optional[int] mux_pipeline_levels)
 
int _select_latency (int num_inputs, Optional[int] mux_pipeline_levels)
 
BitsSignal _select_mux (BitsSignal sel, List[BitsSignal] values, ClockSignal clk, Signal rst, Optional[int] mux_pipeline_levels)
 
 RoundRobinArbiterMod (int num_inputs)
 
 ChannelArbiterMod (Channel channel_type, int num_inputs, int output_fifo_depth, bool buffer_inputs, bool telemetry, Optional[int] mux_pipeline_levels)
 
ChannelSignal ChannelArbiter (List[ChannelSignal] input_channels, ClockSignal clk, Signal rst, *Optional[AppID] appid=None, Optional[int] output_fifo_depth=None, bool buffer_inputs=True, Optional[int] mux_pipeline_levels=None, bool telemetry=True)
 

Function Documentation

◆ _select_latency()

int esiaccel.components.channel_arbiter._select_latency ( int  num_inputs,
Optional[int]  mux_pipeline_levels 
)
protected
Pipeline-register latency (cycles) that `_select_mux` inserts.

Definition at line 44 of file channel_arbiter.py.

References esiaccel.components.channel_arbiter._select_reg_levels().

Referenced by esiaccel.components.channel_arbiter.ChannelArbiterMod().

◆ _select_mux()

BitsSignal esiaccel.components.channel_arbiter._select_mux ( BitsSignal  sel,
List[BitsSignal]  values,
ClockSignal  clk,
Signal  rst,
Optional[int]  mux_pipeline_levels 
)
protected
Return `values[sel]`.

With `mux_pipeline_levels` falsy this is a flat combinational mux (a single
`hw.array_get`, which CIRCT lowers to an unpipelined mux tree). Otherwise it
is built as an explicit balanced binary mux tree -- 2:1 nodes consuming one
`sel` bit per level -- with a pipeline register inserted after every
`mux_pipeline_levels` levels. This lets a large/wide selection mux (the
Fmax bottleneck of a big fan-in mux) be retimed across registers. The
remaining `sel` bits are pipelined alongside the partial results so each
level selects with the correctly-delayed index. The added latency is
`_select_latency(len(values), mux_pipeline_levels)` cycles.

Definition at line 49 of file channel_arbiter.py.

References esiaccel.components.channel_arbiter._select_reg_levels().

Referenced by esiaccel.components.channel_arbiter.ChannelArbiterMod().

◆ _select_reg_levels()

List[int] esiaccel.components.channel_arbiter._select_reg_levels ( int  num_inputs,
Optional[int]  mux_pipeline_levels 
)
protected
Tree levels after which `_select_mux` inserts a pipeline register.

A register is placed after every `mux_pipeline_levels` levels, except after
the final (root) level -- its result is registered downstream. This is the
single source of truth for the mux-tree pipelining: `_select_mux` builds the
registers at these levels and `_select_latency` just counts them.

Definition at line 27 of file channel_arbiter.py.

Referenced by esiaccel.components.channel_arbiter._select_latency(), and esiaccel.components.channel_arbiter._select_mux().

◆ ChannelArbiter()

ChannelSignal esiaccel.components.channel_arbiter.ChannelArbiter ( List[ChannelSignal]  input_channels,
ClockSignal  clk,
Signal  rst,
*Optional[AppID]   appid = None,
Optional[int]   output_fifo_depth = None,
bool   buffer_inputs = True,
Optional[int]   mux_pipeline_levels = None,
bool   telemetry = True 
)
Build a pipelined, list-aware N:1 channel multiplexer.

Unlike the combinational `pycde.esi.ChannelMux`, this is a flat registered
round-robin arbiter with a feed-forward output stage (output register + FIFO
+ credit counter), so it closes timing at high fan-in. It also keeps
multi-flit list messages contiguous: once an input is granted, it holds the
output until a flit whose 'last' field is set has been transferred. List
framing is auto-detected from the channel type (window payloads with a 'last'
field); all other payloads are treated as single-flit messages.

Arguments:
  input_channels: the channels to multiplex. All must share the same
    (ValidReady) type.
  clk, rst: clock and reset.
  appid: optional `AppID` for the arbiter instance (e.g. to address it or to
    disambiguate its telemetry in the appid hierarchy).
  output_fifo_depth: depth of the output FIFO; must be greater than the
    pipeline latency (one output register plus any selection-mux pipeline
    latency). Defaults to that plus a small internal slack.
  buffer_inputs: insert a per-input skid buffer to localize backpressure.
  mux_pipeline_levels: if set, build the N:1 data-selection mux as an explicit
    binary tree and insert a pipeline register after every this-many tree
    levels (1 = register every level). This retimes the wide selection mux
    for very large fan-in; the added latency is absorbed by the output FIFO /
    credit counter. `None` (default) uses a flat combinational mux.
  telemetry: emit telemetry (selected channel, list-length stats, etc.).

See `docs/components/ChannelArbiter.md`.

Definition at line 415 of file channel_arbiter.py.

◆ ChannelArbiterMod()

esiaccel.components.channel_arbiter.ChannelArbiterMod ( Channel  channel_type,
int  num_inputs,
int  output_fifo_depth,
bool  buffer_inputs,
bool  telemetry,
Optional[int]  mux_pipeline_levels 
)
Build a pipelined, list-aware N:1 channel multiplexer module. See the
`ChannelArbiter` convenience function for the user-facing entry point and
`docs/components/ChannelArbiter.md` for the design.

Definition at line 147 of file channel_arbiter.py.

References esiaccel.components.channel_arbiter._select_latency(), esiaccel.components.channel_arbiter._select_mux(), and esiaccel.components.channel_arbiter.RoundRobinArbiterMod().

◆ RoundRobinArbiterMod()

esiaccel.components.channel_arbiter.RoundRobinArbiterMod ( int  num_inputs)
Combinational round-robin winner selection, factored into its own module
for waveform visibility.

Given a per-input `valids` bitmask (bit `i` is input `i`) and a `start` index,
`winner` is the lowest-index input that is valid and at index `>= start`
(cyclically), falling back to the lowest-index valid input overall; `any_valid`
is high when any input is valid. Purely combinational -- the owning state
(`grant`/`busy`/`rr_ptr`) lives in the arbiter.

Definition at line 85 of file channel_arbiter.py.

Referenced by esiaccel.components.channel_arbiter.ChannelArbiterMod().