Skip to content

flm.GEMM: take M, K, N and the activation as runtime parameters - #200

Merged
hunhoffe merged 14 commits into
develfrom
flm-gemm-rtp-v2
Sep 16, 2026
Merged

hunhoffe merged 14 commits into
develfrom
flm-gemm-rtp-v2

Conversation

@hunhoffe

@hunhoffe hunhoffe commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator

Moves flm.GEMM's shape out of the device configuration and into the instruction stream, so one xclbin serves every projection of a model instead of one per shape. All 30 E2B + E4B projection shapes now resolve to a single configuration, asserted by test_one_xclbin_serves_every_shape. M, K, N, the activation and the clamp bounds are runtime parameters.

The parameter buffer is 4 words rather than 10. A word costs ~2.06 µs of dispatch latency across the 32 cores, which is most of a short-prefill dispatch against a ~107 µs floor, so the clamp trio is sent only by a clamp-capable build and n_work/n_drain are derived on-core from a raw N word plus the tile's own column. Separately, split legs (K or N = 10240, where the row-block stride overflows the shim BD's 20-bit iteration step) now retire the oldest transfer as the next is issued instead of draining a whole window and then a whole column-block — worth up to -12.4% on those shapes.

The cost is memtile B residency, which sized the memtile buffer from k_iters and replayed it m_row_blocks times, putting both K and M into the configuration. Against the pre-RTP build, short prefill gets faster (M=256 median -5.5%) and long prefill pays for B's re-reads (M=1024 +13.1%, M=2048 +22.0%). This is a deliberate trade rather than a regression to fix before merge. Recovering it needs a replay count driven from the instruction stream; that is now reachable via aiex.dma_channel_reset_for in the pinned v1.4.3, but the buffer would still be sized from k_iters. Follow-up, not a blocker.

Accuracy is identical to pre-RTP.

PR Merge Checklist

  1. The PR is rebased on the latest devel commit and pointing to devel.
  2. Your PR has been reviewed and approved.
  3. All checks are passing.

andrej and others added 3 commits September 11, 2026 15:59
The FastFlowLM harness registers one mm.xclbin per model and swaps
instruction streams, against a budget of 16 xclbins for the whole model.
This operator baked M, K and N into the core loop bounds, into which columns
it built, and into the memtile's B buffer, so it needed one xclbin per
shape: 11 (K, N, activation) combinations times up to 16 chunk lengths.

Five values move into an L1 buffer the runtime sequence writes and each core
reads once its barrier opens: the column's work and drain counts, M/256,
K/512, and the activation. All columns are now always built, and one with no
work for a shape drains its share of the A broadcast instead. The epilogue
tests its mode once per chunk, outside the vector loop, so each mode keeps a
branch-free inner loop; which modes it can select between stays a build-time
choice, since each costs program memory.

The device body is then a function of the tiling alone, verified byte for
byte across every E2B shape and activation. So the xclbin is built from a
module emitted at a reference shape and the per-shape build produces only
the instruction stream, and the two carry different artifact stems.

The core releases its barrier straight after reading the parameters.
wait_for_value emits LockAction.Acquire, which does not leave the lock
consumed, so without the release a core that runs twice does not wait the
second time and reads the previous dispatch's parameters. Releasing before
the work is safe because the sequence cannot set the barrier again until it
has drained this dispatch's C. The repo's other barrier users never wait
twice -- mha puts its infinite loop inside the wait, softmax writes the same
parameters every dispatch -- so this does not arise there.
test_one_xclbin_serves_every_shape is the regression test; the parametrised
tests cannot catch it, because the aie_context fixture reconfigures the
array between cases.

Dropping B residency is what this costs, and it is not cheap: 12.5% at
M=512, 16.4% at M=1024 and 19.3% at M=2048 on NPU2. Residency sizes the
memtile buffer from K and replays it M/256 times through a buffer
descriptor's repeat count, so it carries both K and M into the
configuration. Restoring it needs a replay mechanism that carries neither.

It does lift a cap: the repeat count expands into the memtile's BD chain at
2 blocks per replay and exceeded its 48-block limit at M=4096, so no shape
with K <= 2048 would build there -- 7 of Gemma4 E2B's 10 projections. All of
them build now.

Verified on this base over all 12 distinct E2B prefill projections at M=256
and M=4096, dispatched back to back on one loaded xclbin with no reset in
between, each checked against a CPU reference; peak 12.2 TFLOP/s at M=4096
K=12288 N=1536. Plus the operator's own suite, 17 non-extensive tests.
The merge of andrej/flm-gemm-rtp was textually clean but left the README
self-contradictory: the new intro says M, K, N and the activation are
runtime parameters, while the FLM-compatibility note I had added in
92080d4 still claimed they were baked in at compile time and called
RTP-selectability "follow-up work" -- which 81e2006 had just done.

- Drop that note entirely; the "Runtime parameters" section it would have
  pointed at now covers the same ground correctly.
- Fix the same stale claim in the shipped-overlay section, and record
  what IS still build-time there: which activations the epilogue can
  select between, since each one compiled in costs program memory.
- design.py: "None of these four" was already stale from 92080d4, which
  added a fifth bullet.

Co-Authored-By: André Rösti <an.roesti@gmail.com>
The RTP work left clamp entirely compile-time, so _config_tag carried the
bound values and every distinct pair forked a whole xclbin -- clamp=(-2,2)
and clamp=(-4,4) built twice over.

Split it the way epilogue_modes already splits activations: the CAPABILITY
stays build-time, the SELECTION and the values go runtime.

- Whether a clamped path exists at all is still -DMM_FUSED_CLAMP, because
  the clamped instantiation costs program memory and a build that never
  clamps should not carry it. That bit stays in _config_tag.
- clamp_enabled and the bounds become RTP words 5-7. Bounds are floats but
  npu_write_rtp writes i32 only, so they travel as raw bit patterns and the
  kernel casts them back with __builtin_bit_cast -- memcpy leaves an
  unresolved external call in the compiled object rather than folding to a
  register move.
- epilogue_body gains a CLAMP template parameter so the clamped and
  unclamped inner loops both stay branch-free; epilogue_dispatch picks
  between them once per chunk, and only compiles the clamped one when the
  capability is on.

Deliberately NOT done: making clamp_enabled a plain runtime branch. That
would double epilogue_body instantiations (mode x clamp), and program
memory is the exact constraint epilogue_modes exists to manage.

Verified on npu2: all four kernel variants (aie2/aie2p x clamp on/off)
compile, 36/36 flm/gemm iter0 tests pass, and the new
test_one_xclbin_serves_every_clamp_bound confirms three different bound
pairs run back to back on one loaded xclbin while an unclamped build
still resolves to a different configuration.

Co-Authored-By: André Rösti <an.roesti@gmail.com>
@github-actions

github-actions Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

CI Test Results

bb0d09b (2026_09_15_22_10_53)

IRON - CI Summary

Examples

iron/applications/llama_3.2_1b
Test Krackan Status Krackan Phoenix Status Phoenix
test_llama_3_2_1b[llama_3.2_1b_prompt_1024_tokens_1] - - -
test_llama_3_2_1b[llama_3.2_1b_prompt_1024_tokens_40] - - -
test_llama_3_2_1b[llama_3.2_1b_prompt_13_tokens_1] - - -
test_llama_3_2_1b[llama_3.2_1b_prompt_13_tokens_40] - - -

Small

