backend: Add MX quant/dequant on-the-fly compute (size-changing datapath) - #167
Open
DanielKellerM wants to merge 2 commits into
Open
backend: Add MX quant/dequant on-the-fly compute (size-changing datapath)#167DanielKellerM wants to merge 2 commits into
DanielKellerM wants to merge 2 commits into
Conversation
DanielKellerM
force-pushed
the
otf/size-changing-compute
branch
3 times, most recently
from
August 6, 2026 08:06
8333342 to
fca1db0
Compare
…ath) Support compute ops whose write byte count differs from the read byte count: per-op source:dest ratios in idma_pkg (compute_in_bytes/compute_out_bytes) program the legalizer write length, and the compute seam presents per-lane valid (pack occupancy) with full strobes so the write manager's own beat mask gates acceptance — a partial beat can only complete the transfer's genuine tail. The legalizer asserts input-granule alignment, beat-aligned src/dst, per-beat-capable destination protocols (no TileLink), the FP16 width cap, and that the requested op is elaborated (EnableCompute / ComputeOps). Ops (selected via compute_cfg.compute_op like transpose): - COMPUTE_MXQUANT / COMPUTE_MXQUANT_FP16: FP32/FP16 -> MXFP8, one 33B block ([1B E8M0 scale][32B E5M2]) per 32 elements (128B/64B in), RNE with full subnormal, saturation and Inf/NaN handling, bit-exact with the viDMA ALCU. FP16 requires StrbWidth <= 64; FP32 scales to StrbWidth 128 (1024b). - COMPUTE_MXDEQUANT: MXFP8 -> FP32 (33B -> 128B); input length must be beat-aligned (33k % StrbWidth == 0). Verified byte-exact against a DPI-C golden at every legal StrbWidth (DataWidth 32-1024): tb_idma_mxquant (FP16 + FP32 sources, partial tail, 4K page crossing) and tb_idma_mxroundtrip (quant -> dequant, FP16 leg at 512b, FP32 leg at 1024b); transpose regressions unchanged.
DanielKellerM
force-pushed
the
otf/size-changing-compute
branch
from
August 6, 2026 09:43
fca1db0 to
aa0bf44
Compare
Hoist the block-completion datapath out of the unrolled element loop (64x replicated at 1024b: 2048 quantizer sites -> 32), generate-gate the FP16 path above 512b, drop output registers that duplicated pack state, reduce the subnormal shifter to its 3 reachable amounts, and rebuild the dequant pack as a one-block-per-cycle expansion into a pow2 circular buffer (no byte shifting). Bit-exact vs the DPI golden and throughput-neutral; the naive engines did not finish synthesis in 14h, the restructured ones close 1 GHz timing in a 12 nm technology in ~25 min (quant 39.5k/71.5k cells at 512b/1024b, dequant 37.4k/52.8k).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds size-changing on-the-fly compute (write byte count != read byte count) on top of the transpose/otf_compute framework, with MX (OCP microscaling) quantization and dequantization as the first ops. Stacked on #166 (
backend/w-beat-done-retire), which provides the per-beat write retire this depends on.Mechanism. Per-op source:dest byte ratios in
idma_pkg(compute_in_bytes/compute_out_bytes) program the legalizer write length, so the write burst's beat count matches the beats the compute engine emits. The compute seam presents per-lane valid (pack-buffer occupancy) with full strobes; the write manager's own beat mask gates acceptance, and the engine retires lane-exactly against the byte lanes the write port actually consumed (buffer_out_ready), so a partial tail beat pops only its own bytes — no drain FSM, no transport-layer state machine, and back-to-back transfers with an identical compute config pipeline with zero inter-transfer bubbles. The legalizer asserts fence the contract: input-granule alignment, beat-aligned src/dst, per-beat-capable destination protocols (no TileLink), the FP16 width cap, and that the requested op is elaborated (EnableCompute/ComputeOps).Ops (selected via
compute_cfg.compute_op, same programming model as transpose):COMPUTE_MXQUANTCOMPUTE_MXQUANT_FP16COMPUTE_MXDEQUANTMX block layout is inline
[1B E8M0 scale][32B E5M2]. The quantizer is RNE with full subnormal, saturation and Inf/NaN handling, bit-exact with the viDMA ALCU reference (the split normal/subnormal rounding bands are load-bearing; do not merge them).Validation
Byte-exact against a DPI-C golden (
test/idma_mxquant_dpi.c, pure integer pipeline) on Questa 2026.1 at every legal StrbWidth (DataWidth 32/64/128/256/512/1024):tb_idma_mxquant: FP16 and FP32 sources, a genuine partial 33B tail beat, a 4K page-crossing write.tb_idma_mxroundtrip: quant -> dequant back-to-back through one backend, byte-exact at both stages (the exact E5M2 identity); FP16 leg at 512b, FP32 leg at 1024b (256 blocks, 32KB legs).tb_idma_mxrand: constrained-random campaign — 40 serialized transfers per run with a random op each (FP16/FP32 quant, dequant, plain unaligned copy), random block counts, writes biased across 4K boundaries, behind an AXI shim injecting 40% random per-channel stalls; canary bytes fence each destination.tb_idma_mxneg: every compute guard assert proven to fire (9 cases, incl. transfer overlap tripping the sub-unit fatal). Note this PR also adds+define+INC_ASSERTto the sim flow — without itASSERT_NEVERcompiles to nothing, so the legalizer guard asserts (including pre-existing ones) were inert in simulation.tb_idma_transpose_b2b/tb_idma_transpose_ndunchanged and green (backward compatibility).tb_idma_mxperf: steady-state throughput vs a plain-copy baseline on ideal memory — the bottleneck channel (quant: R, dequant: W) sustains 100% bus utilization at every StrbWidth, both for single transfers and for pipelined back-to-back streams (aggregate window across 8 transfers including the boundaries); the other channel sits at the compression ratio (e.g. 33/128). Three microarchitectural points make this hold: pack-buffer space only gates block-completing input beats, the dequant pack buffer carries one expanded-block window of refill-during-drain headroom, and lane-exact retire keeps tails sound across transfer boundaries. The pipelined quant stream is also checked byte-exact under the random-stall shim intb_idma_mxrand.Known scope / disclosures
idma_backend_rw_axi. Size-changing compute on non-AXI src/dst is fenced withNOT IMPLEMENTEDasserts (ComputeMxSrcProtocol/ComputeMxDstProtocol) until validated; OBI is the natural first candidate (its write ready is already per-beat). Transpose keeps its pre-existing protocol scope.$fatalin the dispatcher (config change while busy) and in the MX sub-units (clear with in-flight state) instead of corrupting silently.tb_idma_mxneg).ComputeOpsdefaults to'1: existingEnableComputedesigns gain the MX engines on regeneration (area); setComputeOpsexplicitly to opt out.BufferDepth=3,MemSysDepth=0, 1D transfers only.