char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
0a50d9909
char/aliceai-t5-moe
1#include "hmx-utils.h" 2#include "hmx-queue.h" 3 4// MXFP4 dequantization LUT: maps 4-bit index to fp16 mantissa value 5// kvalues: 0, 0.5, 1, 1.5, 2, 3, 4, 6, 0, -0.5, -1, -1.5, -2, -3, -4, -6 6static const __fp16 mxfp4_to_fp16_lut [64 ] __attribute__((aligned (VLEN )))= { 70 ,0 ,0.5 ,0 ,1 ,0 ,1.5 ,0 ,2 ,0 ,3 ,0 ,4 ,0 ,6 ,0 ,0 ,0 ,-0.5 ,0 ,-1 ,0 ,-1.5 ,0 ,-2 ,0 ,-3 ,0 ,-4 ,0 ,-6 ,0 , 8}; 9 10static const __fp16 iq4_nl_to_fp16_lut [64 ] __attribute__((aligned (VLEN )))= { 11-127 ,0 ,-104 ,0 ,-83 ,0 ,-65 ,0 ,-49 ,0 ,-35 ,0 ,-22 ,0 ,-10 ,0 , 121 ,0 ,13 ,0 ,25 ,0 ,38 ,0 ,53 ,0 ,69 ,0 ,89 ,0 ,113 ,0 , 13}; 14 15// --- tiled format dequantizers --- 16 17typedef struct { 18struct htp_context * ctx ; 19struct htp_thread_trace * traces ; 20__fp16 * dst ; 21const uint8_t * src ; 22 23struct fastdiv_values n_k_tiles_div ; 24uint32_t n_k_tiles ; 25uint32_t n_tot_tiles ; 26uint32_t n_tiles_per_task ; 27uint32_t tile_size ; 28uint32_t aligned_tile_size ; 29uint32_t n_tasks ; 30uint32_t n_cols ; 31uint32_t k_block ; 32size_t row_stride ; 33uint32_t weight_type ; 34}tiled_dequantize_state_t ; 35 36// Dequantize a single tile from tiled weight data (already in VTCM) to tile-major FP16. 37static void dequantize_tiled_weight_to_fp16_task_q4_0 ( 38const tiled_dequantize_state_t * state , 39uint32_t start_tile ,uint32_t end_tile ) { 40 41const HVX_Vector mask_h4 = Q6_Vb_vsplat_R (0x0F ); 42const HVX_Vector i8 = Q6_Vb_vsplat_R (8 ); 43 44for (uint32_t t = start_tile ;t < end_tile ;t ++ ) { 45const uint8_t * tile_src = state -> src + t * state -> aligned_tile_size ; 46__fp16 * dst_ptr = state -> dst + t * HTP_MM_HMX_TILE_N_ELMS ; 47 48HVX_Vector v_sc = hvx_vmem (tile_src + 512 ); 49HVX_Vector v_scale_duplicated = Q6_V_lo_W (Q6_W_vshuff_VVR (v_sc ,v_sc ,-2 )); 50 51// Load all 4 groups in parallel 52HVX_Vector vq0 = hvx_vmem (tile_src + 0 * 128 ); 53HVX_Vector vq1 = hvx_vmem (tile_src + 1 * 128 ); 54HVX_Vector vq2 = hvx_vmem (tile_src + 2 * 128 ); 55HVX_Vector vq3 = hvx_vmem (tile_src + 3 * 128 ); 56 57// Nibble extraction 58HVX_Vector v_lo0 = Q6_V_vand_VV (vq0 ,mask_h4 ); 59HVX_Vector v_hi0 = Q6_Vub_vlsr_VubR (vq0 ,4 ); 60HVX_Vector v_lo1 = Q6_V_vand_VV (vq1 ,mask_h4 ); 61HVX_Vector v_hi1 = Q6_Vub_vlsr_VubR (vq1 ,4 ); 62HVX_Vector v_lo2 = Q6_V_vand_VV (vq2 ,mask_h4 ); 63HVX_Vector v_hi2 = Q6_Vub_vlsr_VubR (vq2 ,4 ); 64HVX_Vector v_lo3 = Q6_V_vand_VV (vq3 ,mask_h4 ); 65HVX_Vector v_hi3 = Q6_Vub_vlsr_VubR (vq3 ,4 ); 66 67// Offsetting (-8) 68v_lo0 = Q6_Vb_vsub_VbVb (v_lo0 ,i8 ); 69v_hi0 = Q6_Vb_vsub_VbVb (v_hi0 ,i8 ); 70v_lo1 = Q6_Vb_vsub_VbVb (v_lo1 ,i8 ); 71v_hi1 = Q6_Vb_vsub_VbVb (v_hi1 ,i8 ); 72v_lo2 = Q6_Vb_vsub_VbVb (v_lo2 ,i8 ); 73v_hi2 = Q6_Vb_vsub_VbVb (v_hi2 ,i8 ); 74v_lo3 = Q6_Vb_vsub_VbVb (v_lo3 ,i8 ); 75v_hi3 = Q6_Vb_vsub_VbVb (v_hi3 ,i8 ); 76 77// Shuffling 78HVX_VectorPair vp_shuf0 = Q6_W_vshuff_VVR (v_hi0 ,v_lo0 ,-1 ); 79HVX_VectorPair vp_shuf1 = Q6_W_vshuff_VVR (v_hi1 ,v_lo1 ,-1 ); 80HVX_VectorPair vp_shuf2 = Q6_W_vshuff_VVR (v_hi2 ,v_lo2 ,-1 ); 81HVX_VectorPair vp_shuf3 = Q6_W_vshuff_VVR (v_hi3 ,v_lo3 ,-1 ); 82 83// Unpack to 16-bit 84HVX_VectorPair vp_int16_lo0 = Q6_Wh_vunpack_Vb (Q6_V_lo_W (vp_shuf0 )); 85HVX_VectorPair vp_int16_hi0 = Q6_Wh_vunpack_Vb (Q6_V_hi_W (vp_shuf0 )); 86HVX_VectorPair vp_int16_lo1 = Q6_Wh_vunpack_Vb (Q6_V_lo_W (vp_shuf1 )); 87HVX_VectorPair vp_int16_hi1 = Q6_Wh_vunpack_Vb (Q6_V_hi_W (vp_shuf1 )); 88HVX_VectorPair vp_int16_lo2 = Q6_Wh_vunpack_Vb (Q6_V_lo_W (vp_shuf2 )); 89HVX_VectorPair vp_int16_hi2 = Q6_Wh_vunpack_Vb (Q6_V_hi_W (vp_shuf2 )); 90HVX_VectorPair vp_int16_lo3 = Q6_Wh_vunpack_Vb (Q6_V_lo_W (vp_shuf3 )); 91HVX_VectorPair vp_int16_hi3 = Q6_Wh_vunpack_Vb (Q6_V_hi_W (vp_shuf3 )); 92 93// Convert and scale multiplication 94HVX_Vector v_grp0_0 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_lo_W (vp_int16_lo0 )),v_scale_duplicated )); 95HVX_Vector v_grp0_1 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_hi_W (vp_int16_lo0 )),v_scale_duplicated )); 96HVX_Vector v_grp0_2 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_lo_W (vp_int16_hi0 )),v_scale_duplicated )); 97HVX_Vector v_grp0_3 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_hi_W (vp_int16_hi0 )),v_scale_duplicated )); 98 99HVX_Vector v_grp1_0 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_lo_W (vp_int16_lo1 )),v_scale_duplicated )); 100HVX_Vector v_grp1_1 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_hi_W (vp_int16_lo1 )),v_scale_duplicated )); 101HVX_Vector v_grp1_2 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_lo_W (vp_int16_hi1 )),v_scale_duplicated )); 102HVX_Vector v_grp1_3 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_hi_W (vp_int16_hi1 )),v_scale_duplicated )); 103 104HVX_Vector v_grp2_0 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_lo_W (vp_int16_lo2 )),v_scale_duplicated )); 105HVX_Vector v_grp2_1 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_hi_W (vp_int16_lo2 )),v_scale_duplicated )); 106HVX_Vector v_grp2_2 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_lo_W (vp_int16_hi2 )),v_scale_duplicated )); 107HVX_Vector v_grp2_3 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_hi_W (vp_int16_hi2 )),v_scale_duplicated )); 108 109HVX_Vector v_grp3_0 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_lo_W (vp_int16_lo3 )),v_scale_duplicated )); 110HVX_Vector v_grp3_1 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_hi_W (vp_int16_lo3 )),v_scale_duplicated )); 111HVX_Vector v_grp3_2 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_lo_W (vp_int16_hi3 )),v_scale_duplicated )); 112HVX_Vector v_grp3_3 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_hi_W (vp_int16_hi3 )),v_scale_duplicated )); 113 114hvx_vmem (dst_ptr + 0 * 64 )= v_grp0_0 ; 115hvx_vmem (dst_ptr + 1 * 64 )= v_grp0_1 ; 116hvx_vmem (dst_ptr + 2 * 64 )= v_grp0_2 ; 117hvx_vmem (dst_ptr + 3 * 64 )= v_grp0_3 ; 118 119hvx_vmem (dst_ptr + 4 * 64 )= v_grp1_0 ; 120hvx_vmem (dst_ptr + 5 * 64 )= v_grp1_1 ; 121hvx_vmem (dst_ptr + 6 * 64 )= v_grp1_2 ; 122hvx_vmem (dst_ptr + 7 * 64 )= v_grp1_3 ; 123 124hvx_vmem (dst_ptr + 8 * 64 )= v_grp2_0 ; 125hvx_vmem (dst_ptr + 9 * 64 )= v_grp2_1 ; 126hvx_vmem (dst_ptr + 10 * 64 )= v_grp2_2 ; 127hvx_vmem (dst_ptr + 11 * 64 )= v_grp2_3 ; 128 129hvx_vmem (dst_ptr + 12 * 64 )= v_grp3_0 ; 130hvx_vmem (dst_ptr + 13 * 64 )= v_grp3_1 ; 131hvx_vmem (dst_ptr + 14 * 64 )= v_grp3_2 ; 132hvx_vmem (dst_ptr + 15 * 64 )= v_grp3_3 ; 133 } 134} 135 136static void dequantize_tiled_weight_to_fp16_task_q4_1 ( 137const tiled_dequantize_state_t * state , 138uint32_t start_tile ,uint32_t end_tile ) { 139 140const HVX_Vector mask_h4 = Q6_Vb_vsplat_R (0x0F ); 141 142for (uint32_t t = start_tile ;t < end_tile ;t ++ ) { 143const uint8_t * tile_src = state -> src + t * state -> aligned_tile_size ; 144__fp16 * dst_ptr = state -> dst + t * HTP_MM_HMX_TILE_N_ELMS ; 145 146HVX_Vector vscale_offset = hvx_vmem (tile_src + 512 ); 147HVX_VectorPair dm_deal = Q6_W_vdeal_VVR (vscale_offset ,vscale_offset ,-2 ); 148HVX_Vector vd = Q6_V_lo_W (dm_deal ); 149HVX_Vector vm = Q6_V_hi_W (dm_deal ); 150 151HVX_Vector v_scale_duplicated = Q6_V_lo_W (Q6_W_vshuff_VVR (vd ,vd ,-2 )); 152HVX_Vector v_offset_duplicated = Q6_V_lo_W (Q6_W_vshuff_VVR (vm ,vm ,-2 )); 153 154// Load all 4 groups in parallel 155HVX_Vector vq0 = hvx_vmem (tile_src + 0 * 128 ); 156HVX_Vector vq1 = hvx_vmem (tile_src + 1 * 128 ); 157HVX_Vector vq2 = hvx_vmem (tile_src + 2 * 128 ); 158HVX_Vector vq3 = hvx_vmem (tile_src + 3 * 128 ); 159 160// Nibble extraction 161HVX_Vector v_lo0 = Q6_V_vand_VV (vq0 ,mask_h4 ); 162HVX_Vector v_hi0 = Q6_Vub_vlsr_VubR (vq0 ,4 ); 163HVX_Vector v_lo1 = Q6_V_vand_VV (vq1 ,mask_h4 ); 164HVX_Vector v_hi1 = Q6_Vub_vlsr_VubR (vq1 ,4 ); 165HVX_Vector v_lo2 = Q6_V_vand_VV (vq2 ,mask_h4 ); 166HVX_Vector v_hi2 = Q6_Vub_vlsr_VubR (vq2 ,4 ); 167HVX_Vector v_lo3 = Q6_V_vand_VV (vq3 ,mask_h4 ); 168HVX_Vector v_hi3 = Q6_Vub_vlsr_VubR (vq3 ,4 ); 169 170// Shuffling 171HVX_VectorPair vp_shuf0 = Q6_W_vshuff_VVR (v_hi0 ,v_lo0 ,-1 ); 172HVX_VectorPair vp_shuf1 = Q6_W_vshuff_VVR (v_hi1 ,v_lo1 ,-1 ); 173HVX_VectorPair vp_shuf2 = Q6_W_vshuff_VVR (v_hi2 ,v_lo2 ,-1 ); 174HVX_VectorPair vp_shuf3 = Q6_W_vshuff_VVR (v_hi3 ,v_lo3 ,-1 ); 175 176// Unpack to 16-bit 177HVX_VectorPair vp_int16_lo0 = Q6_Wh_vunpack_Vb (Q6_V_lo_W (vp_shuf0 )); 178HVX_VectorPair vp_int16_hi0 = Q6_Wh_vunpack_Vb (Q6_V_hi_W (vp_shuf0 )); 179HVX_VectorPair vp_int16_lo1 = Q6_Wh_vunpack_Vb (Q6_V_lo_W (vp_shuf1 )); 180HVX_VectorPair vp_int16_hi1 = Q6_Wh_vunpack_Vb (Q6_V_hi_W (vp_shuf1 )); 181HVX_VectorPair vp_int16_lo2 = Q6_Wh_vunpack_Vb (Q6_V_lo_W (vp_shuf2 )); 182HVX_VectorPair vp_int16_hi2 = Q6_Wh_vunpack_Vb (Q6_V_hi_W (vp_shuf2 )); 183HVX_VectorPair vp_int16_lo3 = Q6_Wh_vunpack_Vb (Q6_V_lo_W (vp_shuf3 )); 184HVX_VectorPair vp_int16_hi3 = Q6_Wh_vunpack_Vb (Q6_V_hi_W (vp_shuf3 )); 185 186// Convert, multiply, add offset 187HVX_Vector v_grp0_0 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vadd_Vqf16Vhf (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_lo_W (vp_int16_lo0 )),v_scale_duplicated ),v_offset_duplicated )); 188HVX_Vector v_grp0_1 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vadd_Vqf16Vhf (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_hi_W (vp_int16_lo0 )),v_scale_duplicated ),v_offset_duplicated )); 189HVX_Vector v_grp0_2 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vadd_Vqf16Vhf (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_lo_W (vp_int16_hi0 )),v_scale_duplicated ),v_offset_duplicated )); 190HVX_Vector v_grp0_3 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vadd_Vqf16Vhf (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_hi_W (vp_int16_hi0 )),v_scale_duplicated ),v_offset_duplicated )); 191 192HVX_Vector v_grp1_0 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vadd_Vqf16Vhf (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_lo_W (vp_int16_lo1 )),v_scale_duplicated ),v_offset_duplicated )); 193HVX_Vector v_grp1_1 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vadd_Vqf16Vhf (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_hi_W (vp_int16_lo1 )),v_scale_duplicated ),v_offset_duplicated )); 194HVX_Vector v_grp1_2 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vadd_Vqf16Vhf (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_lo_W (vp_int16_hi1 )),v_scale_duplicated ),v_offset_duplicated )); 195HVX_Vector v_grp1_3 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vadd_Vqf16Vhf (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_hi_W (vp_int16_hi1 )),v_scale_duplicated ),v_offset_duplicated )); 196 197HVX_Vector v_grp2_0 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vadd_Vqf16Vhf (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_lo_W (vp_int16_lo2 )),v_scale_duplicated ),v_offset_duplicated )); 198HVX_Vector v_grp2_1 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vadd_Vqf16Vhf (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_hi_W (vp_int16_lo2 )),v_scale_duplicated ),v_offset_duplicated )); 199HVX_Vector v_grp2_2 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vadd_Vqf16Vhf (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_lo_W (vp_int16_hi2 )),v_scale_duplicated ),v_offset_duplicated )); 200HVX_Vector v_grp2_3 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vadd_Vqf16Vhf (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_hi_W (vp_int16_hi2 )),v_scale_duplicated ),v_offset_duplicated )); 201 202HVX_Vector v_grp3_0 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vadd_Vqf16Vhf (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_lo_W (vp_int16_lo3 )),v_scale_duplicated ),v_offset_duplicated )); 203HVX_Vector v_grp3_1 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vadd_Vqf16Vhf (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_hi_W (vp_int16_lo3 )),v_scale_duplicated ),v_offset_duplicated )); 204HVX_Vector v_grp3_2 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vadd_Vqf16Vhf (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_lo_W (vp_int16_hi3 )),v_scale_duplicated ),v_offset_duplicated )); 205HVX_Vector v_grp3_3 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vadd_Vqf16Vhf (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_hi_W (vp_int16_hi3 )),v_scale_duplicated ),v_offset_duplicated )); 206 207// Parallel Stores 208hvx_vmem (dst_ptr + 0 * 64 )= v_grp0_0 ; 209hvx_vmem (dst_ptr + 1 * 64 )= v_grp0_1 ; 210hvx_vmem (dst_ptr + 2 * 64 )= v_grp0_2 ; 211hvx_vmem (dst_ptr + 3 * 64 )= v_grp0_3 ; 212 213hvx_vmem (dst_ptr + 4 * 64 )= v_grp1_0 ; 214hvx_vmem (dst_ptr + 5 * 64 )= v_grp1_1 ; 215hvx_vmem (dst_ptr + 6 * 64 )= v_grp1_2 ; 216hvx_vmem (dst_ptr + 7 * 64 )= v_grp1_3 ; 217 218hvx_vmem (dst_ptr + 8 * 64 )= v_grp2_0 ; 219hvx_vmem (dst_ptr + 9 * 64 )= v_grp2_1 ; 220hvx_vmem (dst_ptr + 10 * 64 )= v_grp2_2 ; 221hvx_vmem (dst_ptr + 11 * 64 )= v_grp2_3 ; 222 223hvx_vmem (dst_ptr + 12 * 64 )= v_grp3_0 ; 224hvx_vmem (dst_ptr + 13 * 64 )= v_grp3_1 ; 225hvx_vmem (dst_ptr + 14 * 64 )= v_grp3_2 ; 226hvx_vmem (dst_ptr + 15 * 64 )= v_grp3_3 ; 227 } 228} 229 230static void dequantize_tiled_weight_to_fp16_task_iq4_nl ( 231const tiled_dequantize_state_t * state , 232uint32_t start_tile ,uint32_t end_tile ) { 233 234const HVX_Vector mask_h4 = Q6_Vb_vsplat_R (0x0F ); 235const HVX_Vector vlut_cvt = hvx_vmem (iq4_nl_to_fp16_lut ); 236 237for (uint32_t t = start_tile ;t < end_tile ;t ++ ) { 238const uint8_t * tile_src = state -> src + t * state -> aligned_tile_size ; 239__fp16 * dst_ptr = state -> dst + t * HTP_MM_HMX_TILE_N_ELMS ; 240 241HVX_Vector v_sc = hvx_vmem (tile_src + 512 ); 242HVX_Vector v_scale_duplicated = Q6_V_lo_W (Q6_W_vshuff_VVR (v_sc ,v_sc ,-2 )); 243 244// Load all 4 groups in parallel 245HVX_Vector vq0 = hvx_vmem (tile_src + 0 * 128 ); 246HVX_Vector vq1 = hvx_vmem (tile_src + 1 * 128 ); 247HVX_Vector vq2 = hvx_vmem (tile_src + 2 * 128 ); 248HVX_Vector vq3 = hvx_vmem (tile_src + 3 * 128 ); 249 250// Nibble extraction 251HVX_Vector v_lo0 = Q6_V_vand_VV (vq0 ,mask_h4 ); 252HVX_Vector v_hi0 = Q6_Vub_vlsr_VubR (vq0 ,4 ); 253HVX_Vector v_lo1 = Q6_V_vand_VV (vq1 ,mask_h4 ); 254HVX_Vector v_hi1 = Q6_Vub_vlsr_VubR (vq1 ,4 ); 255HVX_Vector v_lo2 = Q6_V_vand_VV (vq2 ,mask_h4 ); 256HVX_Vector v_hi2 = Q6_Vub_vlsr_VubR (vq2 ,4 ); 257HVX_Vector v_lo3 = Q6_V_vand_VV (vq3 ,mask_h4 ); 258HVX_Vector v_hi3 = Q6_Vub_vlsr_VubR (vq3 ,4 ); 259 260// Shuffling 261HVX_VectorPair vp_shuf0 = Q6_W_vshuff_VVR (v_hi0 ,v_lo0 ,-1 ); 262HVX_VectorPair vp_shuf1 = Q6_W_vshuff_VVR (v_hi1 ,v_lo1 ,-1 ); 263HVX_VectorPair vp_shuf2 = Q6_W_vshuff_VVR (v_hi2 ,v_lo2 ,-1 ); 264HVX_VectorPair vp_shuf3 = Q6_W_vshuff_VVR (v_hi3 ,v_lo3 ,-1 ); 265 266// Shuffle for LUT lookup 267HVX_Vector v_q_lo0 = Q6_Vb_vshuff_Vb (Q6_V_lo_W (vp_shuf0 )); 268HVX_Vector v_q_hi0 = Q6_Vb_vshuff_Vb (Q6_V_hi_W (vp_shuf0 )); 269HVX_Vector v_q_lo1 = Q6_Vb_vshuff_Vb (Q6_V_lo_W (vp_shuf1 )); 270HVX_Vector v_q_hi1 = Q6_Vb_vshuff_Vb (Q6_V_hi_W (vp_shuf1 )); 271HVX_Vector v_q_lo2 = Q6_Vb_vshuff_Vb (Q6_V_lo_W (vp_shuf2 )); 272HVX_Vector v_q_hi2 = Q6_Vb_vshuff_Vb (Q6_V_hi_W (vp_shuf2 )); 273HVX_Vector v_q_lo3 = Q6_Vb_vshuff_Vb (Q6_V_lo_W (vp_shuf3 )); 274HVX_Vector v_q_hi3 = Q6_Vb_vshuff_Vb (Q6_V_hi_W (vp_shuf3 )); 275 276// LUT lookup 277HVX_VectorPair vp_lo0 = Q6_Wh_vlut16_VbVhR (v_q_lo0 ,vlut_cvt ,0 ); 278HVX_VectorPair vp_hi0 = Q6_Wh_vlut16_VbVhR (v_q_hi0 ,vlut_cvt ,0 ); 279HVX_VectorPair vp_lo1 = Q6_Wh_vlut16_VbVhR (v_q_lo1 ,vlut_cvt ,0 ); 280HVX_VectorPair vp_hi1 = Q6_Wh_vlut16_VbVhR (v_q_hi1 ,vlut_cvt ,0 ); 281HVX_VectorPair vp_lo2 = Q6_Wh_vlut16_VbVhR (v_q_lo2 ,vlut_cvt ,0 ); 282HVX_VectorPair vp_hi2 = Q6_Wh_vlut16_VbVhR (v_q_hi2 ,vlut_cvt ,0 ); 283HVX_VectorPair vp_lo3 = Q6_Wh_vlut16_VbVhR (v_q_lo3 ,vlut_cvt ,0 ); 284HVX_VectorPair vp_hi3 = Q6_Wh_vlut16_VbVhR (v_q_hi3 ,vlut_cvt ,0 ); 285 286// Convert and scale multiplication 287HVX_Vector v_grp0_0 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_lo_W (vp_lo0 ),v_scale_duplicated )); 288HVX_Vector v_grp0_1 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_hi_W (vp_lo0 ),v_scale_duplicated )); 289HVX_Vector v_grp0_2 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_lo_W (vp_hi0 ),v_scale_duplicated )); 290HVX_Vector v_grp0_3 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_hi_W (vp_hi0 ),v_scale_duplicated )); 291 292HVX_Vector v_grp1_0 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_lo_W (vp_lo1 ),v_scale_duplicated )); 293HVX_Vector v_grp1_1 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_hi_W (vp_lo1 ),v_scale_duplicated )); 294HVX_Vector v_grp1_2 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_lo_W (vp_hi1 ),v_scale_duplicated )); 295HVX_Vector v_grp1_3 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_hi_W (vp_hi1 ),v_scale_duplicated )); 296 297HVX_Vector v_grp2_0 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_lo_W (vp_lo2 ),v_scale_duplicated )); 298HVX_Vector v_grp2_1 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_hi_W (vp_lo2 ),v_scale_duplicated )); 299HVX_Vector v_grp2_2 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_lo_W (vp_hi2 ),v_scale_duplicated )); 300HVX_Vector v_grp2_3 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_hi_W (vp_hi2 ),v_scale_duplicated )); 301 302HVX_Vector v_grp3_0 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_lo_W (vp_lo3 ),v_scale_duplicated )); 303HVX_Vector v_grp3_1 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_hi_W (vp_lo3 ),v_scale_duplicated )); 304HVX_Vector v_grp3_2 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_lo_W (vp_hi3 ),v_scale_duplicated )); 305HVX_Vector v_grp3_3 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_hi_W (vp_hi3 ),v_scale_duplicated )); 306 307hvx_vmem (dst_ptr + 0 * 64 )= v_grp0_0 ; 308hvx_vmem (dst_ptr + 1 * 64 )= v_grp0_1 ; 309hvx_vmem (dst_ptr + 2 * 64 )= v_grp0_2 ; 310hvx_vmem (dst_ptr + 3 * 64 )= v_grp0_3 ; 311 312hvx_vmem (dst_ptr + 4 * 64 )= v_grp1_0 ; 313hvx_vmem (dst_ptr + 5 * 64 )= v_grp1_1 ; 314hvx_vmem (dst_ptr + 6 * 64 )= v_grp1_2 ; 315hvx_vmem (dst_ptr + 7 * 64 )= v_grp1_3 ; 316 317hvx_vmem (dst_ptr + 8 * 64 )= v_grp2_0 ; 318hvx_vmem (dst_ptr + 9 * 64 )= v_grp2_1 ; 319hvx_vmem (dst_ptr + 10 * 64 )= v_grp2_2 ; 320hvx_vmem (dst_ptr + 11 * 64 )= v_grp2_3 ; 321 322hvx_vmem (dst_ptr + 12 * 64 )= v_grp3_0 ; 323hvx_vmem (dst_ptr + 13 * 64 )= v_grp3_1 ; 324hvx_vmem (dst_ptr + 14 * 64 )= v_grp3_2 ; 325hvx_vmem (dst_ptr + 15 * 64 )= v_grp3_3 ; 326 } 327} 328 329static void dequantize_tiled_weight_to_fp16_task_mxfp4 ( 330const tiled_dequantize_state_t * state , 331uint32_t start_tile ,uint32_t end_tile ) { 332 333const HVX_Vector mask_h4 = Q6_Vb_vsplat_R (0x0F ); 334const HVX_Vector vlut_cvt = hvx_vmem (mxfp4_to_fp16_lut ); 335 336for (uint32_t t = start_tile ;t < end_tile ;t ++ ) { 337const uint8_t * tile_src = state -> src + t * state -> aligned_tile_size ; 338__fp16 * dst_ptr = state -> dst + t * HTP_MM_HMX_TILE_N_ELMS ; 339 340HVX_Vector v = hvx_vmem (tile_src + 512 ); 341HVX_Vector vh = Q6_V_lo_W (Q6_Wuh_vunpack_Vub (v )); 342vh = Q6_Vh_vsub_VhVh (vh ,Q6_Vh_vsplat_R (112 )); 343vh = Q6_Vh_vmax_VhVh (vh ,Q6_V_vzero ()); 344vh = Q6_Vh_vmin_VhVh (vh ,Q6_Vh_vsplat_R (30 )); 345vh = Q6_Vh_vasl_VhR (vh ,10 ); 346 347HVX_Vector v_scale_duplicated = Q6_V_lo_W (Q6_W_vshuff_VVR (vh ,vh ,-2 )); 348 349// Load all 4 groups in parallel 350HVX_Vector vq0 = hvx_vmem (tile_src + 0 * 128 ); 351HVX_Vector vq1 = hvx_vmem (tile_src + 1 * 128 ); 352HVX_Vector vq2 = hvx_vmem (tile_src + 2 * 128 ); 353HVX_Vector vq3 = hvx_vmem (tile_src + 3 * 128 ); 354 355// Nibble extraction 356HVX_Vector v_lo0 = Q6_V_vand_VV (vq0 ,mask_h4 ); 357HVX_Vector v_hi0 = Q6_Vub_vlsr_VubR (vq0 ,4 ); 358HVX_Vector v_lo1 = Q6_V_vand_VV (vq1 ,mask_h4 ); 359HVX_Vector v_hi1 = Q6_Vub_vlsr_VubR (vq1 ,4 ); 360HVX_Vector v_lo2 = Q6_V_vand_VV (vq2 ,mask_h4 ); 361HVX_Vector v_hi2 = Q6_Vub_vlsr_VubR (vq2 ,4 ); 362HVX_Vector v_lo3 = Q6_V_vand_VV (vq3 ,mask_h4 ); 363HVX_Vector v_hi3 = Q6_Vub_vlsr_VubR (vq3 ,4 ); 364 365// Shuffling 366HVX_VectorPair vp_shuf0 = Q6_W_vshuff_VVR (v_hi0 ,v_lo0 ,-1 ); 367HVX_VectorPair vp_shuf1 = Q6_W_vshuff_VVR (v_hi1 ,v_lo1 ,-1 ); 368HVX_VectorPair vp_shuf2 = Q6_W_vshuff_VVR (v_hi2 ,v_lo2 ,-1 ); 369HVX_VectorPair vp_shuf3 = Q6_W_vshuff_VVR (v_hi3 ,v_lo3 ,-1 ); 370 371// Shuffle for LUT lookup 372HVX_Vector v_q_lo0 = Q6_Vb_vshuff_Vb (Q6_V_lo_W (vp_shuf0 )); 373HVX_Vector v_q_hi0 = Q6_Vb_vshuff_Vb (Q6_V_hi_W (vp_shuf0 )); 374HVX_Vector v_q_lo1 = Q6_Vb_vshuff_Vb (Q6_V_lo_W (vp_shuf1 )); 375HVX_Vector v_q_hi1 = Q6_Vb_vshuff_Vb (Q6_V_hi_W (vp_shuf1 )); 376HVX_Vector v_q_lo2 = Q6_Vb_vshuff_Vb (Q6_V_lo_W (vp_shuf2 )); 377HVX_Vector v_q_hi2 = Q6_Vb_vshuff_Vb (Q6_V_hi_W (vp_shuf2 )); 378HVX_Vector v_q_lo3 = Q6_Vb_vshuff_Vb (Q6_V_lo_W (vp_shuf3 )); 379HVX_Vector v_q_hi3 = Q6_Vb_vshuff_Vb (Q6_V_hi_W (vp_shuf3 )); 380 381// LUT lookup 382HVX_VectorPair vp_lo0 = Q6_Wh_vlut16_VbVhR (v_q_lo0 ,vlut_cvt ,0 ); 383HVX_VectorPair vp_hi0 = Q6_Wh_vlut16_VbVhR (v_q_hi0 ,vlut_cvt ,0 ); 384HVX_VectorPair vp_lo1 = Q6_Wh_vlut16_VbVhR (v_q_lo1 ,vlut_cvt ,0 ); 385HVX_VectorPair vp_hi1 = Q6_Wh_vlut16_VbVhR (v_q_hi1 ,vlut_cvt ,0 ); 386HVX_VectorPair vp_lo2 = Q6_Wh_vlut16_VbVhR (v_q_lo2 ,vlut_cvt ,0 ); 387HVX_VectorPair vp_hi2 = Q6_Wh_vlut16_VbVhR (v_q_hi2 ,vlut_cvt ,0 ); 388HVX_VectorPair vp_lo3 = Q6_Wh_vlut16_VbVhR (v_q_lo3 ,vlut_cvt ,0 ); 389HVX_VectorPair vp_hi3 = Q6_Wh_vlut16_VbVhR (v_q_hi3 ,vlut_cvt ,0 ); 390 391// Convert and scale multiplication 392HVX_Vector v_grp0_0 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_lo_W (vp_lo0 ),v_scale_duplicated )); 393HVX_Vector v_grp0_1 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_hi_W (vp_lo0 ),v_scale_duplicated )); 394HVX_Vector v_grp0_2 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_lo_W (vp_hi0 ),v_scale_duplicated )); 395HVX_Vector v_grp0_3 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_hi_W (vp_hi0 ),v_scale_duplicated )); 396 397HVX_Vector v_grp1_0 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_lo_W (vp_lo1 ),v_scale_duplicated )); 398HVX_Vector v_grp1_1 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_hi_W (vp_lo1 ),v_scale_duplicated )); 399HVX_Vector v_grp1_2 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_lo_W (vp_hi1 ),v_scale_duplicated )); 400HVX_Vector v_grp1_3 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_hi_W (vp_hi1 ),v_scale_duplicated )); 401 402HVX_Vector v_grp2_0 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_lo_W (vp_lo2 ),v_scale_duplicated )); 403HVX_Vector v_grp2_1 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_hi_W (vp_lo2 ),v_scale_duplicated )); 404HVX_Vector v_grp2_2 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_lo_W (vp_hi2 ),v_scale_duplicated )); 405HVX_Vector v_grp2_3 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_hi_W (vp_hi2 ),v_scale_duplicated )); 406 407HVX_Vector v_grp3_0 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_lo_W (vp_lo3 ),v_scale_duplicated )); 408HVX_Vector v_grp3_1 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_hi_W (vp_lo3 ),v_scale_duplicated )); 409HVX_Vector v_grp3_2 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_lo_W (vp_hi3 ),v_scale_duplicated )); 410HVX_Vector v_grp3_3 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_V_hi_W (vp_hi3 ),v_scale_duplicated )); 411 412hvx_vmem (dst_ptr + 0 * 64 )= v_grp0_0 ; 413hvx_vmem (dst_ptr + 1 * 64 )= v_grp0_1 ; 414hvx_vmem (dst_ptr + 2 * 64 )= v_grp0_2 ; 415hvx_vmem (dst_ptr + 3 * 64 )= v_grp0_3 ; 416 417hvx_vmem (dst_ptr + 4 * 64 )= v_grp1_0 ; 418hvx_vmem (dst_ptr + 5 * 64 )= v_grp1_1 ; 419hvx_vmem (dst_ptr + 6 * 64 )= v_grp1_2 ; 420hvx_vmem (dst_ptr + 7 * 64 )= v_grp1_3 ; 421 422hvx_vmem (dst_ptr + 8 * 64 )= v_grp2_0 ; 423hvx_vmem (dst_ptr + 9 * 64 )= v_grp2_1 ; 424hvx_vmem (dst_ptr + 10 * 64 )= v_grp2_2 ; 425hvx_vmem (dst_ptr + 11 * 64 )= v_grp2_3 ; 426 427hvx_vmem (dst_ptr + 12 * 64 )= v_grp3_0 ; 428hvx_vmem (dst_ptr + 13 * 64 )= v_grp3_1 ; 429hvx_vmem (dst_ptr + 14 * 64 )= v_grp3_2 ; 430hvx_vmem (dst_ptr + 15 * 64 )= v_grp3_3 ; 431 } 432} 433 434static void dequantize_tiled_weight_to_fp16_task_q8_0 ( 435const tiled_dequantize_state_t * state , 436uint32_t start_tile ,uint32_t end_tile ) { 437 438for (uint32_t t = start_tile ;t < end_tile ;t ++ ) { 439const uint8_t * tile_src = state -> src + t * state -> aligned_tile_size ; 440__fp16 * dst_ptr = state -> dst + t * HTP_MM_HMX_TILE_N_ELMS ; 441 442HVX_Vector v_sc = hvx_vmem (tile_src + 1024 ); 443HVX_Vector v_scale_duplicated = Q6_V_lo_W (Q6_W_vshuff_VVR (v_sc ,v_sc ,-2 )); 444 445// Load groups 0-3 in parallel 446HVX_Vector vq0 = hvx_vmem (tile_src + 0 * 128 ); 447HVX_Vector vq1 = hvx_vmem (tile_src + 1 * 128 ); 448HVX_Vector vq2 = hvx_vmem (tile_src + 2 * 128 ); 449HVX_Vector vq3 = hvx_vmem (tile_src + 3 * 128 ); 450 451HVX_VectorPair vp_int16_0 = Q6_Wh_vunpack_Vb (vq0 ); 452HVX_VectorPair vp_int16_1 = Q6_Wh_vunpack_Vb (vq1 ); 453HVX_VectorPair vp_int16_2 = Q6_Wh_vunpack_Vb (vq2 ); 454HVX_VectorPair vp_int16_3 = Q6_Wh_vunpack_Vb (vq3 ); 455 456// Load groups 4-7 in parallel 457HVX_Vector vq4 = hvx_vmem (tile_src + 4 * 128 ); 458HVX_Vector vq5 = hvx_vmem (tile_src + 5 * 128 ); 459HVX_Vector vq6 = hvx_vmem (tile_src + 6 * 128 ); 460HVX_Vector vq7 = hvx_vmem (tile_src + 7 * 128 ); 461 462HVX_VectorPair vp_int16_4 = Q6_Wh_vunpack_Vb (vq4 ); 463HVX_VectorPair vp_int16_5 = Q6_Wh_vunpack_Vb (vq5 ); 464HVX_VectorPair vp_int16_6 = Q6_Wh_vunpack_Vb (vq6 ); 465HVX_VectorPair vp_int16_7 = Q6_Wh_vunpack_Vb (vq7 ); 466 467// Convert and scale multiply for groups 0-3 468HVX_Vector v_grp0_0 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_lo_W (vp_int16_0 )),v_scale_duplicated )); 469HVX_Vector v_grp0_1 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_hi_W (vp_int16_0 )),v_scale_duplicated )); 470HVX_Vector v_grp1_0 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_lo_W (vp_int16_1 )),v_scale_duplicated )); 471HVX_Vector v_grp1_1 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_hi_W (vp_int16_1 )),v_scale_duplicated )); 472HVX_Vector v_grp2_0 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_lo_W (vp_int16_2 )),v_scale_duplicated )); 473HVX_Vector v_grp2_1 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_hi_W (vp_int16_2 )),v_scale_duplicated )); 474HVX_Vector v_grp3_0 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_lo_W (vp_int16_3 )),v_scale_duplicated )); 475HVX_Vector v_grp3_1 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_hi_W (vp_int16_3 )),v_scale_duplicated )); 476 477// Store groups 0-3 478hvx_vmem (dst_ptr + 0 * 64 )= v_grp0_0 ; 479hvx_vmem (dst_ptr + 1 * 64 )= v_grp0_1 ; 480hvx_vmem (dst_ptr + 2 * 64 )= v_grp1_0 ; 481hvx_vmem (dst_ptr + 3 * 64 )= v_grp1_1 ; 482hvx_vmem (dst_ptr + 4 * 64 )= v_grp2_0 ; 483hvx_vmem (dst_ptr + 5 * 64 )= v_grp2_1 ; 484hvx_vmem (dst_ptr + 6 * 64 )= v_grp3_0 ; 485hvx_vmem (dst_ptr + 7 * 64 )= v_grp3_1 ; 486 487// Convert and scale multiply for groups 4-7 488HVX_Vector v_grp4_0 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_lo_W (vp_int16_4 )),v_scale_duplicated )); 489HVX_Vector v_grp4_1 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_hi_W (vp_int16_4 )),v_scale_duplicated )); 490HVX_Vector v_grp5_0 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_lo_W (vp_int16_5 )),v_scale_duplicated )); 491HVX_Vector v_grp5_1 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_hi_W (vp_int16_5 )),v_scale_duplicated )); 492HVX_Vector v_grp6_0 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_lo_W (vp_int16_6 )),v_scale_duplicated )); 493HVX_Vector v_grp6_1 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_hi_W (vp_int16_6 )),v_scale_duplicated )); 494HVX_Vector v_grp7_0 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_lo_W (vp_int16_7 )),v_scale_duplicated )); 495HVX_Vector v_grp7_1 = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vmpy_VhfVhf (Q6_Vhf_equals_Vh (Q6_V_hi_W (vp_int16_7 )),v_scale_duplicated )); 496 497// Store groups 4-7 498hvx_vmem (dst_ptr + 8 * 64 )= v_grp4_0 ; 499hvx_vmem (dst_ptr + 9 * 64 )= v_grp4_1 ; 500hvx_vmem (dst_ptr + 10 * 64 )= v_grp5_0 ; 501hvx_vmem (dst_ptr + 11 * 64 )= v_grp5_1 ; 502hvx_vmem (dst_ptr + 12 * 64 )= v_grp6_0 ; 503hvx_vmem (dst_ptr + 13 * 64 )= v_grp6_1 ; 504hvx_vmem (dst_ptr + 14 * 64 )= v_grp7_0 ; 505hvx_vmem (dst_ptr + 15 * 64 )= v_grp7_1 ; 506 } 507} 508 509static __attribute__((noinline )) 510void convert_f16_weight_to_fp16_tiles_task ( 511const tiled_dequantize_state_t * state , 512uint32_t start_tile ,uint32_t end_tile ) { 513 514const uint32_t n_k_tiles = state -> n_k_tiles ; 515const struct fastdiv_values n_k_tiles_div = state -> n_k_tiles_div ; 516 517const HVX_Vector v_scat_base = hvx_vmem (hmx_transpose_scatter_offsets ); 518const HVX_Vector v_scat_step = Q6_V_vsplat_R (4 ); 519const HVX_VectorPred q_mask64 = Q6_Q_vsetq_R (64 ); 520 521unsigned ct = fastdiv ((unsigned )start_tile ,& n_k_tiles_div ); 522unsigned kt = fastmodulo ((unsigned )start_tile ,n_k_tiles ,& n_k_tiles_div ); 523 524for (unsigned t = start_tile ;t < (unsigned )end_tile ; ) { 525if (kt >= (unsigned )n_k_tiles ) {kt = 0 ;ct ++ ; } 526 527__fp16 * tile_base = state -> dst + t * HTP_MM_HMX_TILE_N_ELMS ; 528 { 529uint32_t byte_off = kt * 32 * sizeof (__fp16 ); 530 531HVX_Vector v_off = v_scat_base ; 532for (uint32_t r = 0 ;r < HTP_MM_HMX_TILE_N_ROWS ;r += 2 ) { 533uint32_t row0 = ct * HTP_MM_HMX_TILE_N_COLS + r ; 534uint32_t row1 = row0 + 1 ; 535 536const uint8_t * r0 = state -> src + row0 * state -> row_stride ; 537const uint8_t * r1 = state -> src + row1 * state -> row_stride ; 538 539HVX_Vector v0 = hvx_vmemu ((const __fp16 * )(r0 + byte_off )); 540HVX_Vector v1 = (row1 < state -> n_cols ) ?hvx_vmemu ((const __fp16 * )(r1 + byte_off )) :Q6_V_vzero (); 541 542Q6_vscatter_QRMVwV (q_mask64 , (size_t )tile_base ,HTP_MM_HMX_TILE_SIZE - 1 ,v_off ,v0 ); 543v_off = Q6_Vw_vadd_VwVw (v_off ,v_scat_step ); 544Q6_vscatter_QRMVwV (q_mask64 , (size_t )tile_base ,HTP_MM_HMX_TILE_SIZE - 1 ,v_off ,v1 ); 545v_off = Q6_Vw_vadd_VwVw (v_off ,v_scat_step ); 546 } 547 } 548++ t ;++ kt ; 549 } 550} 551 552static __attribute__((noinline )) 553void quantize_f32_weight_to_fp16_tiles_task ( 554const tiled_dequantize_state_t * state , 555uint32_t start_tile ,uint32_t end_tile ) { 556 557const uint32_t n_k_tiles = state -> n_k_tiles ; 558const struct fastdiv_values n_k_tiles_div = state -> n_k_tiles_div ; 559 560const HVX_Vector v_scat_base = hvx_vmem (hmx_transpose_scatter_offsets ); 561const HVX_Vector v_scat_step = Q6_V_vsplat_R (4 ); 562const HVX_VectorPred q_mask64 = Q6_Q_vsetq_R (64 ); 563 564unsigned ct = fastdiv ((unsigned )start_tile ,& n_k_tiles_div ); 565unsigned kt = fastmodulo ((unsigned )start_tile ,n_k_tiles ,& n_k_tiles_div ); 566 567for (unsigned t = start_tile ;t < (unsigned )end_tile ; ) { 568if (kt >= (unsigned )n_k_tiles ) {kt = 0 ;ct ++ ; } 569 570__fp16 * tile_base = state -> dst + t * HTP_MM_HMX_TILE_N_ELMS ; 571 { 572uint32_t byte_off = kt * 32 * sizeof (float ); 573 574HVX_Vector v_off = v_scat_base ; 575for (uint32_t r = 0 ;r < HTP_MM_HMX_TILE_N_ROWS ;r += 2 ) { 576uint32_t row0 = ct * HTP_MM_HMX_TILE_N_COLS + r ; 577uint32_t row1 = row0 + 1 ; 578 579const uint8_t * r0 = state -> src + row0 * state -> row_stride ; 580const uint8_t * r1 = state -> src + row1 * state -> row_stride ; 581 582HVX_Vector v0_f32 = hvx_vmem ((const float * )(r0 + byte_off )); 583HVX_Vector v1_f32 = (row1 < state -> n_cols ) ?hvx_vmem ((const float * )(r1 + byte_off )) :Q6_V_vzero (); 584 585HVX_Vector v_out = hvx_vec_f32_to_f16 (v0_f32 ,v1_f32 ); 586 587Q6_vscatter_QRMVwV (q_mask64 , (size_t )tile_base ,HTP_MM_HMX_TILE_SIZE - 1 ,v_off ,v_out ); 588v_off = Q6_Vw_vadd_VwVw (v_off ,v_scat_step ); 589 590HVX_Vector v_out_hi = Q6_V_vror_VR (v_out ,64 ); 591Q6_vscatter_QRMVwV (q_mask64 , (size_t )tile_base ,HTP_MM_HMX_TILE_SIZE - 1 ,v_off ,v_out_hi ); 592v_off = Q6_Vw_vadd_VwVw (v_off ,v_scat_step ); 593 } 594 } 595++ t ;++ kt ; 596 } 597} 598 599// --- End tiled dequantizers --- 600 601// dot-chunk functions require external HMX lock 602 603static void core_dot_chunk_fp16_short (__fp16 * restrictoutput ,const __fp16 * restrictactivation , 604const __fp16 * restrictweight ,const __fp16 * restrictscales , 605uint32_t n_row_tiles ,uint32_t n_col_tiles ,uint32_t n_dot_tiles ) { 606__builtin_assume (n_row_tiles > 0 ); 607__builtin_assume (n_col_tiles > 0 ); 608__builtin_assume (n_dot_tiles > 0 ); 609__builtin_assume (n_dot_tiles <=32 ); 610 611 asmvolatile (HMX_SET_BIAS ("%0" ) ::"r" ((unsigned int )scales )); 612 613const size_t dot_stride = n_dot_tiles * HTP_MM_HMX_TILE_N_ELMS ; 614const uint32_t range = 2048u * n_dot_tiles - 1 ; 615 616for (uint32_t r = 0 ;r < n_row_tiles ;++ r ) { 617const __fp16 * row_base = activation + r * dot_stride ; 618const __fp16 * col_base = weight ; 619__fp16 * out_tile = output + r * n_col_tiles * HTP_MM_HMX_TILE_N_ELMS ; 620 621for (size_t c = 0 ;c < n_col_tiles ;++ c ) { 622 asmvolatile (HMX_CLRACC_F16 ()); 623 asmvolatile (HMX_LOAD_MPY_DEEP_F16 ("%1" ,"%2" ,"%0" ) : :"r" (range ),"r" (row_base ),"r" (col_base )); 624 asmvolatile (HMX_STORE_AFTER_F16 ("%0" ,"%1" ) : :"r" (out_tile ),"r" (0 ) :"memory" ); 625col_base += dot_stride ; 626out_tile += HTP_MM_HMX_TILE_N_ELMS ; 627 } 628 } 629} 630 631static void core_dot_chunk_fp16 (__fp16 * restrictoutput ,const __fp16 * restrictactivation , 632const __fp16 * restrictweight ,const __fp16 * restrictscales , 633uint32_t n_row_tiles ,uint32_t n_col_tiles ,uint32_t n_dot_tiles ) { 634if (n_dot_tiles <=32 ) { 635core_dot_chunk_fp16_short (output ,activation ,weight ,scales ,n_row_tiles ,n_col_tiles ,n_dot_tiles ); 636return ; 637 } 638__builtin_assume (n_row_tiles > 0 ); 639__builtin_assume (n_col_tiles > 0 ); 640__builtin_assume (n_dot_tiles > 32 ); 641 642 asmvolatile (HMX_SET_BIAS ("%0" ) ::"r" ((unsigned int )scales )); 643 644const size_t dot_stride = n_dot_tiles * HTP_MM_HMX_TILE_N_ELMS ; 645 646for (uint32_t r = 0 ;r < n_row_tiles ;++ r ) { 647const __fp16 * row_base = activation + r * dot_stride ; 648const __fp16 * col_base = weight ; 649__fp16 * out_tile = output + r * n_col_tiles * HTP_MM_HMX_TILE_N_ELMS ; 650 651for (size_t c = 0 ;c < n_col_tiles ;++ c ) { 652const __fp16 * row_tiles = row_base ; 653const __fp16 * col_tiles = col_base ; 654 655 asmvolatile (HMX_CLRACC_F16 ()); 656 657const uint32_t n_loops = n_dot_tiles /32 ; 658const uint32_t rem = n_dot_tiles %32 ; 659 660for (uint32_t l = 0 ;l < n_loops ;++ l ) { 661 asmvolatile (HMX_LOAD_MPY_DEEP_F16 ("%1" ,"%2" ,"%0" ) : :"r" (65535 ),"r" (row_tiles ),"r" (col_tiles )); 662row_tiles += 32 * HTP_MM_HMX_TILE_N_ELMS ; 663col_tiles += 32 * HTP_MM_HMX_TILE_N_ELMS ; 664 } 665 666if (rem > 0 ) { 667const uint32_t range = 2048u * rem - 1 ; 668 asmvolatile (HMX_LOAD_MPY_DEEP_F16 ("%1" ,"%2" ,"%0" ) : :"r" (range ),"r" (row_tiles ),"r" (col_tiles )); 669 } 670 671 asmvolatile (HMX_STORE_AFTER_F16 ("%0" ,"%1" ) : :"r" (out_tile ),"r" (0 ) :"memory" ); 672 673col_base += dot_stride ; 674out_tile += HTP_MM_HMX_TILE_N_ELMS ; 675 } 676 } 677} 678 679static void core_mma_chunk_fp16_short (__fp16 * restrictc ,const __fp16 * restricta ,const __fp16 * restrictb , 680const __fp16 * restrictcol_scales ,const __fp16 * restricteye_tile , 681uint32_t n_row_tiles ,uint32_t n_col_tiles ,uint32_t n_dot_tiles ,bool zero_init ) { 682__builtin_assume (n_row_tiles > 0 ); 683__builtin_assume (n_col_tiles > 0 ); 684__builtin_assume (n_dot_tiles > 0 ); 685__builtin_assume (n_dot_tiles <=32 ); 686 687 asmvolatile (HMX_SET_BIAS ("%0" ) ::"r" ((unsigned int )col_scales )); 688 689const size_t dot_tile_stride = n_dot_tiles * HTP_MM_HMX_TILE_N_ELMS ; 690const uint32_t range = 2048u * n_dot_tiles - 1 ; 691 692for (size_t i = 0 ;i < n_row_tiles ;++ i ) { 693const __fp16 * row_base = a + i * dot_tile_stride ; 694__fp16 * res_base = c + i * n_col_tiles * HTP_MM_HMX_TILE_N_ELMS ; 695const __fp16 * col_base = b ; 696__fp16 * accum_tile = res_base ; 697 698for (size_t j = 0 ;j < n_col_tiles ;++ j ) { 699 asmvolatile (HMX_CLRACC_F16 ()); 700 701if (!zero_init ) { 702 asmvolatile (HMX_LOAD_MPY_F16 ("%1" ,"%2" ,"%0" ) : :"r" (2047 ),"r" (accum_tile ),"r" (eye_tile )); 703 } 704 705 asmvolatile (HMX_LOAD_MPY_DEEP_F16 ("%1" ,"%2" ,"%0" ) : :"r" (range ),"r" (row_base ),"r" (col_base )); 706 707 asmvolatile (HMX_STORE_AFTER_F16 ("%0" ,"%1" ) : :"r" (accum_tile ),"r" (0 ) :"memory" ); 708 709col_base += dot_tile_stride ; 710accum_tile += HTP_MM_HMX_TILE_N_ELMS ; 711 } 712 } 713} 714 715static void core_mma_chunk_fp16 (__fp16 * restrictc ,const __fp16 * restricta ,const __fp16 * restrictb , 716const __fp16 * restrictcol_scales ,const __fp16 * restricteye_tile , 717uint32_t n_row_tiles ,uint32_t n_col_tiles ,uint32_t n_dot_tiles ,bool zero_init ) { 718if (n_dot_tiles <=32 ) { 719core_mma_chunk_fp16_short (c ,a ,b ,col_scales ,eye_tile ,n_row_tiles ,n_col_tiles ,n_dot_tiles ,zero_init ); 720return ; 721 } 722__builtin_assume (n_row_tiles > 0 ); 723__builtin_assume (n_col_tiles > 0 ); 724__builtin_assume (n_dot_tiles > 32 ); 725 726 asmvolatile (HMX_SET_BIAS ("%0" ) ::"r" ((unsigned int )col_scales )); 727 728const size_t dot_tile_stride = n_dot_tiles * HTP_MM_HMX_TILE_N_ELMS ; 729 730for (size_t i = 0 ;i < n_row_tiles ;++ i ) { 731const __fp16 * row_base = a + i * dot_tile_stride ; 732__fp16 * res_base = c + i * n_col_tiles * HTP_MM_HMX_TILE_N_ELMS ; 733const __fp16 * col_base = b ; 734__fp16 * accum_tile = res_base ; 735 736for (size_t j = 0 ;j < n_col_tiles ;++ j ) { 737const __fp16 * col_tiles = col_base ; 738const __fp16 * row_tiles = row_base ; 739 740 asmvolatile (HMX_CLRACC_F16 ()); 741 742if (!zero_init ) { 743 asmvolatile (HMX_LOAD_MPY_F16 ("%1" ,"%2" ,"%0" ) : :"r" (2047 ),"r" (accum_tile ),"r" (eye_tile )); 744 } 745 746const uint32_t n_loops = n_dot_tiles /32 ; 747const uint32_t rem = n_dot_tiles %32 ; 748 749for (uint32_t l = 0 ;l < n_loops ;++ l ) { 750 asmvolatile (HMX_LOAD_MPY_DEEP_F16 ("%1" ,"%2" ,"%0" ) : :"r" (65535 ),"r" (row_tiles ),"r" (col_tiles )); 751row_tiles += 32 * HTP_MM_HMX_TILE_N_ELMS ; 752col_tiles += 32 * HTP_MM_HMX_TILE_N_ELMS ; 753 } 754 755if (rem > 0 ) { 756const uint32_t range = 2048u * rem - 1 ; 757 asmvolatile (HMX_LOAD_MPY_DEEP_F16 ("%1" ,"%2" ,"%0" ) : :"r" (range ),"r" (row_tiles ),"r" (col_tiles )); 758 } 759 760 asmvolatile (HMX_STORE_AFTER_F16 ("%0" ,"%1" ) : :"r" (accum_tile ),"r" (0 ) :"memory" ); 761 762col_base += dot_tile_stride ; 763accum_tile += HTP_MM_HMX_TILE_N_ELMS ; 764 } 765 } 766} 767 768// output : fp16 -> f32p 769 770static void transfer_output_chunk_fp16_to_fp32_col_chunk ( 771float * restrictdst , 772const float * restrictsrc2 , 773const __fp16 * restrictvtcm_src , 774uint32_t start_row , 775uint32_t n_rows , 776uint32_t c_len , 777uint32_t total_n_cols , 778uint32_t dst_stride , 779uint32_t src2_stride , 780uint32_t dst_cols 781) { 782assert (c_len %HTP_MM_HMX_TILE_N_COLS == 0 ); 783assert (total_n_cols %HTP_MM_HMX_TILE_N_COLS == 0 ); 784const size_t tile_row_stride = (total_n_cols /HTP_MM_HMX_TILE_N_COLS )* HTP_MM_HMX_TILE_N_ELMS ; 785 786const HVX_Vector one = hvx_vec_splat_f16 (1.0 ); 787 788const size_t limit_c = hex_smin (c_len ,dst_cols ); 789const size_t limit_c_aligned = (limit_c & ~31 ); 790 791for (size_t r = 0 ;r < n_rows ;r += 2 ) { 792const size_t r_idx0 = start_row + r + 0 ; 793const size_t r0 = r_idx0 /HTP_MM_HMX_TILE_N_ROWS ; 794const size_t r1 = (r_idx0 %HTP_MM_HMX_TILE_N_ROWS ) /2 ;// index of the row pair within the tile 795const __fp16 * row_base = vtcm_src + r0 * tile_row_stride ; 796float * output_row_base = dst + r * dst_stride ;// global memory row base for row r (and r+1) 797const float * src2_row_base = src2 ? (src2 + r * src2_stride ) :NULL ; 798 799#pragma unroll(4) 800for (size_t c = 0 ;c < limit_c_aligned ;c += HTP_MM_HMX_TILE_N_COLS ) { 801const size_t c0 = c /HTP_MM_HMX_TILE_N_COLS ; 802const __fp16 * tile = row_base + c0 * HTP_MM_HMX_TILE_N_ELMS ; 803HVX_Vector v = ((const HVX_Vector * )tile )[r1 ]; 804HVX_VectorPair vp = Q6_Wqf32_vmpy_VhfVhf (v ,one ); 805 806HVX_Vector * pv_out0 = (HVX_Vector * ) (output_row_base + c + 0 ); 807HVX_Vector * pv_out1 = (HVX_Vector * ) (output_row_base + c + dst_stride ); 808 809HVX_Vector v_out0 = Q6_Vsf_equals_Vqf32 (Q6_V_lo_W (vp )); 810if (src2_row_base ) { 811HVX_Vector v_src2_0 = hvx_vmemu (src2_row_base + c + 0 ); 812v_out0 = hvx_vec_add_f32_f32 (v_out0 ,v_src2_0 ); 813 } 814* pv_out0 = v_out0 ; 815 816if (r + 1 < n_rows ) { 817HVX_Vector v_out1 = Q6_Vsf_equals_Vqf32 (Q6_V_hi_W (vp )); 818if (src2_row_base ) { 819HVX_Vector v_src2_1 = hvx_vmemu (src2_row_base + c + src2_stride ); 820v_out1 = hvx_vec_add_f32_f32 (v_out1 ,v_src2_1 ); 821 } 822* pv_out1 = v_out1 ; 823 } 824 } 825 826if (limit_c_aligned < limit_c ) { 827size_t c = limit_c_aligned ; 828size_t valid_c = limit_c - c ; 829const size_t c0 = c /HTP_MM_HMX_TILE_N_COLS ; 830const __fp16 * tile = row_base + c0 * HTP_MM_HMX_TILE_N_ELMS ; 831HVX_Vector v = ((const HVX_Vector * )tile )[r1 ]; 832HVX_VectorPair vp = Q6_Wqf32_vmpy_VhfVhf (v ,one ); 833 834HVX_Vector v_out0 = Q6_Vsf_equals_Vqf32 (Q6_V_lo_W (vp )); 835if (src2_row_base ) { 836HVX_Vector v_src2_0 = hvx_vmemu (src2_row_base + c + 0 ); 837v_out0 = hvx_vec_add_f32_f32 (v_out0 ,v_src2_0 ); 838 } 839hvx_vec_store_u (output_row_base + c ,valid_c * sizeof (float ),v_out0 ); 840 841if (r + 1 < n_rows ) { 842HVX_Vector v_out1 = Q6_Vsf_equals_Vqf32 (Q6_V_hi_W (vp )); 843if (src2_row_base ) { 844HVX_Vector v_src2_1 = hvx_vmemu (src2_row_base + c + src2_stride ); 845v_out1 = hvx_vec_add_f32_f32 (v_out1 ,v_src2_1 ); 846 } 847hvx_vec_store_u (output_row_base + c + dst_stride ,valid_c * sizeof (float ),v_out1 ); 848 } 849 } 850 } 851} 852 853static inline void transfer_output_chunk_fp16_to_fp32 ( 854float * restrictdst , 855const float * restrictsrc2 , 856const __fp16 * restrictvtcm_src , 857uint32_t start_row , 858uint32_t n_rows , 859uint32_t n_cols , 860uint32_t dst_stride , 861uint32_t src2_stride , 862uint32_t dst_cols 863) { 864transfer_output_chunk_fp16_to_fp32_col_chunk ( 865dst ,src2 ,vtcm_src ,start_row ,n_rows ,n_cols ,n_cols ,dst_stride ,src2_stride ,dst_cols 866 ); 867} 868 869typedef struct { 870const __fp16 * vtcm_src ; 871float * dst ; 872const float * src2 ; 873uint32_t n_tasks ; 874uint32_t n_tot_chunks ; 875uint32_t n_chunks_per_task ; 876uint32_t n_cols ; 877uint32_t dst_stride ;// DDR row stride 878uint32_t src2_stride ;// DDR row stride for residual 879uint32_t dst_cols ;// Actual output columns 880struct htp_thread_trace * traces ; 881}output_transfer_task_state_t ; 882 883// activations : fp32 -> fp16 884 885static void transfer_activation_chunk_fp32_to_fp16 (__fp16 * restrictvtcm_dst ,const float * restrictsrc ,uint32_t n_rows ,uint32_t k_block ,uint32_t k_stride ,uint32_t k_valid ) { 886const uint32_t n_rows_padded = hex_align_up (n_rows ,HTP_MM_HMX_TILE_N_ROWS ); 887const uint32_t n_rows_tiled = (n_rows /HTP_MM_HMX_TILE_N_ROWS )* HTP_MM_HMX_TILE_N_ROWS ; 888 889uint32_t r = 0 ; 890 891#pragma unroll(2) 892for (r = 0 ;r < n_rows_tiled ;r += 2 ) { 893uint32_t r0 = r /HTP_MM_HMX_TILE_N_ROWS ;// tile row index 894uint32_t r1 = r %HTP_MM_HMX_TILE_N_ROWS ;// intra-tile row idx 895 896const float * ptr_in0 = src + (r + 0 )* k_stride ; 897const float * ptr_in1 = src + (r + 1 )* k_stride ; 898 899uint32_t c = 0 ; 900for (;c + 32 <=k_valid ;c += 32 ) { 901HVX_Vector v0 = * (const HVX_Vector * )(ptr_in0 + c ); 902HVX_Vector v1 = * (const HVX_Vector * )(ptr_in1 + c ); 903HVX_Vector v_out = hvx_vec_f32_to_f16_shuff (v0 ,v1 ); 904 905uint32_t c0 = c /HTP_MM_HMX_TILE_N_COLS ;// tile column index 906uint32_t tile_idx = r0 * (k_block /HTP_MM_HMX_TILE_N_COLS )+ c0 ; 907 908HVX_Vector * tile = (HVX_Vector * ) (vtcm_dst + tile_idx * HTP_MM_HMX_TILE_N_ELMS ); 909tile [r1 /2 ]= v_out ; 910 } 911if (c < k_block ) { 912HVX_Vector v0 = * (const HVX_Vector * )(ptr_in0 + c ); 913HVX_Vector v1 = * (const HVX_Vector * )(ptr_in1 + c ); 914 915uint32_t rem = k_valid - c ; 916HVX_VectorPred mask = Q6_Q_vsetq2_R (rem > 0 ?rem * sizeof (float ) :0 ); 917v0 = Q6_V_vmux_QVV (mask ,v0 ,Q6_V_vzero ()); 918v1 = Q6_V_vmux_QVV (mask ,v1 ,Q6_V_vzero ()); 919 920HVX_Vector v_out = hvx_vec_f32_to_f16_shuff (v0 ,v1 ); 921 922uint32_t c0 = c /HTP_MM_HMX_TILE_N_COLS ;// tile column index 923uint32_t tile_idx = r0 * (k_block /HTP_MM_HMX_TILE_N_COLS )+ c0 ; 924 925HVX_Vector * tile = (HVX_Vector * ) (vtcm_dst + tile_idx * HTP_MM_HMX_TILE_N_ELMS ); 926tile [r1 /2 ]= v_out ; 927 } 928 } 929 930for (;r < n_rows_padded ;r += 2 ) { 931uint32_t r0 = r /HTP_MM_HMX_TILE_N_ROWS ;// tile row index 932uint32_t r1 = r %HTP_MM_HMX_TILE_N_ROWS ;// intra-tile row idx 933 934const bool row0_valid = r < n_rows ; 935const bool row1_valid = (r + 1 )< n_rows ; 936 937const float * ptr_in0 = row0_valid ? (src + (r + 0 )* k_stride ) :NULL ; 938const float * ptr_in1 = row1_valid ? (src + (r + 1 )* k_stride ) :NULL ; 939 940uint32_t c = 0 ; 941for (;c + 32 <=k_valid ;c += 32 ) { 942HVX_Vector v0 = Q6_V_vzero (); 943HVX_Vector v1 = Q6_V_vzero (); 944if (row0_valid )v0 = * (const HVX_Vector * )(ptr_in0 + c ); 945if (row1_valid )v1 = * (const HVX_Vector * )(ptr_in1 + c ); 946 947HVX_Vector v_out = hvx_vec_f32_to_f16_shuff (v0 ,v1 ); 948 949uint32_t c0 = c /HTP_MM_HMX_TILE_N_COLS ;// tile column index 950uint32_t tile_idx = r0 * (k_block /HTP_MM_HMX_TILE_N_COLS )+ c0 ; 951 952HVX_Vector * tile = (HVX_Vector * ) (vtcm_dst + tile_idx * HTP_MM_HMX_TILE_N_ELMS ); 953tile [r1 /2 ]= v_out ; 954 } 955if (c < k_block ) { 956HVX_Vector v0 = Q6_V_vzero (); 957HVX_Vector v1 = Q6_V_vzero (); 958if (row0_valid )v0 = * (const HVX_Vector * )(ptr_in0 + c ); 959if (row1_valid )v1 = * (const HVX_Vector * )(ptr_in1 + c ); 960 961uint32_t rem = k_valid - c ; 962HVX_VectorPred mask = Q6_Q_vsetq2_R (rem > 0 ?rem * sizeof (float ) :0 ); 963v0 = Q6_V_vmux_QVV (mask ,v0 ,Q6_V_vzero ()); 964v1 = Q6_V_vmux_QVV (mask ,v1 ,Q6_V_vzero ()); 965 966HVX_Vector v_out = hvx_vec_f32_to_f16_shuff (v0 ,v1 ); 967 968uint32_t c0 = c /HTP_MM_HMX_TILE_N_COLS ;// tile column index 969uint32_t tile_idx = r0 * (k_block /HTP_MM_HMX_TILE_N_COLS )+ c0 ; 970 971HVX_Vector * tile = (HVX_Vector * ) (vtcm_dst + tile_idx * HTP_MM_HMX_TILE_N_ELMS ); 972tile [r1 /2 ]= v_out ; 973 } 974 } 975} 976 977static void transfer_activation_row_pair_fp32_to_fp16 ( 978__fp16 * restrictvtcm_dst , 979const float * restrictrow0 , 980const float * restrictrow1 , 981uint32_t r , 982uint32_t k_block , 983uint32_t k_valid , 984bool row0_valid , 985bool row1_valid ) { 986 987uint32_t r0 = r /HTP_MM_HMX_TILE_N_ROWS ;// tile row index 988uint32_t r1 = r %HTP_MM_HMX_TILE_N_ROWS ;// intra-tile row idx 989 990uint32_t c = 0 ; 991for (;c + 32 <=k_valid ;c += 32 ) { 992HVX_Vector v0 = Q6_V_vzero (); 993HVX_Vector v1 = Q6_V_vzero (); 994if (row0_valid )v0 = * (const HVX_Vector * )(row0 + c ); 995if (row1_valid )v1 = * (const HVX_Vector * )(row1 + c ); 996 997HVX_Vector v_out = hvx_vec_f32_to_f16_shuff (v0 ,v1 ); 998 999uint32_t c0 = c /HTP_MM_HMX_TILE_N_COLS ;// tile column index 1000uint32_t tile_idx = r0 * (k_block /HTP_MM_HMX_TILE_N_COLS )+ c0 ; 1001 1002HVX_Vector * tile = (HVX_Vector * ) (vtcm_dst + tile_idx * HTP_MM_HMX_TILE_N_ELMS ); 1003tile [r1 /2 ]= v_out ; 1004 } 1005if (c < k_block ) { 1006HVX_Vector v0 = Q6_V_vzero (); 1007HVX_Vector v1 = Q6_V_vzero (); 1008if (row0_valid )v0 = * (const HVX_Vector * )(row0 + c ); 1009if (row1_valid )v1 = * (const HVX_Vector * )(row1 + c ); 1010 1011uint32_t rem = k_valid - c ; 1012HVX_VectorPred mask = Q6_Q_vsetq2_R (rem > 0 ?rem * sizeof (float ) :0 ); 1013v0 = Q6_V_vmux_QVV (mask ,v0 ,Q6_V_vzero ()); 1014v1 = Q6_V_vmux_QVV (mask ,v1 ,Q6_V_vzero ()); 1015 1016HVX_Vector v_out = hvx_vec_f32_to_f16_shuff (v0 ,v1 ); 1017 1018uint32_t c0 = c /HTP_MM_HMX_TILE_N_COLS ;// tile column index 1019uint32_t tile_idx = r0 * (k_block /HTP_MM_HMX_TILE_N_COLS )+ c0 ; 1020 1021HVX_Vector * tile = (HVX_Vector * ) (vtcm_dst + tile_idx * HTP_MM_HMX_TILE_N_ELMS ); 1022tile [r1 /2 ]= v_out ; 1023 } 1024} 1025 1026static void transfer_activation_row_pair_fp32_to_fp16_col_chunk ( 1027__fp16 * restrictvtcm_dst , 1028const float * restrictrow0 ,// offset by c_first 1029const float * restrictrow1 ,// offset by c_first 1030uint32_t r , 1031uint32_t k_block , 1032uint32_t c_first , 1033uint32_t c_len , 1034uint32_t k_chunk_valid , 1035bool row0_valid , 1036bool row1_valid ) { 1037 1038uint32_t r0 = r /HTP_MM_HMX_TILE_N_ROWS ;// tile row index 1039uint32_t r1 = r %HTP_MM_HMX_TILE_N_ROWS ;// intra-tile row idx 1040 1041uint32_t c = 0 ; 1042for (;c + 32 <=k_chunk_valid ;c += 32 ) { 1043HVX_Vector v0 = Q6_V_vzero (); 1044HVX_Vector v1 = Q6_V_vzero (); 1045if (row0_valid )v0 = * (const HVX_Vector * )(row0 + c ); 1046if (row1_valid )v1 = * (const HVX_Vector * )(row1 + c ); 1047 1048HVX_Vector v_out = hvx_vec_f32_to_f16_shuff (v0 ,v1 ); 1049 1050uint32_t c0 = (c_first + c ) /HTP_MM_HMX_TILE_N_COLS ;// tile column index 1051uint32_t tile_idx = r0 * (k_block /HTP_MM_HMX_TILE_N_COLS )+ c0 ; 1052 1053HVX_Vector * tile = (HVX_Vector * ) (vtcm_dst + tile_idx * HTP_MM_HMX_TILE_N_ELMS ); 1054tile [r1 /2 ]= v_out ; 1055 } 1056if (c < c_len ) { 1057HVX_Vector v0 = Q6_V_vzero (); 1058HVX_Vector v1 = Q6_V_vzero (); 1059if (row0_valid )v0 = * (const HVX_Vector * )(row0 + c ); 1060if (row1_valid )v1 = * (const HVX_Vector * )(row1 + c ); 1061 1062uint32_t rem = (k_chunk_valid > c ) ? (k_chunk_valid - c ) :0 ; 1063HVX_VectorPred mask = Q6_Q_vsetq2_R (rem > 0 ?rem * sizeof (float ) :0 ); 1064v0 = Q6_V_vmux_QVV (mask ,v0 ,Q6_V_vzero ()); 1065v1 = Q6_V_vmux_QVV (mask ,v1 ,Q6_V_vzero ()); 1066 1067HVX_Vector v_out = hvx_vec_f32_to_f16_shuff (v0 ,v1 ); 1068 1069uint32_t c0 = (c_first + c ) /HTP_MM_HMX_TILE_N_COLS ;// tile column index 1070uint32_t tile_idx = r0 * (k_block /HTP_MM_HMX_TILE_N_COLS )+ c0 ; 1071 1072HVX_Vector * tile = (HVX_Vector * ) (vtcm_dst + tile_idx * HTP_MM_HMX_TILE_N_ELMS ); 1073tile [r1 /2 ]= v_out ; 1074 } 1075} 1076 1077static void transfer_activation_chunk_fp32_to_fp16_gathered ( 1078__fp16 * restrictvtcm_dst , 1079const float * restrictsrc , 1080uint32_t start_row , 1081uint32_t vtcm_start_row , 1082uint32_t n_rows , 1083uint32_t k_block , 1084const struct mmid_row_mapping * matrix_rows , 1085uint32_t cur_a , 1086uint32_t mapping_stride , 1087uint32_t ne11 , 1088const struct fastdiv_values * ne11_div , 1089size_t nb11 , 1090size_t nb12 , 1091uint32_t cne1 , 1092uint32_t k_valid ) { 1093const uint32_t n_rows_padded = hex_align_up (n_rows ,HTP_MM_HMX_TILE_N_ROWS ); 1094const uint32_t n_rows_tiled = (n_rows /HTP_MM_HMX_TILE_N_ROWS )* HTP_MM_HMX_TILE_N_ROWS ; 1095 1096uint32_t r = 0 ; 1097 1098#pragma unroll(2) 1099for (r = 0 ;r < n_rows_tiled ;r += 2 ) { 1100uint32_t r_idx0 = start_row + r + 0 ; 1101uint32_t r_idx1 = start_row + r + 1 ; 1102uint32_t lr = vtcm_start_row + r ;// vtcm-local row 1103uint32_t r0 = lr /HTP_MM_HMX_TILE_N_ROWS ;// tile row index 1104uint32_t r1 = lr %HTP_MM_HMX_TILE_N_ROWS ;// intra-tile row idx 1105 1106struct mmid_row_mapping mapping0 = matrix_rows [cur_a * mapping_stride + r_idx0 ]; 1107struct mmid_row_mapping mapping1 = matrix_rows [cur_a * mapping_stride + r_idx1 ]; 1108 1109uint32_t i11_0 = fastmodulo (mapping0 .i1 ,ne11 ,ne11_div ); 1110uint32_t i11_1 = fastmodulo (mapping1 .i1 ,ne11 ,ne11_div ); 1111 1112const float * row0_ptr = (const float * ) ((const uint8_t * )src + i11_0 * nb11 + mapping0 .i2 * nb12 ); 1113const float * row1_ptr = (const float * ) ((const uint8_t * )src + i11_1 * nb11 + mapping1 .i2 * nb12 ); 1114 1115uint32_t c = 0 ; 1116for (;c + 32 <=k_valid ;c += 32 ) { 1117HVX_Vector v0 = * (const HVX_Vector * )(row0_ptr + c ); 1118HVX_Vector v1 = * (const HVX_Vector * )(row1_ptr + c ); 1119HVX_Vector v_out = hvx_vec_f32_to_f16_shuff (v0 ,v1 ); 1120 1121uint32_t c0 = c /HTP_MM_HMX_TILE_N_COLS ; 1122uint32_t tile_idx = r0 * (k_block /HTP_MM_HMX_TILE_N_COLS )+ c0 ; 1123 1124HVX_Vector * tile = (HVX_Vector * ) (vtcm_dst + tile_idx * HTP_MM_HMX_TILE_N_ELMS ); 1125tile [r1 /2 ]= v_out ; 1126 } 1127if (c < k_block ) { 1128HVX_Vector v0 = * (const HVX_Vector * )(row0_ptr + c ); 1129HVX_Vector v1 = * (const HVX_Vector * )(row1_ptr + c ); 1130 1131uint32_t rem = k_valid - c ; 1132HVX_VectorPred mask = Q6_Q_vsetq2_R (rem > 0 ?rem * sizeof (float ) :0 ); 1133v0 = Q6_V_vmux_QVV (mask ,v0 ,Q6_V_vzero ()); 1134v1 = Q6_V_vmux_QVV (mask ,v1 ,Q6_V_vzero ()); 1135 1136HVX_Vector v_out = hvx_vec_f32_to_f16_shuff (v0 ,v1 ); 1137 1138uint32_t c0 = c /HTP_MM_HMX_TILE_N_COLS ; 1139uint32_t tile_idx = r0 * (k_block /HTP_MM_HMX_TILE_N_COLS )+ c0 ; 1140 1141HVX_Vector * tile = (HVX_Vector * ) (vtcm_dst + tile_idx * HTP_MM_HMX_TILE_N_ELMS ); 1142tile [r1 /2 ]= v_out ; 1143 } 1144 } 1145 1146for (;r < n_rows_padded ;r += 2 ) { 1147uint32_t lr = vtcm_start_row + r ;// vtcm-local row 1148uint32_t r0 = lr /HTP_MM_HMX_TILE_N_ROWS ;// tile row index 1149uint32_t r1 = lr %HTP_MM_HMX_TILE_N_ROWS ;// intra-tile row idx 1150 1151const bool row0_valid = (start_row + r + 0 )< cne1 ; 1152const bool row1_valid = (start_row + r + 1 )< cne1 ; 1153 1154const float * row0_ptr = NULL ; 1155const float * row1_ptr = NULL ; 1156 1157if (row0_valid ) { 1158struct mmid_row_mapping mapping0 = matrix_rows [cur_a * mapping_stride + (start_row + r + 0 )]; 1159uint32_t i11_0 = fastmodulo (mapping0 .i1 ,ne11 ,ne11_div ); 1160row0_ptr = (const float * ) ((const uint8_t * )src + i11_0 * nb11 + mapping0 .i2 * nb12 ); 1161 } 1162if (row1_valid ) { 1163struct mmid_row_mapping mapping1 = matrix_rows [cur_a * mapping_stride + (start_row + r + 1 )]; 1164uint32_t i11_1 = fastmodulo (mapping1 .i1 ,ne11 ,ne11_div ); 1165row1_ptr = (const float * ) ((const uint8_t * )src + i11_1 * nb11 + mapping1 .i2 * nb12 ); 1166 } 1167 1168uint32_t c = 0 ; 1169for (;c + 32 <=k_valid ;c += 32 ) { 1170HVX_Vector v0 = Q6_V_vzero (); 1171HVX_Vector v1 = Q6_V_vzero (); 1172if (row0_valid )v0 = * (const HVX_Vector * )(row0_ptr + c ); 1173if (row1_valid )v1 = * (const HVX_Vector * )(row1_ptr + c ); 1174 1175HVX_Vector v_out = hvx_vec_f32_to_f16_shuff (v0 ,v1 ); 1176 1177uint32_t c0 = c /HTP_MM_HMX_TILE_N_COLS ; 1178uint32_t tile_idx = r0 * (k_block /HTP_MM_HMX_TILE_N_COLS )+ c0 ; 1179 1180HVX_Vector * tile = (HVX_Vector * ) (vtcm_dst + tile_idx * HTP_MM_HMX_TILE_N_ELMS ); 1181tile [r1 /2 ]= v_out ; 1182 } 1183if (c < k_block ) { 1184HVX_Vector v0 = Q6_V_vzero (); 1185HVX_Vector v1 = Q6_V_vzero (); 1186if (row0_valid )v0 = * (const HVX_Vector * )(row0_ptr + c ); 1187if (row1_valid )v1 = * (const HVX_Vector * )(row1_ptr + c ); 1188 1189uint32_t rem = k_valid - c ; 1190HVX_VectorPred mask = Q6_Q_vsetq2_R (rem > 0 ?rem * sizeof (float ) :0 ); 1191v0 = Q6_V_vmux_QVV (mask ,v0 ,Q6_V_vzero ()); 1192v1 = Q6_V_vmux_QVV (mask ,v1 ,Q6_V_vzero ()); 1193 1194HVX_Vector v_out = hvx_vec_f32_to_f16_shuff (v0 ,v1 ); 1195 1196uint32_t c0 = c /HTP_MM_HMX_TILE_N_COLS ; 1197uint32_t tile_idx = r0 * (k_block /HTP_MM_HMX_TILE_N_COLS )+ c0 ; 1198 1199HVX_Vector * tile = (HVX_Vector * ) (vtcm_dst + tile_idx * HTP_MM_HMX_TILE_N_ELMS ); 1200tile [r1 /2 ]= v_out ; 1201 } 1202 } 1203} 1204 1205static void transfer_activation_chunk_fp32_to_fp16_gathered_flat ( 1206__fp16 * restrictvtcm_dst , 1207const float * restrictsrc , 1208uint32_t start_row , 1209uint32_t vtcm_start_row , 1210uint32_t n_rows , 1211uint32_t k_block , 1212const struct mmid_row_mapping * matrix_rows , 1213uint32_t cur_a , 1214uint32_t mapping_stride , 1215size_t nb12 , 1216uint32_t cne1 , 1217uint32_t k_valid ) { 1218const uint32_t n_rows_padded = hex_align_up (n_rows ,HTP_MM_HMX_TILE_N_ROWS ); 1219const uint32_t n_rows_tiled = (n_rows /HTP_MM_HMX_TILE_N_ROWS )* HTP_MM_HMX_TILE_N_ROWS ; 1220 1221uint32_t r = 0 ; 1222 1223#pragma unroll(2) 1224for (r = 0 ;r < n_rows_tiled ;r += 2 ) { 1225uint32_t r_idx0 = start_row + r + 0 ; 1226uint32_t r_idx1 = start_row + r + 1 ; 1227uint32_t lr = vtcm_start_row + r ;// vtcm-local row 1228uint32_t r0 = lr /HTP_MM_HMX_TILE_N_ROWS ;// tile row index 1229uint32_t r1 = lr %HTP_MM_HMX_TILE_N_ROWS ;// intra-tile row idx 1230 1231struct mmid_row_mapping mapping0 = matrix_rows [cur_a * mapping_stride + r_idx0 ]; 1232struct mmid_row_mapping mapping1 = matrix_rows [cur_a * mapping_stride + r_idx1 ]; 1233 1234const float * row0_ptr = (const float * ) ((const uint8_t * )src + mapping0 .i2 * nb12 ); 1235const float * row1_ptr = (const float * ) ((const uint8_t * )src + mapping1 .i2 * nb12 ); 1236 1237uint32_t c = 0 ; 1238for (;c + 32 <=k_valid ;c += 32 ) { 1239HVX_Vector v0 = * (const HVX_Vector * )(row0_ptr + c ); 1240HVX_Vector v1 = * (const HVX_Vector * )(row1_ptr + c ); 1241HVX_Vector v_out = hvx_vec_f32_to_f16_shuff (v0 ,v1 ); 1242 1243uint32_t c0 = c /HTP_MM_HMX_TILE_N_COLS ; 1244uint32_t tile_idx = r0 * (k_block /HTP_MM_HMX_TILE_N_COLS )+ c0 ; 1245 1246HVX_Vector * tile = (HVX_Vector * ) (vtcm_dst + tile_idx * HTP_MM_HMX_TILE_N_ELMS ); 1247tile [r1 /2 ]= v_out ; 1248 } 1249if (c < k_block ) { 1250HVX_Vector v0 = * (const HVX_Vector * )(row0_ptr + c ); 1251HVX_Vector v1 = * (const HVX_Vector * )(row1_ptr + c ); 1252 1253uint32_t rem = k_valid - c ; 1254HVX_VectorPred mask = Q6_Q_vsetq2_R (rem > 0 ?rem * sizeof (float ) :0 ); 1255v0 = Q6_V_vmux_QVV (mask ,v0 ,Q6_V_vzero ()); 1256v1 = Q6_V_vmux_QVV (mask ,v1 ,Q6_V_vzero ()); 1257 1258HVX_Vector v_out = hvx_vec_f32_to_f16_shuff (v0 ,v1 ); 1259 1260uint32_t c0 = c /HTP_MM_HMX_TILE_N_COLS ; 1261uint32_t tile_idx = r0 * (k_block /HTP_MM_HMX_TILE_N_COLS )+ c0 ; 1262 1263HVX_Vector * tile = (HVX_Vector * ) (vtcm_dst + tile_idx * HTP_MM_HMX_TILE_N_ELMS ); 1264tile [r1 /2 ]= v_out ; 1265 } 1266 } 1267 1268for (;r < n_rows_padded ;r += 2 ) { 1269uint32_t lr = vtcm_start_row + r ;// vtcm-local row 1270uint32_t r0 = lr /HTP_MM_HMX_TILE_N_ROWS ;// tile row index 1271uint32_t r1 = lr %HTP_MM_HMX_TILE_N_ROWS ;// intra-tile row idx 1272 1273const bool row0_valid = (start_row + r + 0 )< cne1 ; 1274const bool row1_valid = (start_row + r + 1 )< cne1 ; 1275 1276const float * row0_ptr = NULL ; 1277const float * row1_ptr = NULL ; 1278 1279if (row0_valid ) { 1280struct mmid_row_mapping mapping0 = matrix_rows [cur_a * mapping_stride + (start_row + r + 0 )]; 1281row0_ptr = (const float * ) ((const uint8_t * )src + mapping0 .i2 * nb12 ); 1282 } 1283if (row1_valid ) { 1284struct mmid_row_mapping mapping1 = matrix_rows [cur_a * mapping_stride + (start_row + r + 1 )]; 1285row1_ptr = (const float * ) ((const uint8_t * )src + mapping1 .i2 * nb12 ); 1286 } 1287 1288uint32_t c = 0 ; 1289for (;c + 32 <=k_valid ;c += 32 ) { 1290HVX_Vector v0 = Q6_V_vzero (); 1291HVX_Vector v1 = Q6_V_vzero (); 1292if (row0_valid )v0 = * (const HVX_Vector * )(row0_ptr + c ); 1293if (row1_valid )v1 = * (const HVX_Vector * )(row1_ptr + c ); 1294 1295HVX_Vector v_out = hvx_vec_f32_to_f16_shuff (v0 ,v1 ); 1296 1297uint32_t c0 = c /HTP_MM_HMX_TILE_N_COLS ; 1298uint32_t tile_idx = r0 * (k_block /HTP_MM_HMX_TILE_N_COLS )+ c0 ; 1299 1300HVX_Vector * tile = (HVX_Vector * ) (vtcm_dst + tile_idx * HTP_MM_HMX_TILE_N_ELMS ); 1301tile [r1 /2 ]= v_out ; 1302 } 1303if (c < k_block ) { 1304HVX_Vector v0 = Q6_V_vzero (); 1305HVX_Vector v1 = Q6_V_vzero (); 1306if (row0_valid )v0 = * (const HVX_Vector * )(row0_ptr + c ); 1307if (row1_valid )v1 = * (const HVX_Vector * )(row1_ptr + c ); 1308 1309uint32_t rem = k_valid - c ; 1310HVX_VectorPred mask = Q6_Q_vsetq2_R (rem > 0 ?rem * sizeof (float ) :0 ); 1311v0 = Q6_V_vmux_QVV (mask ,v0 ,Q6_V_vzero ()); 1312v1 = Q6_V_vmux_QVV (mask ,v1 ,Q6_V_vzero ()); 1313 1314HVX_Vector v_out = hvx_vec_f32_to_f16_shuff (v0 ,v1 ); 1315 1316uint32_t c0 = c /HTP_MM_HMX_TILE_N_COLS ; 1317uint32_t tile_idx = r0 * (k_block /HTP_MM_HMX_TILE_N_COLS )+ c0 ; 1318 1319HVX_Vector * tile = (HVX_Vector * ) (vtcm_dst + tile_idx * HTP_MM_HMX_TILE_N_ELMS ); 1320tile [r1 /2 ]= v_out ; 1321 } 1322 } 1323} 1324 1325static void transfer_output_chunk_fp16_to_fp32_scattered ( 1326float * restrictdst , 1327const __fp16 * restrictvtcm_src , 1328uint32_t start_row , 1329uint32_t vtcm_start_row , 1330uint32_t n_rows , 1331uint32_t n_cols , 1332const struct mmid_row_mapping * matrix_rows , 1333uint32_t cur_a , 1334uint32_t mapping_stride , 1335size_t dst_nb1 , 1336size_t dst_nb2 , 1337uint32_t cne1 ) { 1338assert (n_cols %HTP_MM_HMX_TILE_N_COLS == 0 ); 1339const size_t tile_row_stride = (n_cols /HTP_MM_HMX_TILE_N_COLS )* HTP_MM_HMX_TILE_N_ELMS ; 1340 1341const HVX_Vector one = hvx_vec_splat_f16 (1.0 ); 1342 1343for (size_t r = 0 ;r < n_rows ;r += 2 ) { 1344uint32_t r_idx0 = start_row + r + 0 ; 1345uint32_t r_idx1 = start_row + r + 1 ; 1346uint32_t lr = vtcm_start_row + r ;// vtcm-local row 1347const size_t r0 = (lr /HTP_MM_HMX_TILE_N_ROWS ); 1348const size_t r1 = (lr %HTP_MM_HMX_TILE_N_ROWS ) /2 ;// index of the row pair within the tile 1349const __fp16 * row_base = vtcm_src + r0 * tile_row_stride ; 1350 1351if (r_idx0 >=cne1 )break ; 1352 1353struct mmid_row_mapping mapping0 = matrix_rows [cur_a * mapping_stride + r_idx0 ]; 1354float * output_row0 = (float * ) ((uint8_t * )dst + mapping0 .i1 * dst_nb1 + mapping0 .i2 * dst_nb2 ); 1355 1356float * output_row1 = NULL ; 1357if (r_idx1 < cne1 ) { 1358struct mmid_row_mapping mapping1 = matrix_rows [cur_a * mapping_stride + r_idx1 ]; 1359output_row1 = (float * ) ((uint8_t * )dst + mapping1 .i1 * dst_nb1 + mapping1 .i2 * dst_nb2 ); 1360 } 1361 1362#pragma unroll(4) 1363for (size_t c = 0 ;c < (size_t )n_cols ;c += HTP_MM_HMX_TILE_N_COLS ) { 1364const size_t c0 = c /HTP_MM_HMX_TILE_N_COLS ; 1365const __fp16 * tile = row_base + c0 * HTP_MM_HMX_TILE_N_ELMS ; 1366HVX_Vector v = ((const HVX_Vector * )tile )[r1 ]; 1367HVX_VectorPair vp = Q6_Wqf32_vmpy_VhfVhf (v ,one ); 1368 1369HVX_Vector * pv_out0 = (HVX_Vector * ) (output_row0 + c ); 1370HVX_Vector * pv_out1 = output_row1 ? (HVX_Vector * ) (output_row1 + c ) :NULL ; 1371 1372* pv_out0 = Q6_Vsf_equals_Vqf32 (Q6_V_lo_W (vp )); 1373if (pv_out1 ) { 1374* pv_out1 = Q6_Vsf_equals_Vqf32 (Q6_V_hi_W (vp )); 1375 } 1376 } 1377 } 1378}