iron/operators/axpy
Test Krackan Status Krackan Latency (mean) Phoenix Status Phoenix Latency (mean)
test_axpy[input_length_2048-num_aie_columns_1-tile_size_2048-scalar_factor_3.0] 148.30 415.98
test_axpy[input_length_2048-num_aie_columns_2-tile_size_1024-scalar_factor_3.0] 136.16 414.16
test_axpy[input_length_2048-num_aie_columns_4-tile_size_512-scalar_factor_3.0] 161.00 524.50
test_axpy[input_length_2048-num_aie_columns_8-tile_size_256-scalar_factor_3.0] 203.74 - -
iron/operators/dequant
Test Krackan Status Krackan Latency (mean) Phoenix Status Phoenix Latency (mean)
test_dequant[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048-group_size_32] 157.68 397.56
test_dequant[input_length_2048-num_aie_columns_1-num_channels_2-tile_size_1024-group_size_32] 157.10 448.88
test_dequant[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024-group_size_32] 155.26 454.26
test_dequant[input_length_2048-num_aie_columns_2-num_channels_2-tile_size_512-group_size_32] 160.72 487.24
test_dequant[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512-group_size_32] 168.94 380.98
test_dequant[input_length_2048-num_aie_columns_4-num_channels_2-tile_size_256-group_size_32] 167.98 481.62
test_dequant[input_length_2048-num_aie_columns_8-num_channels_1-tile_size_256-group_size_32] 168.78 - -
test_dequant[input_length_2048-num_aie_columns_8-num_channels_2-tile_size_128-group_size_32] 220.44 - -
iron/operators/elementwise_add
Test Krackan Status Krackan Latency (mean) Phoenix Status Phoenix Latency (mean)
test_elementwise_add[input_length_2048-num_aie_columns_1-tile_size_2048] 152.90 497.48
test_elementwise_add[input_length_2048-num_aie_columns_2-tile_size_1024] 147.56 846.58
test_elementwise_add[input_length_2048-num_aie_columns_4-tile_size_512] 158.52 543.88
test_elementwise_add[input_length_2048-num_aie_columns_8-tile_size_256] 177.84 - -
iron/operators/elementwise_mul
Test Krackan Status Krackan Latency (mean) Phoenix Status Phoenix Latency (mean)
test_elementwise_mul[input_length_2048-num_aie_columns_1-tile_size_2048] 162.28 332.94
test_elementwise_mul[input_length_2048-num_aie_columns_2-tile_size_1024] 166.62 442.54
test_elementwise_mul[input_length_2048-num_aie_columns_4-tile_size_512] 202.60 418.38
test_elementwise_mul[input_length_2048-num_aie_columns_8-tile_size_256] 229.18 - -
iron/operators/flm/gemm
Test Krackan Status Krackan Latency (mean) Phoenix Status Phoenix Latency (mean)
test_artifact_stem_differs_from_generic_gemm[M_256-K_512-N_1024] - -
test_artifact_stem_differs_from_generic_gemm[M_512-K_1024-N_2048] - -
test_gemm[M_256-K_512-N_1024-epilogue_gelu-clamp_None-rounding_conv_even] 460.56 - -
test_gemm[M_256-K_512-N_1024-epilogue_none-clamp_(-2.0, 2.0)-rounding_conv_even] 381.98 - -
test_gemm[M_256-K_512-N_1024-epilogue_none-clamp_None-rounding_conv_even] 315.82 - -
test_gemm[M_256-K_512-N_1024-epilogue_none-clamp_None-rounding_floor] 363.10 - -
test_gemm[M_256-K_512-N_1024-epilogue_silu-clamp_None-rounding_conv_even] 462.50 - -
test_gemm[M_256-K_512-N_128-epilogue_none-clamp_None-rounding_conv_even] 338.80 737.46
test_gemm[M_256-K_512-N_1536-epilogue_none-clamp_None-rounding_conv_even] 396.62 - -
test_gemm[M_256-K_512-N_256-epilogue_none-clamp_None-rounding_conv_even] - - 864.92
test_gemm[M_256-K_512-N_320-epilogue_none-clamp_None-rounding_conv_even] - - 736.98
test_gemm[M_256-K_512-N_512-epilogue_gelu-clamp_None-rounding_conv_even] - - 1010.80
test_gemm[M_256-K_512-N_512-epilogue_none-clamp_(-2.0, 2.0)-rounding_conv_even] - - 1020.82
test_gemm[M_256-K_512-N_512-epilogue_none-clamp_None-rounding_floor] - - 939.96
test_gemm[M_256-K_512-N_512-epilogue_silu-clamp_None-rounding_conv_even] - - 1048.06
test_gemm[M_256-K_512-N_64-epilogue_none-clamp_None-rounding_conv_even] - - 640.90
test_gemm[M_512-K_1024-N_2048-epilogue_none-clamp_None-rounding_conv_even] 463.10 - -
test_gemm[M_512-K_1024-N_512-epilogue_none-clamp_None-rounding_conv_even] - - 1909.40
test_gemm_split_leg_bounds[iter0] - -
test_gemm_split_leg_bounds[iter1] - -
test_gemm_split_leg_bounds[iter2] - -
test_gemm_split_leg_bounds[iter3] - -
test_gemm_split_leg_bounds[iter4] - -
test_gemm_split_leg_bounds_runs[iter0] - -
test_gemm_split_leg_bounds_runs[iter1] - -
test_gemm_split_leg_bounds_runs[iter2] - -
test_gemm_split_leg_bounds_runs[iter3] - -
test_gemm_split_leg_bounds_runs[iter4] - -
test_gemm_tile_options[tn128-ma64-default] - -
test_gemm_tile_options[tn16-ma64-default] - -
test_gemm_tile_options[tn32-ma64-default] - -
test_gemm_tile_options[tn64-ma16-default] - - -
test_gemm_tile_options[tn64-ma32-default] - - -
test_one_xclbin_serves_every_clamp_bound[iter0] - -
test_one_xclbin_serves_every_clamp_bound[iter1] - -
test_one_xclbin_serves_every_clamp_bound[iter2] - -
test_one_xclbin_serves_every_clamp_bound[iter3] - -
test_one_xclbin_serves_every_clamp_bound[iter4] - -
test_one_xclbin_serves_every_shape[iter0] - -
test_one_xclbin_serves_every_shape[iter1] - -
test_one_xclbin_serves_every_shape[iter2] - -
test_one_xclbin_serves_every_shape[iter3] - -
test_one_xclbin_serves_every_shape[iter4] - -
iron/operators/gelu
Test Krackan Status Krackan Latency (mean) Phoenix Status Phoenix Latency (mean)
test_gelu[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048] 193.04 383.36
test_gelu[input_length_2048-num_aie_columns_1-num_channels_2-tile_size_1024] 174.82 428.10
test_gelu[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024] 177.78 464.02
test_gelu[input_length_2048-num_aie_columns_2-num_channels_2-tile_size_512] 189.08 651.32
test_gelu[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512] 178.48 425.32
test_gelu[input_length_2048-num_aie_columns_4-num_channels_2-tile_size_256] 196.50 427.72
test_gelu[input_length_2048-num_aie_columns_8-num_channels_1-tile_size_256] 167.70 - -
test_gelu[input_length_2048-num_aie_columns_8-num_channels_2-tile_size_128] 205.12 - -
iron/operators/gemm
Test Krackan Status Krackan Latency (mean) Phoenix Status Phoenix Latency (mean)
test_gemm[M_1792-K_896-N_1152-num_aie_columns_8-b_col_maj_False-c_col_maj_True-m_64-k_32-n_48-trace_size_0-partition_N_1] 2243.64 - -
test_gemm[M_192-K_384-N_64-num_aie_columns_4-b_col_maj_False-c_col_maj_False-m_48-k_96-n_16-trace_size_0-partition_N_1] 193.86 912.54
test_gemm[M_192-K_384-N_64-num_aie_columns_4-b_col_maj_True-c_col_maj_True-m_48-k_96-n_16-trace_size_0-partition_N_1] 210.98 980.86
test_gemm[M_2048-K_2048-N_2048-num_aie_columns_1-b_col_maj_False-c_col_maj_False-m_64-k_64-n_64-trace_size_0-partition_N_1] 47823.42 82749.56
test_gemm[M_2048-K_2048-N_2048-num_aie_columns_2-b_col_maj_True-c_col_maj_False-m_64-k_64-n_64-trace_size_0-partition_N_1] 27921.00 21930.58
test_gemm[M_2048-K_2048-N_2048-num_aie_columns_8-b_col_maj_True-c_col_maj_True-m_64-k_64-n_64-trace_size_0-partition_N_1] 7713.58 - -
test_gemm[M_384-K_1536-N_1792-num_aie_columns_4-b_col_maj_True-c_col_maj_False-m_32-k_48-n_64-trace_size_0-partition_N_1] 2200.06 4093.60
test_gemm[M_64-K_512-N_256-num_aie_columns_4-b_col_maj_True-c_col_maj_False-m_16-k_64-n_64-trace_size_0-partition_N_4] 3508.34 5532.54
test_gemm[M_896-K_1792-N_640-num_aie_columns_8-b_col_maj_False-c_col_maj_True-m_32-k_64-n_80-trace_size_0-partition_N_1] 1605.54 - -
iron/operators/gemv
Test Krackan Status Krackan Latency (mean) Phoenix Status Phoenix Latency (mean)
test_gemv[M_128-K_128-num_aie_columns_1-tile_size_input_32-tile_size_output_128] 0.19 0.10
test_gemv[M_2048-K_8192-num_aie_columns_1-tile_size_input_1-tile_size_output_2048] 12.48 3.61
test_gemv[M_2048-K_8192-num_aie_columns_2-tile_size_input_1-tile_size_output_1024] 23.95 6.16
test_gemv[M_2048-K_8192-num_aie_columns_4-tile_size_input_1-tile_size_output_512] 39.94 11.04
test_gemv[M_2048-K_8192-num_aie_columns_8-tile_size_input_1-tile_size_output_256] 37.89 - -
test_gemv[M_8192-K_2048-num_aie_columns_1-tile_size_input_4-tile_size_output_1024] 11.95 3.69
test_gemv[M_8192-K_2048-num_aie_columns_2-tile_size_input_4-tile_size_output_1024] 24.25 6.74
test_gemv[M_8192-K_2048-num_aie_columns_4-tile_size_input_4-tile_size_output_1024] 39.75 11.80
test_gemv[M_8192-K_2048-num_aie_columns_8-tile_size_input_4-tile_size_output_1024] 41.26 - -
test_gemv_batched[M_1024-K_1024-num_aie_columns_1-tile_size_input_1-tile_size_output_64-num_batches_2] 8.87 2.51
test_gemv_batched[M_1026-K_64-num_aie_columns_1-tile_size_input_1-tile_size_output_2-num_batches_2] 0.90 0.27
test_gemv_batched[M_256-K_128-num_aie_columns_1-tile_size_input_1-tile_size_output_256-num_batches_4] 1.17 0.44
test_gemv_batched[M_256-K_128-num_aie_columns_8-tile_size_input_1-tile_size_output_32-num_batches_100] 17.42 - -
test_gemv_batched[M_448-K_64-num_aie_columns_8-tile_size_input_1-tile_size_output_56-num_batches_192] 12.66 - -
test_gemv_batched[M_512-K_64-num_aie_columns_8-tile_size_input_4-tile_size_output_64-num_batches_32] 7.98 - -
test_gemv_batched[M_64-K_1536-num_aie_columns_1-tile_size_input_1-tile_size_output_64-num_batches_8] 5.54 1.84
test_gemv_gelu[M_128-K_128-num_aie_columns_1-tile_size_input_32-tile_size_output_128] 0.19 -
test_gemv_gelu[M_2048-K_8192-num_aie_columns_1-tile_size_input_1-tile_size_output_2048] 12.34 -
test_gemv_gelu[M_8192-K_2048-num_aie_columns_1-tile_size_input_4-tile_size_output_1024] 12.68 -
iron/operators/layer_norm
Test Krackan Status Krackan Latency (mean) Phoenix Status Phoenix Latency (mean)
test_layer_norm[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048] 175.64 269.56
test_layer_norm[input_length_2048-num_aie_columns_1-num_channels_2-tile_size_1024] 181.28 263.76
test_layer_norm[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024] 216.62 282.44
test_layer_norm[input_length_2048-num_aie_columns_2-num_channels_2-tile_size_512] 182.66 361.92
test_layer_norm[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512] 187.50 326.74
test_layer_norm[input_length_2048-num_aie_columns_4-num_channels_2-tile_size_256] 187.92 438.98
test_layer_norm[input_length_2048-num_aie_columns_8-num_channels_1-tile_size_256] 240.36 - -
test_layer_norm[input_length_2048-num_aie_columns_8-num_channels_2-tile_size_128] 229.72 - -
iron/operators/leaky_relu
Test Krackan Status Krackan Latency (mean) Phoenix Status Phoenix Latency (mean)
test_leaky_relu[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048-alpha_0.01] 143.74 339.76
test_leaky_relu[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048-alpha_0.1] 168.50 403.10
test_leaky_relu[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048-alpha_0.25] 171.68 676.26
test_leaky_relu[input_length_2048-num_aie_columns_1-num_channels_2-tile_size_1024-alpha_0.01] 146.02 426.42
test_leaky_relu[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024-alpha_0.01] 161.80 447.10
test_leaky_relu[input_length_2048-num_aie_columns_2-num_channels_2-tile_size_512-alpha_0.01] 187.76 504.80
test_leaky_relu[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512-alpha_0.01] 176.70 458.66
test_leaky_relu[input_length_2048-num_aie_columns_4-num_channels_2-tile_size_256-alpha_0.01] 170.74 421.40
test_leaky_relu[input_length_2048-num_aie_columns_8-num_channels_1-tile_size_256-alpha_0.01] 172.76 - -
test_leaky_relu[input_length_2048-num_aie_columns_8-num_channels_2-tile_size_128-alpha_0.01] 196.16 - -
iron/operators/mem_copy
Test Krackan Status Krackan Latency (mean) Phoenix Status Phoenix Latency (mean)
test_mem_copy[input_length_2048-num_cores_1-num_channels_1-bypass_False-tile_size_2048] 152.60 367.88
test_mem_copy[input_length_2048-num_cores_16-num_channels_2-bypass_False-tile_size_128] 225.44 - -
test_mem_copy[input_length_2048-num_cores_2-num_channels_1-bypass_False-tile_size_1024] 182.10 629.32
test_mem_copy[input_length_2048-num_cores_2-num_channels_2-bypass_False-tile_size_1024] 198.62 337.10
test_mem_copy[input_length_2048-num_cores_4-num_channels_1-bypass_False-tile_size_512] 151.98 393.78
test_mem_copy[input_length_2048-num_cores_4-num_channels_2-bypass_False-tile_size_512] 162.66 390.18
test_mem_copy[input_length_2048-num_cores_8-num_channels_1-bypass_False-tile_size_256] 160.52 - -
test_mem_copy[input_length_2048-num_cores_8-num_channels_2-bypass_False-tile_size_256] 187.82 473.94
iron/operators/mha
Test Krackan Status Krackan Latency (mean) Phoenix Status Phoenix Latency (mean)
test_mha[seq_len_16384-dim_64-num_heads_1-num_pipelines_8-num_kv_heads_0] 47495.48 - -
iron/operators/relu
Test Krackan Status Krackan Latency (mean) Phoenix Status Phoenix Latency (mean)
test_relu[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048] 154.52 347.58
test_relu[input_length_2048-num_aie_columns_1-num_channels_2-tile_size_1024] 155.00 326.26
test_relu[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024] 176.48 452.80
test_relu[input_length_2048-num_aie_columns_2-num_channels_2-tile_size_512] 191.92 413.50
test_relu[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512] 178.30 337.84
test_relu[input_length_2048-num_aie_columns_4-num_channels_2-tile_size_256] 170.50 397.34
test_relu[input_length_2048-num_aie_columns_8-num_channels_1-tile_size_256] 185.44 - -
test_relu[input_length_2048-num_aie_columns_8-num_channels_2-tile_size_128] 198.54 - -
iron/operators/repeat
Test Krackan Status Krackan Latency (mean) Phoenix Status Phoenix Latency (mean)
test_cols_without_a_legal_split_is_rejected[cols_1031-why_prime > 1023: the only divisors are 1 and cols, neither legal] - -
test_cols_without_a_legal_split_is_rejected[cols_2062-why_2 x 1031: the only word-aligned chunk leaves a 1031-wide chunk count] - -
test_cols_without_a_legal_split_is_rejected[cols_513-why_odd: every divisor is odd, so no chunk is a whole 32-bit word] - -
test_repeat[rows_4-cols_1024-repeat_2-transfer_size_None] 165.10 251.90
test_repeat[rows_8-cols_512-repeat_4-transfer_size_64] 172.96 395.52
test_repeat[rows_8-cols_64-repeat_4-transfer_size_None] 171.04 334.42
iron/operators/rms_norm
Test Krackan Status Krackan Latency (mean) Phoenix Status Phoenix Latency (mean)
test_rms_norm[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048-weighted_False] 164.42 334.64
test_rms_norm[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048-weighted_True] 164.40 365.22
test_rms_norm[input_length_2048-num_aie_columns_1-num_channels_2-tile_size_1024-weighted_False] 165.00 385.36
test_rms_norm[input_length_2048-num_aie_columns_1-num_channels_2-tile_size_1024-weighted_True] 161.82 773.16
test_rms_norm[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024-weighted_False] 166.42 368.10
test_rms_norm[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024-weighted_True] 177.26 335.36
test_rms_norm[input_length_2048-num_aie_columns_2-num_channels_2-tile_size_512-weighted_False] 177.94 515.80
test_rms_norm[input_length_2048-num_aie_columns_2-num_channels_2-tile_size_512-weighted_True] 182.78 271.30
test_rms_norm[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512-weighted_False] 172.08 482.98
test_rms_norm[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512-weighted_True] 181.36 414.00
test_rms_norm[input_length_2048-num_aie_columns_4-num_channels_2-tile_size_256-weighted_False] 188.94 453.40
test_rms_norm[input_length_2048-num_aie_columns_4-num_channels_2-tile_size_256-weighted_True] 209.84 - -
test_rms_norm[input_length_2048-num_aie_columns_8-num_channels_1-tile_size_256-weighted_False] 185.08 - -
test_rms_norm[input_length_2048-num_aie_columns_8-num_channels_1-tile_size_256-weighted_True] 206.76 - -
test_rms_norm[input_length_2048-num_aie_columns_8-num_channels_2-tile_size_128-weighted_False] 214.40 - -
iron/operators/rope
Test Krackan Status Krackan Latency (mean) Phoenix Status Phoenix Latency (mean)
test_rope[rows_32-cols_512-angle_rows_32-aie_columns_1-method_type_0] 178.52 690.56
test_rope[rows_32-cols_512-angle_rows_32-aie_columns_2-method_type_0] 176.90 489.36
test_rope[rows_32-cols_512-angle_rows_32-aie_columns_4-method_type_0] 156.50 459.50
test_rope[rows_32-cols_512-angle_rows_32-aie_columns_8-method_type_0] 239.18 - -
test_rope[rows_32-cols_512-angle_rows_8-aie_columns_1-method_type_0] 167.48 318.96
test_rope[rows_32-cols_512-angle_rows_8-aie_columns_2-method_type_0] 182.70 322.36
test_rope[rows_32-cols_512-angle_rows_8-aie_columns_4-method_type_0] 189.42 431.90
test_rope[rows_32-cols_512-angle_rows_8-aie_columns_8-method_type_0] 186.30 - -
iron/operators/sigmoid
Test Krackan Status Krackan Latency (mean) Phoenix Status Phoenix Latency (mean)
test_sigmoid[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048] 164.78 428.92
test_sigmoid[input_length_2048-num_aie_columns_1-num_channels_2-tile_size_1024] 171.96 320.46
test_sigmoid[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024] 162.12 402.28
test_sigmoid[input_length_2048-num_aie_columns_2-num_channels_2-tile_size_512] 165.26 540.52
test_sigmoid[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512] 159.16 864.08
test_sigmoid[input_length_2048-num_aie_columns_4-num_channels_2-tile_size_256] 193.86 535.74
test_sigmoid[input_length_2048-num_aie_columns_8-num_channels_1-tile_size_256] 176.86 - -
test_sigmoid[input_length_2048-num_aie_columns_8-num_channels_2-tile_size_128] 215.80 - -
iron/operators/silu
Test Krackan Status Krackan Latency (mean) Phoenix Status Phoenix Latency (mean)
test_silu[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048] 170.84 333.38
test_silu[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024] 188.88 538.18
test_silu[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512] 156.26 461.90
test_silu[input_length_2048-num_aie_columns_8-num_channels_1-tile_size_256] 187.94 - -
iron/operators/softmax
Test Krackan Status Krackan Latency (mean) Phoenix Status Phoenix Latency (mean)
test_softmax[input_length_32768-num_aie_columns_2-num_channels_2-tile_size_1024] 177.00 542.98
test_softmax[input_length_32768-num_aie_columns_2-num_channels_2-tile_size_2048] 190.08 572.64
test_softmax[input_length_32768-num_aie_columns_2-num_channels_2-tile_size_512] 178.34 490.30
iron/operators/strided_copy
Test Krackan Status Krackan Latency (mean) Phoenix Status Phoenix Latency (mean)
test_strided_copy[chunked_transfer] 175.48 278.72
test_strided_copy[contiguous] 175.70 417.70
test_strided_copy[four_channels] 182.56 737.60
test_strided_copy[kv_slot0] 163.80 274.46
test_strided_copy[kv_slot5] 163.40 359.04
test_strided_copy[kv_slot5_four_channels] 162.34 432.92
test_strided_copy[kv_slot5_two_channels] 142.94 341.88
test_strided_copy[kv_slot_last] 172.44 307.30
test_strided_copy[two_channels] 199.10 412.64
test_strided_copy[two_channels_chunked] 169.62 389.62
test_transfer_size_not_dividing_per_channel_share_is_rejected[iter0] - -
test_transfer_size_not_dividing_per_channel_share_is_rejected[iter1] - -
test_transfer_size_not_dividing_per_channel_share_is_rejected[iter2] - -
test_transfer_size_not_dividing_per_channel_share_is_rejected[iter3] - -
test_transfer_size_not_dividing_per_channel_share_is_rejected[iter4] - -
iron/operators/swiglu_decode
Test Krackan Status Krackan Latency (mean) Phoenix Status Phoenix Latency (mean)
test_swiglu_decode[embedding_dim_1024-hidden_dim_3584] 974.34 16685.17
test_swiglu_decode[embedding_dim_2048-hidden_dim_2048] 997.11 14249.28
iron/operators/swiglu_prefill
Test Krackan Status Krackan Latency (mean) Phoenix Status Phoenix Latency (mean)
test_swiglu_prefill[seq_len_256-embedding_dim_2048-hidden_dim_2048-prio_accuracy_False] 2188.58 24678.41
iron/operators/tanh
Test Krackan Status Krackan Latency (mean) Phoenix Status Phoenix Latency (mean)
test_tanh[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048] 177.14 372.08
test_tanh[input_length_2048-num_aie_columns_1-num_channels_2-tile_size_1024] 164.88 521.18
test_tanh[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024] 176.00 400.92
test_tanh[input_length_2048-num_aie_columns_2-num_channels_2-tile_size_512] 177.58 450.22
test_tanh[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512] 164.58 361.88
test_tanh[input_length_2048-num_aie_columns_4-num_channels_2-tile_size_256] 197.48 443.48
test_tanh[input_length_2048-num_aie_columns_8-num_channels_1-tile_size_256] 208.86 - -
test_tanh[input_length_2048-num_aie_columns_8-num_channels_2-tile_size_128] 220.36 - -
iron/operators/transpose
Test Krackan Status Krackan Latency (mean) Phoenix Status Phoenix Latency (mean)
test_transpose[M_2048-N_64-aie_columns_1-channels_1-m_64-n_64-s_8-num_batches_1] 183.88 572.86
test_transpose[M_2048-N_64-aie_columns_1-channels_1-m_64-n_64-s_8-num_batches_2] 218.98 1632.96
test_transpose[M_2048-N_64-aie_columns_1-channels_2-m_64-n_64-s_8-num_batches_1] 181.06 489.28
Krackan - Small

