The clock drives systolic array execution tick by tick.
The clock is the orchestrator: it delegates to the selected backend's tick sequence in strict order, for as many ticks as requested.
Backend selection
By default, the interpreted (single-process) backend is used. You can
select the partitioned (tile-based parallel) backend via the :backend
option:
# Interpreted (default)
Clock.run(array, ticks: 10)
# Partitioned
Clock.run(array, ticks: 10, backend: :partitioned, tile_rows: 4, tile_cols: 4)Both backends produce identical results for the same inputs.
Determinism
Because the interpreted backend is purely functional and the partitioned
backend uses BSP barriers (no interleaving between compute and
communication), running Clock.run(array, ticks: n) always produces
the same result for the same inputs, regardless of backend choice.
API
Summary
Functions
Runs the array for the given number of ticks.
Executes a single tick of the array using the interpreted backend.
Functions
@spec run( ExSystolic.Array.t(), keyword() ) :: ExSystolic.Array.t()
Runs the array for the given number of ticks.
Returns the final array state, which includes the updated PEs, links, tick counter, and trace.
Options
:ticks-- number of ticks (required):backend--:interpreted(default) or:partitioned:tile_rows-- rows per tile (partitioned only):tile_cols-- cols per tile (partitioned only)
Examples
iex> alias ExSystolic.{Array, Clock, PE.MAC}
iex> array = Array.new(rows: 1, cols: 1) |> Array.fill(MAC) |> Array.connect(:west_to_east) |> Array.connect(:north_to_south)
iex> array = Array.input(array, :west, [{{0,0}, [3, 2]}])
iex> array = Array.input(array, :north, [{{0,0}, [4, 5]}])
iex> result = Clock.run(array, ticks: 2)
iex> result.tick
2
@spec step(ExSystolic.Array.t()) :: ExSystolic.Array.t()
Executes a single tick of the array using the interpreted backend.
Follows the strict order:
- INJECT external input streams into boundary link buffers
- READ all link buffers
- EXECUTE all PEs
- COLLECT outputs
- WRITE outputs into link buffers
- RECORD trace
Examples
iex> alias ExSystolic.{Array, Clock, PE.MAC}
iex> array = Array.new(rows: 1, cols: 1) |> Array.fill(MAC) |> Array.connect(:west_to_east) |> Array.connect(:north_to_south)
iex> array = Array.input(array, :west, [{{0,0}, [3]}])
iex> array = Array.input(array, :north, [{{0,0}, [4]}])
iex> result = Clock.step(array)
iex> result.tick
1