metrale_model_layers/layers/moe/mod.rs
1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3//! 2026-09-25: The MoE feed-forward block `MoeLayer`: router, routed experts, optional
4//! shared expert, and the kernel handles and pointer tables its forward paths use.
5//!
6//! Owner: model-layers (MoE).
7//! Invariants:
8//! - Construction (`new_with_hash`) fails unless `num_experts > 0`,
9//! `num_experts_per_tok <= num_experts`, and both are within the sigmoid
10//! routing kernels' fixed bounds.
11
12use anyhow::Result;
13use metrale_gpu_runtime::gpu::{DevicePtr, GpuBackend, KernelHandle};
14
15use crate::layer::ForwardContext;
16use crate::layers::ops;
17use crate::weight_map::{DenseWeight, Fp8ExpertWeight, MoeWeights, QuantizedWeight};
18
19/// 2026-09-25: The MoE feed-forward block. It is a component that layers call for
20/// their FFN step; it does not implement `TransformerLayer`.
21#[allow(dead_code)]
22pub struct MoeLayer {
23 pub weights: MoeWeights,
24 /// 2026-09-25: Quant format of the routed experts. `new_with_hash` sets `Nvfp4`;
25 /// the DeepSeek-V4 loader sets the detected format, and `Mxfp4E8m0` makes
26 /// `e8m0_or` and the prefill dispatch pick the `_e8m0` kernels.
27 #[allow(dead_code)]
28 pub experts_scale_kind: crate::weight_map::WeightQuantFormat,
29 /// 2026-09-25: Quant format of the shared expert, detected separately from the
30 /// routed experts. `new_with_hash` sets `Nvfp4`. With E8M0 routed experts,
31 /// the dual-format decode paths check it with `WeightQuantFormat::expect`.
32 #[allow(dead_code)]
33 pub shared_experts_scale_kind: crate::weight_map::WeightQuantFormat,
34 // 2026-09-25: NVFP4 copy of the router gate. When set, the router GEMM runs on
35 // it instead of the BF16 `weights.gate`.
36 gate_nvfp4: Option<QuantizedWeight>,
37 /// 2026-09-25: RMS norm applied to the expert input after routing; the router reads
38 /// its own input (`router_input`). Only the Gemma-4 loader sets it.
39 pub pre_expert_norm: Option<crate::weight_map::DenseWeight>,
40 pre_expert_norm_k: metrale_gpu_runtime::gpu::KernelHandle,
41 dense_gemv: KernelHandle,
42 w4a16_gemv: KernelHandle,
43 w4a16_gemv_sw: KernelHandle,
44 w4a16_gemm: KernelHandle,
45 dense_gemm: KernelHandle,
46 /// 2026-09-25: `dense_gemm_bf16_router`, read only by `router_gate_gemm_dense`,
47 /// which uses `dense_gemm` instead when this handle is 0.
48 dense_gemm_router: KernelHandle,
49 /// 2026-09-28: `moe_router_gemm_rt`, the same bits as `dense_gemm_router` on a register
50 /// tile, taken from `MOE_ROUTER_RT_MIN_ROWS` rows; 0 when the target lacks it or
51 /// `METRALE_NO_MOE_ROUTER_RT` is set.
52 moe_router_rt_k: KernelHandle,
53 // 2026-09-26: `moe_router_gemm_bf16` (`router_gemm_bf16`); 0 on targets that
54 // do not ship it.
55 moe_router_gemm_k: KernelHandle,
56 dense_gemm_pipelined: KernelHandle,
57 /// 2026-09-25: FP32-output router GEMM for the `fp32_gate` lever
58 /// (`METRALE_FP32_GATE`). 0 when the target lacks it; the gate then stays BF16.
59 dense_gemm_f32out: KernelHandle,
60 /// 2026-09-25: FP32-in/FP32-out router GEMM for the `fp32_routing` lever
61 /// (`METRALE_FP32_ROUTING`); `fp32_routing_active` is false while it is 0.
62 dense_gemm_f32in: KernelHandle,
63 moe_topk_f32: KernelHandle,
64 moe_expert_gate_up_shared: KernelHandle,
65 moe_expert_silu_down_shared: KernelHandle,
66 moe_topk: KernelHandle,
67 moe_weighted_sum_blend: KernelHandle,
68 residual_add: KernelHandle,
69 moe_topk_batched: KernelHandle,
70 moe_expert_gate_up_shared_batch2: KernelHandle,
71 moe_expert_silu_down_shared_batch2: KernelHandle,
72 moe_weighted_sum_blend_batch2: KernelHandle,
73 w4a16_gemv_batch2: KernelHandle,
74 moe_expert_gate_up_shared_batch3: KernelHandle,
75 moe_expert_silu_down_shared_batch3: KernelHandle,
76 moe_weighted_sum_blend_batch3: KernelHandle,
77 w4a16_gemv_batch3: KernelHandle,
78 // 2026-09-25: Token-major kernels for `forward_token_major_decode`. The
79 // `atomic_c4` pair serves `forward_atomic_c4_decode`
80 // (`METRALE_MOE_ATOMIC_C4_DECODE=1`).
81 moe_expert_gate_up_shared_token_major: KernelHandle,
82 moe_expert_silu_down_shared_token_major: KernelHandle,
83 moe_weighted_sum_blend_token_major: KernelHandle,
84 moe_decode_atomic_c4_silu_down_accum_k: KernelHandle,
85 moe_decode_atomic_c4_finalize_k: KernelHandle,
86 moe_sort_by_expert: KernelHandle,
87 moe_sorted_gate_up: KernelHandle,
88 moe_sorted_silu_down: KernelHandle,
89 moe_grouped_gemm: KernelHandle,
90 /// 2026-09-25: Wider-K twin of `moe_grouped_gemm`. Loaded only when
91 /// `METRALE_MOE_GROUPED_K32=1` and the target ships it; `grouped_gemm_kernel`
92 /// prefers it whenever it is non-zero.
93 moe_grouped_gemm_k32: KernelHandle,
94 /// 2026-09-25: M_TILE=256 twin of `moe_grouped_gemm`. Loaded only when
95 /// `METRALE_MOE_GROUPED_M256=1` and the target ships it; used whenever it is
96 /// non-zero.
97 moe_grouped_gemm_m256: KernelHandle,
98 moe_silu_mul: KernelHandle,
99 /// 2026-09-25: Activation kernel for the sorted/unfused paths: `moe_silu_mul`, or
100 /// `gelu_mul` after `set_gelu_activation`.
101 moe_act_mul: KernelHandle,
102 /// 2026-09-25: Set by `set_gelu_activation`. The fused SiLU+FP8-quant kernel is used
103 /// only while it is false (`fused_silu_quant_ok`).
104 gelu_activation: bool,
105 moe_unpermute_reduce: KernelHandle,
106 moe_batched_blend: KernelHandle,
107 gate_ptrs: ExpertPtrTable,
108 up_ptrs: ExpertPtrTable,
109 down_ptrs: ExpertPtrTable,
110 /// 2026-09-25: Transposed-layout pointer tables; `None` until a transpose pass or
111 /// `set_down_transpose_scratch` fills them.
112 gate_ptrs_t: Option<ExpertPtrTable>,
113 up_ptrs_t: Option<ExpertPtrTable>,
114 down_ptrs_t: Option<ExpertPtrTable>,
115 /// 2026-09-25: Host-side per-expert packed/SFB pointers and scale2 for the CUTLASS
116 /// grouped NVFP4 path, built once by `build_cutlass_grouped_sfb`. The grouped
117 /// entry reads them on the host; they live on the layer so they are dropped
118 /// with the model. `None` means that path is unavailable.
119 cutlass_grouped_host: Option<ops::MoeCutlassHostTables>,
120 /// 2026-09-25: Owns the per-expert SFB buffers that `cutlass_grouped_host` points at.
121 _cutlass_sfb_owned: Vec<DevicePtr>,
122 /// 2026-09-25: Down-projection transpose scratch shared by all MoE layers, wired by
123 /// `set_down_transpose_scratch`. `transpose_down_into_scratch` refills it at
124 /// the start of each layer's prefill, and `down_ptrs_t` then points into it.
125 /// `None` unless that scratch is wired.
126 down_t_scratch_packed: Option<DevicePtr>,
127 down_t_scratch_scale: Option<DevicePtr>,
128 moe_transpose_u8_batched_k: KernelHandle,
129 moe_expert_gate_up_shared_t_k: KernelHandle,
130 moe_expert_silu_down_shared_t_k: KernelHandle,
131 // 2026-09-25: Decode variants for E8M0-scaled routed experts with an NVFP4 shared
132 // expert. 0 on targets that do not ship them.
133 moe_expert_gate_up_shared_t_e8m0_k: KernelHandle,
134 moe_expert_silu_down_shared_t_e8m0_k: KernelHandle,
135 moe_topk_sqrtsoftplus_k: KernelHandle,
136 moe_topk_sqrtsoftplus_batched_k: KernelHandle,
137 moe_hash_route_k: KernelHandle,
138 moe_hash_route_batched_k: KernelHandle,
139 /// 2026-09-25: Router logit width, `num_experts + zero_expert_num`. It equals
140 /// `num_experts` unless the model has zero-computation experts.
141 pub(crate) router_logits_n: u32,
142 moe_topk_softmax_bias_k: KernelHandle,
143 moe_topk_softmax_bias_batched_k: KernelHandle,
144 moe_zero_expert_add_k: KernelHandle,
145 /// 2026-09-25: Per-token folded zero-expert weight (f32), written by the
146 /// softmax+bias router kernels. Allocated once, for 16384 tokens.
147 zero_accum_dev: DevicePtr,
148 /// 2026-09-25: Static hash-routing table `[vocab_size, top_k]` i64. `Some` marks a
149 /// hash-routed layer: expert selection reads this table instead of the
150 /// gate's top-k.
151 tid2eid_dev: Option<DevicePtr>,
152 moe_expert_gate_up_shared_batch2_t_k: KernelHandle,
153 moe_expert_silu_down_shared_batch2_t_k: KernelHandle,
154 moe_expert_gate_up_shared_batch3_t_k: KernelHandle,
155 moe_expert_silu_down_shared_batch3_t_k: KernelHandle,
156 moe_expert_gate_up_shared_fp8_t_k: KernelHandle,
157 moe_expert_silu_down_shared_fp8_t_k: KernelHandle,
158 moe_expert_gate_up_shared_fp8_batch2_t_k: KernelHandle,
159 moe_expert_silu_down_shared_fp8_batch2_t_k: KernelHandle,
160 moe_expert_gate_up_shared_fp8_batch3_t_k: KernelHandle,
161 moe_expert_silu_down_shared_fp8_batch3_t_k: KernelHandle,
162 /// 2026-09-25: `METRALE_UNIFIED_MOE_LAYOUT` (`1` or `true`), read at construction.
163 /// With all three transposed tables built and no down scratch, decode runs
164 /// the `moe_expert_*_shared_t` kernels unless `hybrid_layout` is also set.
165 unified_layout: bool,
166 /// 2026-09-25: `METRALE_NVFP4_GATE_UP_M128` (`1` or `true`). Prefill's fused
167 /// gate+up uses the M=128 kernel when this is set and
168 /// `moe_fused_gate_up_t_k64_m128` is non-zero, else the M=64 kernel.
169 nvfp4_gate_up_m128: bool,
170 /// 2026-09-25: `METRALE_HOLO_MOE_GATEUP_FP4` (`1` or `true`). Prefill's fused
171 /// gate+up runs `moe_fused_gate_up_t_k64_fp4` over the existing
172 /// `gate_ptrs_t`/`up_ptrs_t` tables when this is set and the handle is non-zero.
173 gateup_fp4: bool,
174 /// 2026-09-25: `METRALE_HOLO_MOE_DOWN_FP4` (`1` or `true`): the same choice for the
175 /// prefill down projection, with `moe_down_t_k64_fp4` over `down_ptrs_t`.
176 down_fp4: bool,
177 /// 2026-09-25: `METRALE_HYBRID_MOE_LAYOUT` (`1` or `true`), read at construction.
178 /// Prefill uses the transposed tables (`use_t_layout_for_prefill`) while
179 /// decode keeps the original `[N, K/2]` tables, even when `unified_layout`
180 /// is also set.
181 hybrid_layout: bool,
182 shared_gate_t: Option<QuantizedWeight>,
183 shared_up_t: Option<QuantizedWeight>,
184 shared_down_t: Option<QuantizedWeight>,
185 moe_grouped_gemm_t: KernelHandle,
186 moe_grouped_gemm_t_k64: KernelHandle,
187 moe_fused_gate_up_t: KernelHandle,
188 moe_fused_gate_up_t_k64: KernelHandle,
189 // 2026-09-25: E8M0-scale prefill variants of the routed-expert W4A16 GEMMs. 0 on
190 // targets that do not ship them.
191 moe_grouped_gemm_e8m0: KernelHandle,
192 moe_grouped_gemm_t_e8m0: KernelHandle,
193 moe_grouped_gemm_t_k64_e8m0: KernelHandle,
194 moe_fused_gate_up_t_e8m0: KernelHandle,
195 moe_fused_gate_up_t_k64_e8m0: KernelHandle,
196 /// 2026-09-25: M=128 variant of the K64 fused gate+up kernel; 0 on targets that do
197 /// not ship it.
198 moe_fused_gate_up_t_k64_m128: KernelHandle,
199 /// 2026-09-25: Block-scaled FP4 variant of the K64 fused gate+up kernel, launched
200 /// through the same wrapper as `moe_fused_gate_up_t_k64`; 0 on targets that
201 /// do not ship it.
202 moe_fused_gate_up_t_k64_fp4: KernelHandle,
203 moe_fp8_grouped_gemm_t: KernelHandle,
204 w4a16_gemm_t: KernelHandle,
205 bf16_to_fp8_k: KernelHandle,
206 /// 2026-09-25: FP8 copies of the NVFP4 router gate and shared expert, made by
207 /// `predequant_for_prefill`. The shared-expert copies are skipped when a BF16
208 /// shared expert is installed.
209 gate_fp8: Option<DevicePtr>,
210 shared_gate_fp8: Option<DevicePtr>,
211 shared_up_fp8: Option<DevicePtr>,
212 shared_down_fp8: Option<DevicePtr>,
213 fp8_gemm_k: KernelHandle,
214 /// 2026-09-25: Auxiliary stream. Nothing launches on it today: the prefill
215 /// shared-expert overlap is switched off (`use_overlap = false` in
216 /// `forward_prefill`), and `kick_off_lazy_transpose`, the down transpose that
217 /// would run on it, has no caller.
218 prefill_stream: u64,
219 /// 2026-09-25: `event_a` marks the input ready for the auxiliary stream; `event_b`
220 /// marks the auxiliary work (the overlapped shared expert, or
221 /// `kick_off_lazy_transpose`'s transpose) done. Neither is recorded while
222 /// both of those are off.
223 event_a: u64,
224 event_b: u64,
225 /// 2026-09-25: `[num_experts]` routing correction bias, from
226 /// `MoeWeights.correction_bias`. `Some` selects bias-corrected routing
227 /// (sigmoid, or sqrtsoftplus when the config says so); `None` selects softmax.
228 correction_bias_dev: Option<DevicePtr>,
229 moe_topk_sigmoid_k: KernelHandle,
230 moe_topk_sigmoid_batched_k: KernelHandle,
231 moe_expert_gate_up_shared_fp8: KernelHandle,
232 moe_expert_silu_down_shared_fp8: KernelHandle,
233 moe_expert_gate_up_shared_fp8_batch2: KernelHandle,
234 moe_expert_silu_down_shared_fp8_batch2: KernelHandle,
235 moe_weighted_sum_blend_fp8_batch2: KernelHandle,
236 moe_expert_gate_up_shared_fp8_batch3: KernelHandle,
237 moe_expert_silu_down_shared_fp8_batch3: KernelHandle,
238 moe_weighted_sum_blend_fp8_batch3: KernelHandle,
239 // 2026-09-25: Grouped FP8 decode kernels from `GroupedKernels::resolve`; 0 on
240 // targets that do not ship them.
241 moe_expert_gate_up_act_fp8_grouped_k: KernelHandle,
242 moe_expert_down_act_fp8_grouped_k: KernelHandle,
243 moe_weighted_sum_blend_fp8_grouped_k: KernelHandle,
244 // 2026-09-27: `moe_fp8_grouped_sort`: the slot sort and the active-expert list in
245 // one launch.
246 moe_fp8_grouped_sort_k: KernelHandle,
247 // 2026-09-26: The exact-router kernels of the grouped decode
248 // (`GroupedRouting::PerRow` / `PerToken`): `moe_topk_softmax_rows` and
249 // `dense_gemv_bf16_batchm`; 0 on targets that do not ship them.
250 moe_topk_softmax_rows_k: KernelHandle,
251 router_gemv_batchm_k: KernelHandle,
252 // 2026-09-27: The grouped NVFP4 decode's expert kernels (NVFP4 `--expert-quantization`
253 // tiers); 0 on
254 // targets that do not ship them.
255 nvfp4_grouped: forward_nvfp4_grouped_decode::Nvfp4GroupedKernels,
256 // 2026-09-28: The grouped FP8 decode's tensor-core expert kernels (`fp8_grouped_tc.rs`).
257 fp8_grouped_tc: fp8_grouped_tc::Fp8GroupedTcKernels,
258 // 2026-09-25: Routed-expert FP8 grouped GEMM over the tile work-list that
259 // `moe_build_tile_worklist` builds; 0 on targets that do not ship it.
260 moe_fp8_grouped_gemm_k: KernelHandle,
261 moe_build_tile_worklist_k: KernelHandle,
262 // 2026-09-25: The Hopper short-prefill M16 expert GEMM and bucket builder
263 // (`adaptive_fp8.rs`), and the SM count their grids are sized from; 0 when the
264 // target lacks either module.
265 moe_w8a8_m16_k: KernelHandle,
266 moe_bucket_builder_k: KernelHandle,
267 moe_adaptive_sms: u32,
268 // 2026-09-25: W8A8 grouped GEMM with an FP32 epilogue over per-token-quantized
269 // activations. The FP8 prefill uses it when `fp8_blockscaled_prefill` is on
270 // (the default; `METRALE_FP8_SINGLE_SCALE=1` turns it off) and this handle
271 // and the per-token quant kernel are present.
272 moe_w8a8_grouped_gemm_k: KernelHandle,
273 // 2026-09-25: Work-list variant of the W8A8 grouped GEMM. Preferred when it and
274 // `moe_build_tile_worklist_k` are non-zero; otherwise the W8A8 path runs
275 // `moe_w8a8_grouped_gemm_k`.
276 moe_w8a8_grouped_gemm_pm4_k: KernelHandle,
277 // 2026-09-27: The PM4 computation on the native e4m3 MMA (`forward_prefill_fp8/e4m3.rs`),
278 // preferred over PM4 for non-decode prefill.
279 moe_e4m3: forward_prefill_fp8::E4m3Kernels,
280 // 2026-09-28: `moe_unpermute_blend` (unpermute + shared blend in one launch, same bits);
281 // 0 when absent or under `METRALE_NO_MOE_UNPERMUTE_BLEND`.
282 moe_unpermute_blend_k: KernelHandle,
283 per_token_group_quant_fp8_k: ops::Fp8ActQuant,
284 /// 2026-09-25: Fused SiLU·mul + per-token-group FP8 quant for the W8A8 prefill
285 /// down inputs. When `fused_silu_quant_ok` is false (handle 0, GeGLU, or an
286 /// unsupported K) the path runs `silu_mul` then `per_token_group_quant_fp8`.
287 silu_mul_quant_fp8_k: KernelHandle,
288 // 2026-09-25: Dense W8A8 GEMM for the shared expert on the W8A8 FP8 prefill path.
289 fp8_gemm_t_blockscaled_k: KernelHandle,
290 // 2026-09-25: BF16 grouped GEMM for experts installed with `set_bf16_experts`.
291 // Prefill of more than 64 tokens uses it when it is non-zero, except on HIP
292 // builds; otherwise BF16 experts run `forward_batched`.
293 moe_bf16_grouped_gemm_k: KernelHandle,
294 moe_expert_gate_up_shared_bf16_k: KernelHandle,
295 moe_expert_silu_down_shared_bf16_k: KernelHandle,
296 // 2026-09-25: Two-row BF16 decode kernels. `forward_k2` uses them only when both
297 // are non-zero, BF16 experts are installed and expert parallelism is off.
298 moe_expert_gate_up_shared_bf16_batch2_k: KernelHandle,
299 moe_expert_silu_down_shared_bf16_batch2_k: KernelHandle,
300 w8a16_gemm_k: KernelHandle,
301 w8a16_gemm_pipelined_k: KernelHandle,
302 moe_gate_topk_fused_k: KernelHandle,
303 // 2026-09-25: FP8 expert pointer tables; `None` until `set_fp8_experts`.
304 fp8_gate_weight_ptrs: Option<Fp8ExpertPtrTable>,
305 fp8_up_weight_ptrs: Option<Fp8ExpertPtrTable>,
306 fp8_down_weight_ptrs: Option<Fp8ExpertPtrTable>,
307 // 2026-09-25: BF16 expert pointer tables; `None` until `set_bf16_experts`. When
308 // set, prefill takes the BF16 expert path before any FP8 or NVFP4 one.
309 bf16_gate_weight_ptrs: Option<DevicePtr>,
310 bf16_up_weight_ptrs: Option<DevicePtr>,
311 bf16_down_weight_ptrs: Option<DevicePtr>,
312 // 2026-09-25: BF16 shared expert, installed independently of the routed experts'
313 // precision (`set_bf16_shared_expert`).
314 bf16_shared_expert: Option<Bf16SharedExpert>,
315 // 2026-09-25: FP8 shared expert; `None` until `set_fp8_experts`.
316 fp8_shared_expert: Option<Fp8ExpertWeight>,
317 /// 2026-09-25: `moe_w4a16_down_t_k64_fp4`; 0 on targets that do not ship it.
318 pub(crate) moe_down_t_k64_fp4: KernelHandle,
319 /// 2026-09-25: `moe_permute_tokens`. Loaded, but no forward path reads it.
320 #[allow(dead_code)]
321 pub(crate) moe_permute_tokens_k: KernelHandle,
322 // 2026-09-25: True when this layer's index is in `config.dflash_capture_layers`
323 // (set by the qwen35 loader). With the `frankenstein_decode_via_prefill`
324 // lever (`METRALE_FRANKENSTEIN_DECODE_VIA_PREFILL`), `forward` runs this
325 // layer's single-token decode through `forward_prefill` with one row.
326 pub is_dflash_capture_layer: bool,
327 /// 2026-09-25: This layer's installed MoE LoRA (router and routed-expert deltas plus
328 /// apply scratch), set by [`MoeLayer::set_lora_weights`]; `None` means no
329 /// adapter. Decode paths that call `reject_decode_lora` refuse a batch
330 /// routed to the adapter.
331 pub(crate) lora: Option<MoeLoraWeights>,
332}
333
334impl MoeLayer {
335 /// 2026-09-25: Returns `e8m0` when the routed experts are `Mxfp4E8m0`, else `nvfp4`.
336 /// Panics when `e8m0` is selected but its handle is 0, so E8M0 weights never
337 /// run through an NVFP4 kernel.
338 #[inline]
339 fn e8m0_or(
340 &self,
341 nvfp4: metrale_gpu_runtime::gpu::KernelHandle,
342 e8m0: metrale_gpu_runtime::gpu::KernelHandle,
343 site: &str,
344 ) -> metrale_gpu_runtime::gpu::KernelHandle {
345 if self.experts_scale_kind == crate::weight_map::WeightQuantFormat::Mxfp4E8m0 {
346 assert!(
347 e8m0.0 != 0,
348 "ARM-2 Phase-K: routed experts tagged Mxfp4E8m0 at {site}, but the \
349 _e8m0 kernel handle is unresolved (not compiled into this target)."
350 );
351 e8m0
352 } else {
353 nvfp4
354 }
355 }
356}
357
358mod adaptive_fp8;
359mod tables;
360pub(crate) use tables::{Bf16SharedExpert, ExpertPtrTable, Fp8ExpertPtrTable};
361
362mod dump;
363mod forward;
364mod lora;
365mod lora_gateup;
366mod lora_router;
367pub(crate) use lora::MoeLoraWeights;
368mod forward_atomic_c4;
369mod forward_batched;
370mod forward_batched_gate;
371mod forward_ep;
372mod forward_fp8_grouped_decode;
373mod fp8_grouped_tc;
374mod fp8_grouped_tc_w8a8;
375pub use forward_fp8_grouped_decode::fp8_grouped_decode_shape_ok;
376pub use fp8_grouped_tc_w8a8::{moe_expert_fp8_act, set_moe_expert_fp8_act};
377mod forward_fp8_grouped_router;
378pub use forward_fp8_grouped_router::GroupedRouting;
379mod forward_bf16_grouped_decode;
380mod forward_nvfp4_grouped_decode;
381mod nvfp4_lean;
382pub use forward_nvfp4_grouped_decode::{
383 NVFP4_GROUPED_DECODE_MAX_ROWS, NVFP4_GROUPED_DECODE_TC_MAX_ROWS, nvfp4_grouped_decode_shape_ok,
384};
385mod forward_k2;
386mod forward_k3;
387mod forward_phase;
388mod forward_prefill;
389mod forward_prefill_bf16;
390mod forward_prefill_fp8;
391mod forward_prefill_phase;
392mod forward_prefill_routed;
393mod forward_prefill_router;
394mod forward_token_major;
395mod helpers_a;
396mod helpers_b;
397mod helpers_c;
398mod init;
399#[cfg(test)]
400mod mod_tests;
401mod ptr_table_build;
402mod union_stats;
403pub(crate) use ptr_table_build::*;