IRON

Tested on 2026_09_15_22_10_53 at commit bb0d09b.

iron/operators/axpy
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_axpy[input_length_2048-num_aie_columns_1-tile_size_2048-scalar_factor_3.0]✅ 5/5148.300.09n/a
test_axpy[input_length_2048-num_aie_columns_2-tile_size_1024-scalar_factor_3.0]✅ 5/5136.160.09n/a
test_axpy[input_length_2048-num_aie_columns_4-tile_size_512-scalar_factor_3.0]✅ 5/5161.000.08n/a
test_axpy[input_length_2048-num_aie_columns_8-tile_size_256-scalar_factor_3.0]✅ 5/5203.740.06n/a
iron/operators/dequant
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_dequant[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048-group_size_32]✅ 5/5157.680.03n/a
test_dequant[input_length_2048-num_aie_columns_1-num_channels_2-tile_size_1024-group_size_32]✅ 5/5157.100.03n/a
test_dequant[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024-group_size_32]✅ 5/5155.260.03n/a
test_dequant[input_length_2048-num_aie_columns_2-num_channels_2-tile_size_512-group_size_32]✅ 5/5160.720.03n/a
test_dequant[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512-group_size_32]✅ 5/5168.940.03n/a
test_dequant[input_length_2048-num_aie_columns_4-num_channels_2-tile_size_256-group_size_32]✅ 5/5167.980.03n/a
test_dequant[input_length_2048-num_aie_columns_8-num_channels_1-tile_size_256-group_size_32]✅ 5/5168.780.03n/a
test_dequant[input_length_2048-num_aie_columns_8-num_channels_2-tile_size_128-group_size_32]✅ 5/5220.440.02n/a
iron/operators/elementwise_add
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_elementwise_add[input_length_2048-num_aie_columns_1-tile_size_2048]✅ 5/5152.900.08n/a
test_elementwise_add[input_length_2048-num_aie_columns_2-tile_size_1024]✅ 5/5147.560.09n/a
test_elementwise_add[input_length_2048-num_aie_columns_4-tile_size_512]✅ 5/5158.520.08n/a
test_elementwise_add[input_length_2048-num_aie_columns_8-tile_size_256]✅ 5/5177.840.07n/a
iron/operators/elementwise_mul
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_elementwise_mul[input_length_2048-num_aie_columns_1-tile_size_2048]✅ 5/5162.280.08n/a
test_elementwise_mul[input_length_2048-num_aie_columns_2-tile_size_1024]✅ 5/5166.620.08n/a
test_elementwise_mul[input_length_2048-num_aie_columns_4-tile_size_512]✅ 5/5202.600.07n/a
test_elementwise_mul[input_length_2048-num_aie_columns_8-tile_size_256]✅ 5/5229.180.06n/a
iron/operators/flm/gemm
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_artifact_stem_differs_from_generic_gemm[M_256-K_512-N_1024]✅ 5/5n/an/an/a
test_artifact_stem_differs_from_generic_gemm[M_512-K_1024-N_2048]✅ 5/5n/an/an/a
test_gemm[M_256-K_512-N_1024-epilogue_gelu-clamp_None-rounding_conv_even]✅ 5/5460.563.02589.29
test_gemm[M_256-K_512-N_1024-epilogue_none-clamp_(-2.0, 2.0)-rounding_conv_even]✅ 5/5381.983.63708.48
test_gemm[M_256-K_512-N_1024-epilogue_none-clamp_None-rounding_conv_even]✅ 5/5315.824.54884.92
test_gemm[M_256-K_512-N_1024-epilogue_none-clamp_None-rounding_floor]✅ 5/5363.104.04787.02
test_gemm[M_256-K_512-N_1024-epilogue_silu-clamp_None-rounding_conv_even]✅ 5/5462.502.98581.49
test_gemm[M_256-K_512-N_128-epilogue_none-clamp_None-rounding_conv_even]✅ 5/5338.801.22102.05
test_gemm[M_256-K_512-N_1536-epilogue_none-clamp_None-rounding_conv_even]✅ 5/5396.625.021045.80
test_gemm[M_512-K_1024-N_2048-epilogue_none-clamp_None-rounding_conv_even]✅ 5/5463.1012.074707.30
test_gemm_split_leg_bounds[iter0]✅ 1/1n/an/an/a
test_gemm_split_leg_bounds[iter1]✅ 1/1n/an/an/a
test_gemm_split_leg_bounds[iter2]✅ 1/1n/an/an/a
test_gemm_split_leg_bounds[iter3]✅ 1/1n/an/an/a
test_gemm_split_leg_bounds[iter4]✅ 1/1n/an/an/a
test_gemm_split_leg_bounds_runs[iter0]✅ 1/1n/an/an/a
test_gemm_split_leg_bounds_runs[iter1]✅ 1/1n/an/an/a
test_gemm_split_leg_bounds_runs[iter2]✅ 1/1n/an/an/a
test_gemm_split_leg_bounds_runs[iter3]✅ 1/1n/an/an/a
test_gemm_split_leg_bounds_runs[iter4]✅ 1/1n/an/an/a
test_gemm_tile_options[tn128-ma64-default]✅ 5/5n/an/an/a
test_gemm_tile_options[tn16-ma64-default]✅ 5/5n/an/an/a
test_gemm_tile_options[tn32-ma64-default]✅ 5/5n/an/an/a
test_gemm_tile_options[tn64-ma32-default]✅ 5/5n/an/an/a
test_one_xclbin_serves_every_clamp_bound[iter0]✅ 1/1n/an/an/a
test_one_xclbin_serves_every_clamp_bound[iter1]✅ 1/1n/an/an/a
test_one_xclbin_serves_every_clamp_bound[iter2]✅ 1/1n/an/an/a
test_one_xclbin_serves_every_clamp_bound[iter3]✅ 1/1n/an/an/a
test_one_xclbin_serves_every_clamp_bound[iter4]✅ 1/1n/an/an/a
test_one_xclbin_serves_every_shape[iter0]✅ 1/1n/an/an/a
test_one_xclbin_serves_every_shape[iter1]✅ 1/1n/an/an/a
test_one_xclbin_serves_every_shape[iter2]✅ 1/1n/an/an/a
test_one_xclbin_serves_every_shape[iter3]✅ 1/1n/an/an/a
test_one_xclbin_serves_every_shape[iter4]✅ 1/1n/an/an/a
iron/operators/gelu
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_gelu[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048]✅ 5/5193.040.04n/a
test_gelu[input_length_2048-num_aie_columns_1-num_channels_2-tile_size_1024]✅ 5/5174.820.05n/a
test_gelu[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024]✅ 5/5177.780.05n/a
test_gelu[input_length_2048-num_aie_columns_2-num_channels_2-tile_size_512]✅ 5/5189.080.04n/a
test_gelu[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512]✅ 5/5178.480.05n/a
test_gelu[input_length_2048-num_aie_columns_4-num_channels_2-tile_size_256]✅ 5/5196.500.04n/a
test_gelu[input_length_2048-num_aie_columns_8-num_channels_1-tile_size_256]✅ 5/5167.700.05n/a
test_gelu[input_length_2048-num_aie_columns_8-num_channels_2-tile_size_128]✅ 5/5205.120.04n/a
iron/operators/gemm
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_gemm[M_1792-K_896-N_1152-num_aie_columns_8-b_col_maj_False-c_col_maj_True-m_64-k_32-n_48-trace_size_0-partition_N_1]✅ 5/52243.644.191649.25
test_gemm[M_192-K_384-N_64-num_aie_columns_4-b_col_maj_False-c_col_maj_False-m_48-k_96-n_16-trace_size_0-partition_N_1]✅ 5/5193.861.1549.06
test_gemm[M_192-K_384-N_64-num_aie_columns_4-b_col_maj_True-c_col_maj_True-m_48-k_96-n_16-trace_size_0-partition_N_1]✅ 5/5210.981.0645.35
test_gemm[M_2048-K_2048-N_2048-num_aie_columns_1-b_col_maj_False-c_col_maj_False-m_64-k_64-n_64-trace_size_0-partition_N_1]✅ 5/547823.420.53359.24
test_gemm[M_2048-K_2048-N_2048-num_aie_columns_2-b_col_maj_True-c_col_maj_False-m_64-k_64-n_64-trace_size_0-partition_N_1]✅ 5/527921.000.90615.31
test_gemm[M_2048-K_2048-N_2048-num_aie_columns_8-b_col_maj_True-c_col_maj_True-m_64-k_64-n_64-trace_size_0-partition_N_1]✅ 5/57713.583.262228.72
test_gemm[M_384-K_1536-N_1792-num_aie_columns_4-b_col_maj_True-c_col_maj_False-m_32-k_48-n_64-trace_size_0-partition_N_1]✅ 5/52200.063.74980.37
test_gemm[M_64-K_512-N_256-num_aie_columns_4-b_col_maj_True-c_col_maj_False-m_16-k_64-n_64-trace_size_0-partition_N_4]✅ 5/53508.340.3719.74
test_gemm[M_896-K_1792-N_640-num_aie_columns_8-b_col_maj_False-c_col_maj_True-m_32-k_64-n_80-trace_size_0-partition_N_1]✅ 5/51605.544.241308.77
iron/operators/gemv
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_gemv[M_128-K_128-num_aie_columns_1-tile_size_input_32-tile_size_output_128]✅ 5/5n/a0.190.19
test_gemv[M_2048-K_8192-num_aie_columns_1-tile_size_input_1-tile_size_output_2048]✅ 5/5n/a12.4812.47
test_gemv[M_2048-K_8192-num_aie_columns_2-tile_size_input_1-tile_size_output_1024]✅ 5/5n/a23.9523.94
test_gemv[M_2048-K_8192-num_aie_columns_4-tile_size_input_1-tile_size_output_512]✅ 5/5n/a39.9439.92
test_gemv[M_2048-K_8192-num_aie_columns_8-tile_size_input_1-tile_size_output_256]✅ 5/5n/a37.8937.87
test_gemv[M_8192-K_2048-num_aie_columns_1-tile_size_input_4-tile_size_output_1024]✅ 5/5n/a11.9511.95
test_gemv[M_8192-K_2048-num_aie_columns_2-tile_size_input_4-tile_size_output_1024]✅ 5/5n/a24.2524.23
test_gemv[M_8192-K_2048-num_aie_columns_4-tile_size_input_4-tile_size_output_1024]✅ 5/5n/a39.7539.73
test_gemv[M_8192-K_2048-num_aie_columns_8-tile_size_input_4-tile_size_output_1024]✅ 5/5n/a41.2641.23
test_gemv_batched[M_1024-K_1024-num_aie_columns_1-tile_size_input_1-tile_size_output_64-num_batches_2]✅ 5/5n/a8.878.86
test_gemv_batched[M_1026-K_64-num_aie_columns_1-tile_size_input_1-tile_size_output_2-num_batches_2]✅ 5/5n/a0.900.89
test_gemv_batched[M_256-K_128-num_aie_columns_1-tile_size_input_1-tile_size_output_256-num_batches_4]✅ 5/5n/a1.171.16
test_gemv_batched[M_256-K_128-num_aie_columns_8-tile_size_input_1-tile_size_output_32-num_batches_100]✅ 5/5n/a17.4217.21
test_gemv_batched[M_448-K_64-num_aie_columns_8-tile_size_input_1-tile_size_output_56-num_batches_192]✅ 5/5n/a12.6612.44
test_gemv_batched[M_512-K_64-num_aie_columns_8-tile_size_input_4-tile_size_output_64-num_batches_32]✅ 5/5n/a7.987.84
test_gemv_batched[M_64-K_1536-num_aie_columns_1-tile_size_input_1-tile_size_output_64-num_batches_8]✅ 5/5n/a5.545.45
test_gemv_gelu[M_128-K_128-num_aie_columns_1-tile_size_input_32-tile_size_output_128]✅ 5/5n/a0.190.19
test_gemv_gelu[M_2048-K_8192-num_aie_columns_1-tile_size_input_1-tile_size_output_2048]✅ 5/5n/a12.3412.33
test_gemv_gelu[M_8192-K_2048-num_aie_columns_1-tile_size_input_4-tile_size_output_1024]✅ 5/5n/a12.6812.67
iron/operators/layer_norm
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_layer_norm[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048]✅ 5/5175.640.05n/a
test_layer_norm[input_length_2048-num_aie_columns_1-num_channels_2-tile_size_1024]✅ 5/5181.280.05n/a
test_layer_norm[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024]✅ 5/5216.620.04n/a
test_layer_norm[input_length_2048-num_aie_columns_2-num_channels_2-tile_size_512]✅ 5/5182.660.05n/a
test_layer_norm[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512]✅ 5/5187.500.05n/a
test_layer_norm[input_length_2048-num_aie_columns_4-num_channels_2-tile_size_256]✅ 5/5187.920.05n/a
test_layer_norm[input_length_2048-num_aie_columns_8-num_channels_1-tile_size_256]✅ 5/5240.360.04n/a
test_layer_norm[input_length_2048-num_aie_columns_8-num_channels_2-tile_size_128]✅ 5/5229.720.04n/a
iron/operators/leaky_relu
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_leaky_relu[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048-alpha_0.01]✅ 5/5143.740.06n/a
test_leaky_relu[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048-alpha_0.1]✅ 5/5168.500.05n/a
test_leaky_relu[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048-alpha_0.25]✅ 5/5171.680.05n/a
test_leaky_relu[input_length_2048-num_aie_columns_1-num_channels_2-tile_size_1024-alpha_0.01]✅ 5/5146.020.06n/a
test_leaky_relu[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024-alpha_0.01]✅ 5/5161.800.05n/a
test_leaky_relu[input_length_2048-num_aie_columns_2-num_channels_2-tile_size_512-alpha_0.01]✅ 5/5187.760.05n/a
test_leaky_relu[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512-alpha_0.01]✅ 5/5176.700.05n/a
test_leaky_relu[input_length_2048-num_aie_columns_4-num_channels_2-tile_size_256-alpha_0.01]✅ 5/5170.740.05n/a
test_leaky_relu[input_length_2048-num_aie_columns_8-num_channels_1-tile_size_256-alpha_0.01]✅ 5/5172.760.05n/a
test_leaky_relu[input_length_2048-num_aie_columns_8-num_channels_2-tile_size_128-alpha_0.01]✅ 5/5196.160.04n/a
iron/operators/mem_copy
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_mem_copy[input_length_2048-num_cores_1-num_channels_1-bypass_False-tile_size_2048]✅ 5/5152.600.05n/a
test_mem_copy[input_length_2048-num_cores_16-num_channels_2-bypass_False-tile_size_128]✅ 5/5225.440.04n/a
test_mem_copy[input_length_2048-num_cores_2-num_channels_1-bypass_False-tile_size_1024]✅ 5/5182.100.05n/a
test_mem_copy[input_length_2048-num_cores_2-num_channels_2-bypass_False-tile_size_1024]✅ 5/5198.620.05n/a
test_mem_copy[input_length_2048-num_cores_4-num_channels_1-bypass_False-tile_size_512]✅ 5/5151.980.06n/a
test_mem_copy[input_length_2048-num_cores_4-num_channels_2-bypass_False-tile_size_512]✅ 5/5162.660.05n/a
test_mem_copy[input_length_2048-num_cores_8-num_channels_1-bypass_False-tile_size_256]✅ 5/5160.520.05n/a
test_mem_copy[input_length_2048-num_cores_8-num_channels_2-bypass_False-tile_size_256]✅ 5/5187.820.04n/a
iron/operators/mha
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_mha[seq_len_16384-dim_64-num_heads_1-num_pipelines_8-num_kv_heads_0]✅ 5/547495.480.18n/a
iron/operators/relu
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_relu[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048]✅ 5/5154.520.05n/a
test_relu[input_length_2048-num_aie_columns_1-num_channels_2-tile_size_1024]✅ 5/5155.000.06n/a
test_relu[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024]✅ 5/5176.480.05n/a
test_relu[input_length_2048-num_aie_columns_2-num_channels_2-tile_size_512]✅ 5/5191.920.04n/a
test_relu[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512]✅ 5/5178.300.05n/a
test_relu[input_length_2048-num_aie_columns_4-num_channels_2-tile_size_256]✅ 5/5170.500.05n/a
test_relu[input_length_2048-num_aie_columns_8-num_channels_1-tile_size_256]✅ 5/5185.440.04n/a
test_relu[input_length_2048-num_aie_columns_8-num_channels_2-tile_size_128]✅ 5/5198.540.04n/a
iron/operators/repeat
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_cols_without_a_legal_split_is_rejected[cols_1031-why_prime > 1023: the only divisors are 1 and cols, neither legal]✅ 5/5n/an/an/a
test_cols_without_a_legal_split_is_rejected[cols_2062-why_2 x 1031: the only word-aligned chunk leaves a 1031-wide chunk count]✅ 5/5n/an/an/a
test_cols_without_a_legal_split_is_rejected[cols_513-why_odd: every divisor is odd, so no chunk is a whole 32-bit word]✅ 5/5n/an/an/a
test_repeat[rows_4-cols_1024-repeat_2-transfer_size_None]✅ 5/5165.100.15n/a
test_repeat[rows_8-cols_512-repeat_4-transfer_size_64]✅ 5/5172.960.24n/a
test_repeat[rows_8-cols_64-repeat_4-transfer_size_None]✅ 5/5171.040.03n/a
iron/operators/rms_norm
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_rms_norm[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048-weighted_False]✅ 5/5164.420.05n/a
test_rms_norm[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048-weighted_True]✅ 5/5164.400.08n/a
test_rms_norm[input_length_2048-num_aie_columns_1-num_channels_2-tile_size_1024-weighted_False]✅ 5/5165.000.05n/a
test_rms_norm[input_length_2048-num_aie_columns_1-num_channels_2-tile_size_1024-weighted_True]✅ 5/5161.820.06n/a
test_rms_norm[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024-weighted_False]✅ 5/5166.420.05n/a
test_rms_norm[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024-weighted_True]✅ 5/5177.260.06n/a
test_rms_norm[input_length_2048-num_aie_columns_2-num_channels_2-tile_size_512-weighted_False]✅ 5/5177.940.05n/a
test_rms_norm[input_length_2048-num_aie_columns_2-num_channels_2-tile_size_512-weighted_True]✅ 5/5182.780.05n/a
test_rms_norm[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512-weighted_False]✅ 5/5172.080.05n/a
test_rms_norm[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512-weighted_True]✅ 5/5181.360.05n/a
test_rms_norm[input_length_2048-num_aie_columns_4-num_channels_2-tile_size_256-weighted_False]✅ 5/5188.940.05n/a
test_rms_norm[input_length_2048-num_aie_columns_4-num_channels_2-tile_size_256-weighted_True]✅ 5/5209.840.04n/a
test_rms_norm[input_length_2048-num_aie_columns_8-num_channels_1-tile_size_256-weighted_False]✅ 5/5185.080.04n/a
test_rms_norm[input_length_2048-num_aie_columns_8-num_channels_1-tile_size_256-weighted_True]✅ 5/5206.760.04n/a
test_rms_norm[input_length_2048-num_aie_columns_8-num_channels_2-tile_size_128-weighted_False]✅ 5/5214.400.04n/a
iron/operators/rope
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_rope[rows_32-cols_512-angle_rows_32-aie_columns_1-method_type_0]✅ 5/5178.520.57n/a
test_rope[rows_32-cols_512-angle_rows_32-aie_columns_2-method_type_0]✅ 5/5176.900.57n/a
test_rope[rows_32-cols_512-angle_rows_32-aie_columns_4-method_type_0]✅ 5/5156.500.64n/a
test_rope[rows_32-cols_512-angle_rows_32-aie_columns_8-method_type_0]✅ 5/5239.180.44n/a
test_rope[rows_32-cols_512-angle_rows_8-aie_columns_1-method_type_0]✅ 5/5167.480.44n/a
test_rope[rows_32-cols_512-angle_rows_8-aie_columns_2-method_type_0]✅ 5/5182.700.43n/a
test_rope[rows_32-cols_512-angle_rows_8-aie_columns_4-method_type_0]✅ 5/5189.420.40n/a
test_rope[rows_32-cols_512-angle_rows_8-aie_columns_8-method_type_0]✅ 5/5186.300.41n/a
iron/operators/sigmoid
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_sigmoid[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048]✅ 5/5164.780.05n/a
test_sigmoid[input_length_2048-num_aie_columns_1-num_channels_2-tile_size_1024]✅ 5/5171.960.05n/a
test_sigmoid[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024]✅ 5/5162.120.05n/a
test_sigmoid[input_length_2048-num_aie_columns_2-num_channels_2-tile_size_512]✅ 5/5165.260.05n/a
test_sigmoid[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512]✅ 5/5159.160.05n/a
test_sigmoid[input_length_2048-num_aie_columns_4-num_channels_2-tile_size_256]✅ 5/5193.860.05n/a
test_sigmoid[input_length_2048-num_aie_columns_8-num_channels_1-tile_size_256]✅ 5/5176.860.05n/a
test_sigmoid[input_length_2048-num_aie_columns_8-num_channels_2-tile_size_128]✅ 5/5215.800.04n/a
iron/operators/silu
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_silu[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048]✅ 5/5170.840.05n/a
test_silu[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024]✅ 5/5188.880.04n/a
test_silu[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512]✅ 5/5156.260.05n/a
test_silu[input_length_2048-num_aie_columns_8-num_channels_1-tile_size_256]✅ 5/5187.940.04n/a
iron/operators/softmax
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_softmax[input_length_32768-num_aie_columns_2-num_channels_2-tile_size_1024]✅ 5/5177.000.74n/a
test_softmax[input_length_32768-num_aie_columns_2-num_channels_2-tile_size_2048]✅ 5/5190.080.70n/a
test_softmax[input_length_32768-num_aie_columns_2-num_channels_2-tile_size_512]✅ 5/5178.340.74n/a
iron/operators/strided_copy
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_strided_copy[chunked_transfer]✅ 5/5175.480.02n/a
test_strided_copy[contiguous]✅ 5/5175.700.02n/a
test_strided_copy[four_channels]✅ 5/5182.560.02n/a
test_strided_copy[kv_slot0]✅ 5/5163.800.81n/a
test_strided_copy[kv_slot5]✅ 5/5163.400.82n/a
test_strided_copy[kv_slot5_four_channels]✅ 5/5162.340.83n/a
test_strided_copy[kv_slot5_two_channels]✅ 5/5142.940.95n/a
test_strided_copy[kv_slot_last]✅ 5/5172.440.77n/a
test_strided_copy[two_channels]✅ 5/5199.100.02n/a
test_strided_copy[two_channels_chunked]✅ 5/5169.620.02n/a
test_transfer_size_not_dividing_per_channel_share_is_rejected[iter0]✅ 1/1n/an/an/a
test_transfer_size_not_dividing_per_channel_share_is_rejected[iter1]✅ 1/1n/an/an/a
test_transfer_size_not_dividing_per_channel_share_is_rejected[iter2]✅ 1/1n/an/an/a
test_transfer_size_not_dividing_per_channel_share_is_rejected[iter3]✅ 1/1n/an/an/a
test_transfer_size_not_dividing_per_channel_share_is_rejected[iter4]✅ 1/1n/an/an/a
iron/operators/swiglu_decode
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_swiglu_decode[embedding_dim_1024-hidden_dim_3584]✅ 5/5974.340.00n/a
test_swiglu_decode[embedding_dim_2048-hidden_dim_2048]✅ 5/5997.110.01n/a
iron/operators/swiglu_prefill
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_swiglu_prefill[seq_len_256-embedding_dim_2048-hidden_dim_2048-prio_accuracy_False]✅ 5/52188.580.96n/a
iron/operators/tanh
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_tanh[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048]✅ 5/5177.140.05n/a
test_tanh[input_length_2048-num_aie_columns_1-num_channels_2-tile_size_1024]✅ 5/5164.880.05n/a
test_tanh[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024]✅ 5/5176.000.05n/a
test_tanh[input_length_2048-num_aie_columns_2-num_channels_2-tile_size_512]✅ 5/5177.580.05n/a
test_tanh[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512]✅ 5/5164.580.05n/a
test_tanh[input_length_2048-num_aie_columns_4-num_channels_2-tile_size_256]✅ 5/5197.480.05n/a
test_tanh[input_length_2048-num_aie_columns_8-num_channels_1-tile_size_256]✅ 5/5208.860.04n/a
test_tanh[input_length_2048-num_aie_columns_8-num_channels_2-tile_size_128]✅ 5/5220.360.04n/a
iron/operators/transpose
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_transpose[M_2048-N_64-aie_columns_1-channels_1-m_64-n_64-s_8-num_batches_1]✅ 5/5183.882.94n/a
test_transpose[M_2048-N_64-aie_columns_1-channels_1-m_64-n_64-s_8-num_batches_2]✅ 5/5218.984.82n/a
test_transpose[M_2048-N_64-aie_columns_1-channels_2-m_64-n_64-s_8-num_batches_1]✅ 5/5181.062.91n/a
Krackan - Examples

