From f037c35dd326f388a7790e8b7974ff5de20056ec Mon Sep 17 00:00:00 2001 From: booth-algo Date: Tue, 2 Jun 2026 23:01:41 +0100 Subject: [PATCH] fix(im2col): enable the V_SHIFT_V im2col path for non-64-aligned columns (native-dim vision) The shift im2col already loads each patch at its exact pixel_col (patch at [0:K]) and places it with mask + right-shift; only a stale compiler-side assertion required pixel_col to be 64-aligned. That assertion predated the emulator's byte-block HBM gather (dma::transfer_mx_from_hbm, #62), which now walks the load one 64-byte block at a time and handles non-64-aligned starts. Removing the assertion lets the shift path (CONV_USE_SHIFT=1) run for stride-16 patch embedding. Verified: SmolVLM2 vision 64/64/16 1L emulates with allclose 100% PASS. No emulator change. Still opt-in (default stays im2col_asm_no_shift). --- asm_templates/im2col_asm.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/asm_templates/im2col_asm.py b/asm_templates/im2col_asm.py index 780d5d5..6edd6a5 100644 --- a/asm_templates/im2col_asm.py +++ b/asm_templates/im2col_asm.py @@ -125,13 +125,12 @@ def im2col_asm( if W_padded is None: W_padded = W - # Validate HBM alignment: every pixel column offset must be 64-aligned. - for ow in range(OW): - pixel_col = ow * stride - assert pixel_col % 64 == 0, ( - f"im2col_asm: ow={ow}, pixel_col={pixel_col} is not 64-aligned. " - f"Use im2col_asm_no_shift for stride={stride} with non-64-aligned columns." - ) + # HBM alignment: each H_PREFETCH_V load starts at the exact pixel_col, so the K + # patch elements land at [0:K] of the loaded vector and the mask+right-shift below + # places them. The emulator's HBM gather walks the byte range one 64-byte block at a + # time, clamping each read to a block boundary (dma::transfer_mx_from_hbm), so a + # non-64-aligned pixel_col (e.g. stride-16 patch embedding) is loaded correctly + # without any realignment. (The old 64-aligned-only assertion predated that gather.) # Compute save f_regs for precious fp_sram slots (mirrors im2col_asm_no_shift). # Mask construction zeroes fp_sram[0..VLEN-1] then writes mask values, corrupting