IRON

Tested on 2026_09_15_22_18_13 at commit bb0d09b.

iron/applications/llama_3.2_1b
TestChecksTTFT (mean)TPS (mean)
test_llama_3_2_1b[llama_3.2_1b_prompt_1024_tokens_1]✅ 5/52.07n/a
test_llama_3_2_1b[llama_3.2_1b_prompt_1024_tokens_40]✅ 5/52.097.83
test_llama_3_2_1b[llama_3.2_1b_prompt_13_tokens_1]✅ 5/52.03n/a
test_llama_3_2_1b[llama_3.2_1b_prompt_13_tokens_40]✅ 5/52.027.63
Phoenix - Small

IRON

Tested on 2026_09_15_22_09_41 at commit bb0d09b.

iron/operators/axpy
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_axpy[input_length_2048-num_aie_columns_1-tile_size_2048-scalar_factor_3.0]✅ 5/5415.980.03n/a
test_axpy[input_length_2048-num_aie_columns_2-tile_size_1024-scalar_factor_3.0]✅ 5/5414.160.03n/a
test_axpy[input_length_2048-num_aie_columns_4-tile_size_512-scalar_factor_3.0]✅ 5/5524.500.02n/a
iron/operators/dequant
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_dequant[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048-group_size_32]✅ 5/5397.560.01n/a
test_dequant[input_length_2048-num_aie_columns_1-num_channels_2-tile_size_1024-group_size_32]✅ 5/5448.880.01n/a
test_dequant[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024-group_size_32]✅ 5/5454.260.01n/a
test_dequant[input_length_2048-num_aie_columns_2-num_channels_2-tile_size_512-group_size_32]✅ 5/5487.240.01n/a
test_dequant[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512-group_size_32]✅ 5/5380.980.01n/a
test_dequant[input_length_2048-num_aie_columns_4-num_channels_2-tile_size_256-group_size_32]✅ 5/5481.620.01n/a
iron/operators/elementwise_add
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_elementwise_add[input_length_2048-num_aie_columns_1-tile_size_2048]✅ 5/5497.480.03n/a
test_elementwise_add[input_length_2048-num_aie_columns_2-tile_size_1024]✅ 5/5846.580.02n/a
test_elementwise_add[input_length_2048-num_aie_columns_4-tile_size_512]✅ 5/5543.880.02n/a
iron/operators/elementwise_mul
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_elementwise_mul[input_length_2048-num_aie_columns_1-tile_size_2048]✅ 5/5332.940.04n/a
test_elementwise_mul[input_length_2048-num_aie_columns_2-tile_size_1024]✅ 5/5442.540.03n/a
test_elementwise_mul[input_length_2048-num_aie_columns_4-tile_size_512]✅ 5/5418.380.03n/a
iron/operators/flm/gemm
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_artifact_stem_differs_from_generic_gemm[M_256-K_512-N_1024]✅ 5/5n/an/an/a
test_artifact_stem_differs_from_generic_gemm[M_512-K_1024-N_2048]✅ 5/5n/an/an/a
test_gemm[M_256-K_512-N_128-epilogue_none-clamp_None-rounding_conv_even]✅ 5/5737.460.6849.99
test_gemm[M_256-K_512-N_256-epilogue_none-clamp_None-rounding_conv_even]✅ 5/5864.921.04106.28
test_gemm[M_256-K_512-N_320-epilogue_none-clamp_None-rounding_conv_even]✅ 5/5736.981.05116.64
test_gemm[M_256-K_512-N_512-epilogue_gelu-clamp_None-rounding_conv_even]✅ 5/51010.801.20153.13
test_gemm[M_256-K_512-N_512-epilogue_none-clamp_(-2.0, 2.0)-rounding_conv_even]✅ 5/51020.821.35173.35
test_gemm[M_256-K_512-N_512-epilogue_none-clamp_None-rounding_floor]✅ 5/5939.961.36173.88
test_gemm[M_256-K_512-N_512-epilogue_silu-clamp_None-rounding_conv_even]✅ 5/51048.061.25160.21
test_gemm[M_256-K_512-N_64-epilogue_none-clamp_None-rounding_conv_even]✅ 5/5640.900.5927.26
test_gemm[M_512-K_1024-N_512-epilogue_none-clamp_None-rounding_conv_even]✅ 5/51909.401.65337.56
test_gemm_split_leg_bounds[iter0]✅ 1/1n/an/an/a
test_gemm_split_leg_bounds[iter1]✅ 1/1n/an/an/a
test_gemm_split_leg_bounds[iter2]✅ 1/1n/an/an/a
test_gemm_split_leg_bounds[iter3]✅ 1/1n/an/an/a
test_gemm_split_leg_bounds[iter4]✅ 1/1n/an/an/a
test_gemm_split_leg_bounds_runs[iter0]✅ 1/1n/an/an/a
test_gemm_split_leg_bounds_runs[iter1]✅ 1/1n/an/an/a
test_gemm_split_leg_bounds_runs[iter2]✅ 1/1n/an/an/a
test_gemm_split_leg_bounds_runs[iter3]✅ 1/1n/an/an/a
test_gemm_split_leg_bounds_runs[iter4]✅ 1/1n/an/an/a
test_gemm_tile_options[tn128-ma64-default]✅ 5/5n/an/an/a
test_gemm_tile_options[tn16-ma64-default]✅ 5/5n/an/an/a
test_gemm_tile_options[tn32-ma64-default]✅ 5/5n/an/an/a
test_gemm_tile_options[tn64-ma16-default]✅ 5/5n/an/an/a
test_one_xclbin_serves_every_clamp_bound[iter0]✅ 1/1n/an/an/a
test_one_xclbin_serves_every_clamp_bound[iter1]✅ 1/1n/an/an/a
test_one_xclbin_serves_every_clamp_bound[iter2]✅ 1/1n/an/an/a
test_one_xclbin_serves_every_clamp_bound[iter3]✅ 1/1n/an/an/a
test_one_xclbin_serves_every_clamp_bound[iter4]✅ 1/1n/an/an/a
test_one_xclbin_serves_every_shape[iter0]✅ 1/1n/an/an/a
test_one_xclbin_serves_every_shape[iter1]✅ 1/1n/an/an/a
test_one_xclbin_serves_every_shape[iter2]✅ 1/1n/an/an/a
test_one_xclbin_serves_every_shape[iter3]✅ 1/1n/an/an/a
test_one_xclbin_serves_every_shape[iter4]✅ 1/1n/an/an/a
iron/operators/gelu
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_gelu[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048]✅ 5/5383.360.02n/a
test_gelu[input_length_2048-num_aie_columns_1-num_channels_2-tile_size_1024]✅ 5/5428.100.02n/a
test_gelu[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024]✅ 5/5464.020.02n/a
test_gelu[input_length_2048-num_aie_columns_2-num_channels_2-tile_size_512]✅ 5/5651.320.02n/a
test_gelu[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512]✅ 5/5425.320.02n/a
test_gelu[input_length_2048-num_aie_columns_4-num_channels_2-tile_size_256]✅ 5/5427.720.02n/a
iron/operators/gemm
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_gemm[M_192-K_384-N_64-num_aie_columns_4-b_col_maj_False-c_col_maj_False-m_48-k_96-n_16-trace_size_0-partition_N_1]✅ 5/5912.540.2912.55
test_gemm[M_192-K_384-N_64-num_aie_columns_4-b_col_maj_True-c_col_maj_True-m_48-k_96-n_16-trace_size_0-partition_N_1]✅ 5/5980.860.3414.37
test_gemm[M_2048-K_2048-N_2048-num_aie_columns_1-b_col_maj_False-c_col_maj_False-m_64-k_64-n_64-trace_size_0-partition_N_1]✅ 5/582749.560.30207.68
test_gemm[M_2048-K_2048-N_2048-num_aie_columns_2-b_col_maj_True-c_col_maj_False-m_64-k_64-n_64-trace_size_0-partition_N_1]✅ 5/521930.581.15783.44
test_gemm[M_384-K_1536-N_1792-num_aie_columns_4-b_col_maj_True-c_col_maj_False-m_32-k_48-n_64-trace_size_0-partition_N_1]✅ 5/54093.602.28599.10
test_gemm[M_64-K_512-N_256-num_aie_columns_4-b_col_maj_True-c_col_maj_False-m_16-k_64-n_64-trace_size_0-partition_N_4]✅ 5/55532.540.2412.82
iron/operators/gemv
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_gemv[M_128-K_128-num_aie_columns_1-tile_size_input_32-tile_size_output_128]✅ 5/5n/a0.100.09
test_gemv[M_2048-K_8192-num_aie_columns_1-tile_size_input_1-tile_size_output_2048]✅ 5/5n/a3.613.60
test_gemv[M_2048-K_8192-num_aie_columns_2-tile_size_input_1-tile_size_output_1024]✅ 5/5n/a6.166.16
test_gemv[M_2048-K_8192-num_aie_columns_4-tile_size_input_1-tile_size_output_512]✅ 5/5n/a11.0411.03
test_gemv[M_8192-K_2048-num_aie_columns_1-tile_size_input_4-tile_size_output_1024]✅ 5/5n/a3.693.69
test_gemv[M_8192-K_2048-num_aie_columns_2-tile_size_input_4-tile_size_output_1024]✅ 5/5n/a6.746.73
test_gemv[M_8192-K_2048-num_aie_columns_4-tile_size_input_4-tile_size_output_1024]✅ 5/5n/a11.8011.80
test_gemv_batched[M_1024-K_1024-num_aie_columns_1-tile_size_input_1-tile_size_output_64-num_batches_2]✅ 5/5n/a2.512.50
test_gemv_batched[M_1026-K_64-num_aie_columns_1-tile_size_input_1-tile_size_output_2-num_batches_2]✅ 5/5n/a0.270.27
test_gemv_batched[M_256-K_128-num_aie_columns_1-tile_size_input_1-tile_size_output_256-num_batches_4]✅ 5/5n/a0.440.44
test_gemv_batched[M_64-K_1536-num_aie_columns_1-tile_size_input_1-tile_size_output_64-num_batches_8]✅ 5/5n/a1.841.81
test_gemv_gelu[M_128-K_128-num_aie_columns_1-tile_size_input_32-tile_size_output_128]❌ 0/5n/an/an/a
test_gemv_gelu[M_2048-K_8192-num_aie_columns_1-tile_size_input_1-tile_size_output_2048]❌ 0/5n/an/an/a
test_gemv_gelu[M_8192-K_2048-num_aie_columns_1-tile_size_input_4-tile_size_output_1024]❌ 0/5n/an/an/a
iron/operators/layer_norm
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_layer_norm[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048]✅ 5/5269.560.03n/a
test_layer_norm[input_length_2048-num_aie_columns_1-num_channels_2-tile_size_1024]✅ 5/5263.760.03n/a
test_layer_norm[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024]✅ 5/5282.440.03n/a
test_layer_norm[input_length_2048-num_aie_columns_2-num_channels_2-tile_size_512]✅ 5/5361.920.02n/a
test_layer_norm[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512]✅ 5/5326.740.03n/a
test_layer_norm[input_length_2048-num_aie_columns_4-num_channels_2-tile_size_256]✅ 5/5438.980.02n/a
iron/operators/leaky_relu
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_leaky_relu[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048-alpha_0.01]✅ 5/5339.760.03n/a
test_leaky_relu[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048-alpha_0.1]✅ 5/5403.100.02n/a
test_leaky_relu[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048-alpha_0.25]✅ 5/5676.260.02n/a
test_leaky_relu[input_length_2048-num_aie_columns_1-num_channels_2-tile_size_1024-alpha_0.01]✅ 5/5426.420.02n/a
test_leaky_relu[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024-alpha_0.01]✅ 5/5447.100.02n/a
test_leaky_relu[input_length_2048-num_aie_columns_2-num_channels_2-tile_size_512-alpha_0.01]✅ 5/5504.800.02n/a
test_leaky_relu[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512-alpha_0.01]✅ 5/5458.660.02n/a
test_leaky_relu[input_length_2048-num_aie_columns_4-num_channels_2-tile_size_256-alpha_0.01]✅ 5/5421.400.02n/a
iron/operators/mem_copy
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_mem_copy[input_length_2048-num_cores_1-num_channels_1-bypass_False-tile_size_2048]✅ 5/5367.880.02n/a
test_mem_copy[input_length_2048-num_cores_2-num_channels_1-bypass_False-tile_size_1024]✅ 5/5629.320.02n/a
test_mem_copy[input_length_2048-num_cores_2-num_channels_2-bypass_False-tile_size_1024]✅ 5/5337.100.03n/a
test_mem_copy[input_length_2048-num_cores_4-num_channels_1-bypass_False-tile_size_512]✅ 5/5393.780.02n/a
test_mem_copy[input_length_2048-num_cores_4-num_channels_2-bypass_False-tile_size_512]✅ 5/5390.180.02n/a
test_mem_copy[input_length_2048-num_cores_8-num_channels_2-bypass_False-tile_size_256]✅ 5/5473.940.02n/a
iron/operators/relu
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_relu[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048]✅ 5/5347.580.02n/a
test_relu[input_length_2048-num_aie_columns_1-num_channels_2-tile_size_1024]✅ 5/5326.260.03n/a
test_relu[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024]✅ 5/5452.800.02n/a
test_relu[input_length_2048-num_aie_columns_2-num_channels_2-tile_size_512]✅ 5/5413.500.02n/a
test_relu[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512]✅ 5/5337.840.03n/a
test_relu[input_length_2048-num_aie_columns_4-num_channels_2-tile_size_256]✅ 5/5397.340.02n/a
iron/operators/repeat
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_cols_without_a_legal_split_is_rejected[cols_1031-why_prime > 1023: the only divisors are 1 and cols, neither legal]✅ 5/5n/an/an/a
test_cols_without_a_legal_split_is_rejected[cols_2062-why_2 x 1031: the only word-aligned chunk leaves a 1031-wide chunk count]✅ 5/5n/an/an/a
test_cols_without_a_legal_split_is_rejected[cols_513-why_odd: every divisor is odd, so no chunk is a whole 32-bit word]✅ 5/5n/an/an/a
test_repeat[rows_4-cols_1024-repeat_2-transfer_size_None]✅ 5/5251.900.10n/a
test_repeat[rows_8-cols_512-repeat_4-transfer_size_64]✅ 5/5395.520.11n/a
test_repeat[rows_8-cols_64-repeat_4-transfer_size_None]✅ 5/5334.420.02n/a
iron/operators/rms_norm
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_rms_norm[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048-weighted_False]✅ 5/5334.640.03n/a
test_rms_norm[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048-weighted_True]✅ 5/5365.220.04n/a
test_rms_norm[input_length_2048-num_aie_columns_1-num_channels_2-tile_size_1024-weighted_False]✅ 5/5385.360.02n/a
test_rms_norm[input_length_2048-num_aie_columns_1-num_channels_2-tile_size_1024-weighted_True]✅ 5/5773.160.03n/a
test_rms_norm[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024-weighted_False]✅ 5/5368.100.03n/a
test_rms_norm[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024-weighted_True]✅ 5/5335.360.03n/a
test_rms_norm[input_length_2048-num_aie_columns_2-num_channels_2-tile_size_512-weighted_False]✅ 5/5515.800.02n/a
test_rms_norm[input_length_2048-num_aie_columns_2-num_channels_2-tile_size_512-weighted_True]✅ 5/5271.300.03n/a
test_rms_norm[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512-weighted_False]✅ 5/5482.980.02n/a
test_rms_norm[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512-weighted_True]✅ 5/5414.000.03n/a
test_rms_norm[input_length_2048-num_aie_columns_4-num_channels_2-tile_size_256-weighted_False]✅ 5/5453.400.02n/a
iron/operators/rope
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_rope[rows_32-cols_512-angle_rows_32-aie_columns_1-method_type_0]✅ 5/5690.560.22n/a
test_rope[rows_32-cols_512-angle_rows_32-aie_columns_2-method_type_0]✅ 5/5489.360.20n/a
test_rope[rows_32-cols_512-angle_rows_32-aie_columns_4-method_type_0]✅ 5/5459.500.24n/a
test_rope[rows_32-cols_512-angle_rows_8-aie_columns_1-method_type_0]✅ 5/5318.960.24n/a
test_rope[rows_32-cols_512-angle_rows_8-aie_columns_2-method_type_0]✅ 5/5322.360.26n/a
test_rope[rows_32-cols_512-angle_rows_8-aie_columns_4-method_type_0]✅ 5/5431.900.19n/a
iron/operators/sigmoid
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_sigmoid[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048]✅ 5/5428.920.03n/a
test_sigmoid[input_length_2048-num_aie_columns_1-num_channels_2-tile_size_1024]✅ 5/5320.460.03n/a
test_sigmoid[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024]✅ 5/5402.280.02n/a
test_sigmoid[input_length_2048-num_aie_columns_2-num_channels_2-tile_size_512]✅ 5/5540.520.02n/a
test_sigmoid[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512]✅ 5/5864.080.01n/a
test_sigmoid[input_length_2048-num_aie_columns_4-num_channels_2-tile_size_256]✅ 5/5535.740.02n/a
iron/operators/silu
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_silu[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048]✅ 5/5333.380.03n/a
test_silu[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024]✅ 5/5538.180.02n/a
test_silu[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512]✅ 5/5461.900.02n/a
iron/operators/softmax
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_softmax[input_length_32768-num_aie_columns_2-num_channels_2-tile_size_1024]✅ 5/5542.980.26n/a
test_softmax[input_length_32768-num_aie_columns_2-num_channels_2-tile_size_2048]✅ 5/5572.640.23n/a
test_softmax[input_length_32768-num_aie_columns_2-num_channels_2-tile_size_512]✅ 5/5490.300.28n/a
iron/operators/strided_copy
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_strided_copy[chunked_transfer]✅ 5/5278.720.02n/a
test_strided_copy[contiguous]✅ 5/5417.700.01n/a
test_strided_copy[four_channels]✅ 5/5737.600.01n/a
test_strided_copy[kv_slot0]✅ 5/5274.460.49n/a
test_strided_copy[kv_slot5]✅ 5/5359.040.42n/a
test_strided_copy[kv_slot5_four_channels]✅ 5/5432.920.34n/a
test_strided_copy[kv_slot5_two_channels]✅ 5/5341.880.42n/a
test_strided_copy[kv_slot_last]✅ 5/5307.300.47n/a
test_strided_copy[two_channels]✅ 5/5412.640.01n/a
test_strided_copy[two_channels_chunked]✅ 5/5389.620.01n/a
test_transfer_size_not_dividing_per_channel_share_is_rejected[iter0]✅ 1/1n/an/an/a
test_transfer_size_not_dividing_per_channel_share_is_rejected[iter1]✅ 1/1n/an/an/a
test_transfer_size_not_dividing_per_channel_share_is_rejected[iter2]✅ 1/1n/an/an/a
test_transfer_size_not_dividing_per_channel_share_is_rejected[iter3]✅ 1/1n/an/an/a
test_transfer_size_not_dividing_per_channel_share_is_rejected[iter4]✅ 1/1n/an/an/a
iron/operators/swiglu_decode
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_swiglu_decode[embedding_dim_1024-hidden_dim_3584]✅ 5/516685.170.00n/a
test_swiglu_decode[embedding_dim_2048-hidden_dim_2048]✅ 5/514249.280.00n/a
iron/operators/swiglu_prefill
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_swiglu_prefill[seq_len_256-embedding_dim_2048-hidden_dim_2048-prio_accuracy_False]✅ 5/524678.410.09n/a
iron/operators/tanh
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_tanh[input_length_2048-num_aie_columns_1-num_channels_1-tile_size_2048]✅ 5/5372.080.02n/a
test_tanh[input_length_2048-num_aie_columns_1-num_channels_2-tile_size_1024]✅ 5/5521.180.02n/a
test_tanh[input_length_2048-num_aie_columns_2-num_channels_1-tile_size_1024]✅ 5/5400.920.02n/a
test_tanh[input_length_2048-num_aie_columns_2-num_channels_2-tile_size_512]✅ 5/5450.220.02n/a
test_tanh[input_length_2048-num_aie_columns_4-num_channels_1-tile_size_512]✅ 5/5361.880.03n/a
test_tanh[input_length_2048-num_aie_columns_4-num_channels_2-tile_size_256]✅ 5/5443.480.02n/a
iron/operators/transpose
TestChecksLatency (mean)Bandwidth (mean)Throughput (mean)
test_transpose[M_2048-N_64-aie_columns_1-channels_1-m_64-n_64-s_8-num_batches_1]✅ 5/5572.860.96n/a
test_transpose[M_2048-N_64-aie_columns_1-channels_1-m_64-n_64-s_8-num_batches_2]✅ 5/51632.960.98n/a
test_transpose[M_2048-N_64-aie_columns_1-channels_2-m_64-n_64-s_8-num_batches_1]✅ 5/5489.281.30n/a
Phoenix - Examples

IRON

Tested on 2026_09_15_22_02_25 at commit bb0d09b.

Trend tables omitted, the comment hit GitHub's size limit. Full report in the workflow run.

hunhoffe and others added 6 commits September 11, 2026 17:05
A core can HOLD a B chunk across m_chunk accumulators instead of releasing
it after one, so DDR reads B m_row_blocks/m_chunk times. That recovers the
traffic the removed B residency used to save, without residency's cost:
residency sized the memtile buffer from k_iters and replayed it
m_row_blocks times, putting both K and M in the device configuration,
whereas m_chunk is a configuration constant.

Defaults to 1 (off). It is a tested knob, not a default, because
interleaved A/B at K=1024 N=4096 does not show a consistent win:

    M      m_chunk=1 min/med    m_chunk=2 min/med     min      med
     512    525.4 /  622.7       502.1 /  566.3      -4.4%    -9.1%
    1024    959.0 / 1081.6      1092.4 / 1162.9     +13.9%    +7.5%
    2048   1902.8 / 1986.0      1837.1 / 1940.0      -3.5%    -2.3%

B's traffic does fall, but the per-unit A descriptors m_chunk forces
(a_split) appear to eat it. The M=1024 regression is not monotonic in
n_units and is unexplained -- that is the open question, and the reason
this is off by default.

How the interleave works, since it is the non-obvious part: the core
consumes A as (k, b_iter, mc, band), with mc INSIDE b_iter. A second A
fifo would express that directly but needs a third core input DMA channel
against a hardware limit of two. So the memtile A object holds m_chunk
stacked tiles and the forward's dims_to_stream emits them interleaved,
which fits the memtile BD's four dimensions only because mc's stride
(M_TILE*K_TILE) exactly equals the row-group dimension's size*stride and
the two merge.

A partial group is inexpressible -- stride 0 inner is rejected, stride 0
outermost is the BD repeat count (one object per repetition, not one in
total), and sub-object fills do not coalesce, all three confirmed on
hardware -- so op.py resolves m_chunk to 1 when it would not divide
m_row_blocks, or when the group's ROWS*M_TILE*K stride would overflow the
shim BD's 20-bit step.

Also stops forcing OVERLAP=1 on every split block: only a block spanning
more than one window awaits inside itself. Worth -3.5% at M=2048 alone.

37/37 iter0 tests pass on npu2.

Co-Authored-By: André Rösti <an.roesti@gmail.com>
Moves off the 1.4.3.dev85 snapshot onto the tagged release. llvm-aie is
unchanged at 22.0.0.2026090701+3e93bf7b, which is the pin mlir-aie v1.4.3
itself names in utils/peano-requirements.txt, so the two stay in step.

Tagged wheels live under their own tag's asset page rather than
latest-wheels-4 (which carries only the .dev builds), hence the extra
find-links.

Co-Authored-By: Claude <noreply@anthropic.com>
CT_MAX_K_FOR_N is carried to the kernel as -DMM_FUSED_CT_K but appeared in
neither artifact name. This repo's build cache keys on filename and mtime
rather than on source or flags, so an object or xclbin built at one ct_max_k
silently satisfied a request for another.

Naming it in _kernel_object alone is not enough, and the reasoning that let
that hole stand is worth recording: tile_ma usually moves with ct_max_k, but
tile_ma is caller-overridable, so tn128/ma16 is reachable at two different
ct_max_k values. An xclbin built by an experiment at ck=128 was then served
to test_gemm_tile_options[tn128-ma16], which wants ck=32, and it returned
NaN rather than an error.

An artifact name must cover every input to THAT artifact; do not argue one
field is implied by another unless the implication holds for every reachable
configuration, overrides included.

Co-Authored-By: Claude <noreply@anthropic.com>
A parameter word is not free. Each costs ~66 ns per core and the sequence
writes ROWS*COLS = 32 of them, so every word is ~2.06 us of dispatch latency
-- measured by padding the buffer at a fixed core count (12 words 108.6 us,
24 words 135.2, 48 words 182.7). Against a ~107 us floor that is most of a
short-prefill dispatch.

Five of the ten were dead or duplicated:

  * the clamp trio is now sent only by a clamp-capable build. Where no
    clamped path is compiled in -- the default, and every real projection --
    those three words were written on every dispatch and never read.
  * n_chunks / n_units are sent only when m_chunk > 1. They are
    m_row_blocks // M_CHUNK and each other, so at the shipped M_CHUNK = 1 the
    core reads m_row_blocks instead. No on-core arithmetic.

and n_work / n_drain are now derived rather than sent, from a raw N word plus
the tile's own column. Branch-free, and both divisors are powers of two, so
it lowers to sdiv-by-constant and leaves no __divsi3 (verified in the .elf,
not just the .ll). Note ScalarValue overloads add/sub/mul/floordiv/mod but
NOT the shift operators, so this uses // rather than >>.

The column index is per-tile static data, deliberately not a constant folded
into the program: the 32 core programs differ today only in symbol names, and
baking it into code would make them differ in instructions, foreclosing a
future one-program xclbin.

rtp_layout() sizes the buffer from (clamp_capable, m_chunk), both of which are
already in _config_tag, so the word count cannot vary within a configuration
and ship-once-use-many is preserved -- verified by loading one xclbin and
dispatching shapes that disagree on M, K, N, on which columns sit a block
out, and on the activation.

Also guards CT_MAX_K_FOR_N: it reads like a tuning table but is load-bearing
for correctness, and a wrong value fails silently (err/mass 3.45e-02 at
tile_n=64/ct_k=64, NaN at tile_n=128). Root cause not found; pack_b is ruled
out by test, its permutation round-trips at ct_k 128, 64 and 32. Unverified
pairs now raise rather than miscompute.

30-shape suite: -3.5% median at M=256 (best -11.3%, E2B/kv), within noise at
M >= 1024 -- the saving is a constant ~12 us. Accuracy bit-identical on all
30 shapes; frozen-reference control drifted +0.11%.

Co-Authored-By: Claude <noreply@anthropic.com>
--no-short is not a real pytest option. What the harness actually wants is
--iterations 1: each test already averages ITERS dispatches over ROUNDS
interleaved rounds, so conftest's default of 5 repeats the whole matrix five
times for nothing.

Also records that -s must not be passed when the CSV is wanted -- the reporter
parses captured stdout, so disabling capture yields a CSV with no metric
columns.

Co-Authored-By: Claude <noreply@anthropic.com>
Where K or N is 10240 the row-block stride overflows the shim BD's 20-bit
iteration step, so that leg is issued as one transfer per row-block. Two shim
resources bound how many may be outstanding and neither is modelled by the
toolchain: BD ids (16/tile, freed without a completion check) and the channel
task queue (4 deep, pushed unconditionally).

That bound was enforced by windowing -- issue four, await the whole window,
issue the next four, then the same again per column-block. It is correct, but
TaskGroup.finish() emits dma_await_task, so each of those is a real barrier and
the channel drains to EMPTY at every window and column-block boundary. On a
DDR-rate-bound design those bubbles are the entire cost of the split path. The
OVERLAP value computed for this path was never read by it.

Retire the oldest transfer as the next is issued instead: the same number stay
in flight, the queue bound is enforced directly rather than by draining, and
the channel stays full across both kinds of boundary. Interleaved 8 rounds x 30
iters, bit-exact against the previous sequence on every shape:

    E4B/gateup M1024  4119.4 -> 3617.7  -12.2%
    E4B/gateup M2048  7664.8 -> 7182.4   -6.3%
    E4B/down   M1024  3649.2 -> 3553.4   -2.6%
    E4B/down   M2048  7196.6 -> 6978.7   -3.0%

The 24 shapes that do not split are untouched, measured at -0.1% median over
the full suite. One xclbin still serves every shape.

A unit is weighted by the C descriptors it drains (M_CHUNK under c_split), not
counted as one: counting units would overrun the 4-deep queue by exactly
M_CHUNK, and overrunning it hangs rather than diagnoses.

Also drops three knobs that no longer have a consumer -- the overlap parameter
(never passed), col_work/col_drain (superseded by the core deriving its own
trip counts) and the mt_*_bytes sizes (orphaned when B residency went) -- and
the prose describing mechanisms this design no longer has.

Co-Authored-By: Claude <noreply@anthropic.com>
@hunhoffe hunhoffe changed the title FLM GEMM w/ RTPs flm.GEMM: take M, K, N and the activation as runtime parameters Sep 14, 2026

@hunhoffe hunhoffe left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More fine-tuning needed.

Comment thread aie_kernels/generic/mm_fused.cc Outdated
Comment thread aie_kernels/generic/mm_fused.cc Outdated
Comment thread iron/operators/flm/gemm/design.py Outdated
Comment thread iron/operators/flm/gemm/op.py Outdated
Comment thread iron/operators/flm/gemm/op.py
Comment thread requirements.txt Outdated
This operator had accumulated about one line of prose per line of code, and
the RTP work made it worse rather than better -- design.py went from 429
comment and docstring lines to 633 while the code grew by 120.

Most of that was not explaining the code. It was measurement tables that
belong in README.md, rationale for alternatives that were tried and rejected,
and restatements of the line underneath. Several facts were stated two or
three times over: that the build cache keys on filename, that a second A fifo
would want a third input DMA channel, that C drains in row-block order even
under M_CHUNK.

What is kept is the class of comment that is expensive to lose, because the
failure it describes is silent: the BD-id recycle hazard that corrupts rather
than faulting, the shim task-queue depth that hangs rather than diagnosing,
_VERIFIED_CT_K where a wrong entry computes the wrong answer, and the memtile
placement pin. Those are stated once, at the code they constrain.

    design.py     42% -> 33% prose      op.py         45% -> 35%
    test.py       41% -> 33%            benchmark.py  42% -> 35%
    mm_fused.cc   46% -> 36%

Also corrects documentation that had gone stale. test.py still described the
split legs as retired in windows, which they have not been since the rolling
retire landed, so its docstring, an inline comment and two entries in the
shape table were all describing a mechanism that no longer exists.
test_gemm_split_leg_windowing is renamed to test_gemm_split_leg_bounds for the
same reason. Drops an unused `import os`.

No functional change: the AST with docstrings stripped is identical except for
that import and the two renames. 185/185 pass.

Co-Authored-By: Claude <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Instruction-cache collisions and DMA queue overrun can produce stale clamp bounds, incorrect activations, or device hangs.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Moves FLM GEMM shape, activation, and clamp bounds into runtime parameters so configurations can share an xclbin.

Changes:

  • Adds runtime-parameterized GEMM execution and epilogue dispatch.
  • Introduces rolling split-transfer retirement.
  • Pins MLIR-AIE v1.4.3 and expands regression coverage.
File summaries
File Description
requirements.txt Pins the required MLIR-AIE release.
iron/operators/flm/gemm/test.py Tests shared xclbins and runtime parameters.
iron/operators/flm/gemm/README.md Documents runtime parameters and performance tradeoffs.
iron/operators/flm/gemm/op.py Separates configuration and instruction artifacts.
iron/operators/flm/gemm/design.py Implements RTP handling and rolling transfers.
iron/operators/flm/gemm/benchmark.py Updates benchmark guidance and commentary.
aie_kernels/generic/mm_fused.cc Adds runtime epilogue and clamp dispatch.
Review details
  • Files reviewed: 6/7 changed files
  • Comments generated: 3
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread iron/operators/flm/gemm/design.py Outdated
Comment thread iron/operators/flm/gemm/op.py Outdated
Comment thread iron/operators/flm/gemm/op.py Outdated
hunhoffe and others added 4 commits September 15, 2026 15:03
The clamp-capable NPU1 build fails aiecc's measured_stack_sizes edge:

    error: stack_size is absent, so this core uses the device default of
    1024 bytes, but it needs 1088 bytes

which is every Phoenix failure in CI. The activation LUT path plus the
epilogue's clamp vectors put it 64 bytes over the device default, and
nothing had set stack_size, so the default applied.

2048 with the exact requirement named in the comment, since aiecc reports
it if a change ever outgrows this. It also comes off the L1 budget rather
than being left for aiecc to catch: _default_l1 was free to hand a buffer
the bytes the stack needs, and relying on a build failure to notice is
only tolerable while nothing has to fit in the gap. Verified not to move
(tile_ma, b_depth) for any tile_n on either device, so the geometry and
the measured performance are unchanged.

Co-Authored-By: Claude <noreply@anthropic.com>
Review feedback: the find-links line above stands on its own.

Co-Authored-By: Claude <noreply@anthropic.com>
emit_split appended a unit's TaskGroup and only then retired down to
SHIM_TASK_QUEUE, but fill/drain pushes the DMA task immediately while
TaskGroup.finish() is what emits the await. So each unit's transfers went
onto the channel with four already outstanding -- a transient fifth
against a queue documented as four deep, and one more than
test_gemm_split_leg_bounds' 4 + 2 + 2 descriptor arithmetic assumes.

Retire to SHIM_TASK_QUEUE - unit_cost first instead, so the push happens
with room for it. The channel still never drains to empty, which is the
property worth -12.4% on these shapes: three transfers stay in flight
while the oldest is awaited.

Reported by Copilot on #200. Build-verified on both devices at
M=512 K=10240 N=10240, where both legs split -- a miscounted bound fails
to close its task groups at build time. Not verified on hardware: this
box cannot dispatch, so CI is the gate.

Co-Authored-By: Claude <noreply@anthropic.com>
Four review comments on #200, all about what belongs in the xclbin and
what belongs in the instruction stream.

MM_FUSED_CLAMP forked the build between clamped and unclamped callers,
which reads as "a build per clamp" and is the odd one out: the activation
is runtime-selected with every mode compiled in, so the clamp should be
too. It now is. There is no unclamped instantiation to compile out --
an unclamped dispatch sends (-inf, +inf), and min(x, +inf) / max(x, -inf)
leave every finite value bit-identical, so this costs no accuracy. Gone
with it: the CLAMP template parameter, epilogue_dispatch, _clamp_capable,
the cl axis in the config tag and the kernel object, and the
clamp_enabled RTP word and kernel argument.

The bounds are two always-sent words rather than a conditional trio, so
an unclamped caller pays ~4 us of dispatch it did not before and a
clamping one saves ~2. The README's -3.5%-at-M=256 figure was measured at
four words and is annotated rather than restated, since it has not been
re-measured.

_config_tag folded into config_name: it had one caller besides
config_name itself, and name now composes on config_name instead.

name also carries the clamp bounds, as raw bit patterns. They are
immediates in the runtime sequence and the build cache keys on filename
and mtime, so without them a second operator at the same shape with
different bounds is served the first one's instruction stream and
silently clamps to the first one's values.

_epilogue_mask ORs rather than sums, so two copies of a mode cannot carry
into the neighbouring mode's bit, and __post_init__ now rejects an
epilogue that epilogue_modes omits instead of letting it reach the
kernel's default arm and apply no activation at all.

Also trims the epilogue comment block, which review found excessive, and
drops test.py's late import of get_target_model, already at module top.

Build-verified on npu1 and npu2 across every tile_n, with and without a
clamp, and with gelu for the LUT archive path. Not verified on hardware:
this box ships a cp310 pyxrt that no mlir_aie 1.4.3 wheel matches, so CI
is the gate on the numerics.

Co-Authored-By: Claude <noreply@anthropic.com>
@hunhoffe
hunhoffe marked this pull request as ready for review September 16, 2026 19:32
@hunhoffe
hunhoffe added this pull request to the merge queue Sep 16, 2026
Merged via the queue into devel with commit 1fd3dab Sep 16, 2026
6 checks passed
@hunhoffe
hunhoffe deleted the flm-gemm-rtp-v2 branch September 16, 2026 21:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants