whispercpp 1.3.6 → 1.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (965) hide show
  1. checksums.yaml +4 -4
  2. data/.document +3 -0
  3. data/.rdoc_options +2 -0
  4. data/README.md +43 -9
  5. data/Rakefile +18 -3
  6. data/ext/dependencies.rb +10 -4
  7. data/ext/dependencies_for_windows.rb +17 -0
  8. data/ext/extconf.rb +20 -8
  9. data/ext/options.rb +54 -14
  10. data/ext/options_for_windows.rb +51 -0
  11. data/ext/ruby_whisper.c +35 -42
  12. data/ext/ruby_whisper.h +141 -0
  13. data/ext/ruby_whisper_context.c +157 -29
  14. data/ext/ruby_whisper_log_queue.c +180 -0
  15. data/ext/ruby_whisper_log_settable.h +46 -0
  16. data/ext/ruby_whisper_parakeet.c +49 -0
  17. data/ext/ruby_whisper_parakeet_context.c +304 -0
  18. data/ext/ruby_whisper_parakeet_context_params.c +117 -0
  19. data/ext/ruby_whisper_parakeet_model.c +84 -0
  20. data/ext/ruby_whisper_parakeet_params.c +548 -0
  21. data/ext/ruby_whisper_parakeet_segment.c +157 -0
  22. data/ext/ruby_whisper_parakeet_token.c +188 -0
  23. data/ext/ruby_whisper_parakeet_transcribe.cpp +58 -0
  24. data/ext/ruby_whisper_params.c +265 -73
  25. data/ext/ruby_whisper_segment.c +6 -6
  26. data/ext/ruby_whisper_transcribe.cpp +23 -15
  27. data/ext/ruby_whisper_vad_context.c +30 -10
  28. data/ext/ruby_whisper_vad_context_detect.cpp +8 -9
  29. data/ext/ruby_whisper_vad_params.c +4 -4
  30. data/ext/ruby_whisper_vad_segment.c +2 -2
  31. data/ext/sources/CMakeLists.txt +42 -3
  32. data/ext/sources/CMakePresets.json +95 -0
  33. data/ext/sources/cmake/parakeet-config.cmake.in +30 -0
  34. data/ext/sources/cmake/parakeet.pc.in +10 -0
  35. data/ext/sources/cmake/whisper.pc.in +2 -2
  36. data/ext/sources/examples/CMakeLists.txt +4 -2
  37. data/ext/sources/examples/bench/bench.cpp +1 -1
  38. data/ext/sources/examples/cli/cli.cpp +52 -10
  39. data/ext/sources/examples/common-ggml.cpp +4 -0
  40. data/ext/sources/examples/common-whisper.cpp +139 -67
  41. data/ext/sources/examples/common-whisper.h +11 -0
  42. data/ext/sources/examples/ffmpeg-transcode.cpp +211 -341
  43. data/ext/sources/examples/parakeet-cli/CMakeLists.txt +8 -0
  44. data/ext/sources/examples/parakeet-cli/parakeet-cli.cpp +243 -0
  45. data/ext/sources/examples/parakeet-quantize/CMakeLists.txt +7 -0
  46. data/ext/sources/examples/parakeet-quantize/parakeet-quantize.cpp +230 -0
  47. data/ext/sources/examples/server/server.cpp +199 -163
  48. data/ext/sources/examples/vad-speech-segments/speech.cpp +3 -2
  49. data/ext/sources/ggml/CMakeLists.txt +21 -14
  50. data/ext/sources/ggml/cmake/FindNCCL.cmake +36 -0
  51. data/ext/sources/ggml/cmake/ggml-config.cmake.in +12 -2
  52. data/ext/sources/ggml/include/ggml-alloc.h +1 -0
  53. data/ext/sources/ggml/include/ggml-backend.h +72 -10
  54. data/ext/sources/ggml/include/ggml-cuda.h +2 -2
  55. data/ext/sources/ggml/include/ggml-rpc.h +3 -3
  56. data/ext/sources/ggml/include/ggml-sycl.h +8 -0
  57. data/ext/sources/ggml/include/ggml.h +103 -9
  58. data/ext/sources/ggml/include/gguf.h +10 -2
  59. data/ext/sources/ggml/src/CMakeLists.txt +30 -6
  60. data/ext/sources/ggml/src/ggml-alloc.c +5 -1
  61. data/ext/sources/ggml/src/ggml-backend-impl.h +22 -2
  62. data/ext/sources/ggml/src/ggml-backend-meta.cpp +2266 -0
  63. data/ext/sources/ggml/src/ggml-backend-reg.cpp +12 -0
  64. data/ext/sources/ggml/src/ggml-backend.cpp +110 -9
  65. data/ext/sources/ggml/src/ggml-blas/ggml-blas.cpp +4 -0
  66. data/ext/sources/ggml/src/ggml-cann/aclnn_ops.cpp +672 -257
  67. data/ext/sources/ggml/src/ggml-cann/aclnn_ops.h +71 -0
  68. data/ext/sources/ggml/src/ggml-cann/common.h +20 -10
  69. data/ext/sources/ggml/src/ggml-cann/ggml-cann.cpp +211 -30
  70. data/ext/sources/ggml/src/ggml-common.h +24 -2
  71. data/ext/sources/ggml/src/ggml-cpu/CMakeLists.txt +59 -30
  72. data/ext/sources/ggml/src/ggml-cpu/amx/amx.cpp +2 -0
  73. data/ext/sources/ggml/src/ggml-cpu/amx/mmq.cpp +21 -22
  74. data/ext/sources/ggml/src/ggml-cpu/arch/arm/quants.c +194 -11
  75. data/ext/sources/ggml/src/ggml-cpu/arch/arm/repack.cpp +65 -0
  76. data/ext/sources/ggml/src/ggml-cpu/arch/loongarch/quants.c +151 -1
  77. data/ext/sources/ggml/src/ggml-cpu/arch/powerpc/quants.c +0 -1
  78. data/ext/sources/ggml/src/ggml-cpu/arch/riscv/quants.c +4279 -1292
  79. data/ext/sources/ggml/src/ggml-cpu/arch/riscv/repack.cpp +5 -35
  80. data/ext/sources/ggml/src/ggml-cpu/arch/s390/quants.c +0 -1
  81. data/ext/sources/ggml/src/ggml-cpu/arch/wasm/quants.c +72 -1
  82. data/ext/sources/ggml/src/ggml-cpu/arch/x86/quants.c +319 -31
  83. data/ext/sources/ggml/src/ggml-cpu/arch/x86/repack.cpp +1 -1
  84. data/ext/sources/ggml/src/ggml-cpu/arch-fallback.h +12 -2
  85. data/ext/sources/ggml/src/ggml-cpu/cmake/FindSMTIME.cmake +32 -0
  86. data/ext/sources/ggml/src/ggml-cpu/ggml-cpu-impl.h +10 -0
  87. data/ext/sources/ggml/src/ggml-cpu/ggml-cpu.c +109 -5
  88. data/ext/sources/ggml/src/ggml-cpu/ggml-cpu.cpp +2 -0
  89. data/ext/sources/ggml/src/ggml-cpu/kleidiai/kleidiai.cpp +146 -134
  90. data/ext/sources/ggml/src/ggml-cpu/llamafile/sgemm.cpp +107 -82
  91. data/ext/sources/ggml/src/ggml-cpu/ops.cpp +501 -119
  92. data/ext/sources/ggml/src/ggml-cpu/ops.h +3 -0
  93. data/ext/sources/ggml/src/ggml-cpu/quants.c +106 -0
  94. data/ext/sources/ggml/src/ggml-cpu/quants.h +6 -0
  95. data/ext/sources/ggml/src/ggml-cpu/repack.cpp +3 -0
  96. data/ext/sources/ggml/src/ggml-cpu/simd-gemm.h +91 -1
  97. data/ext/sources/ggml/src/ggml-cpu/simd-mappings.h +14 -16
  98. data/ext/sources/ggml/src/ggml-cpu/spacemit/ime.cpp +1402 -687
  99. data/ext/sources/ggml/src/ggml-cpu/spacemit/ime.h +8 -0
  100. data/ext/sources/ggml/src/ggml-cpu/spacemit/ime1_kernels.cpp +597 -2766
  101. data/ext/sources/ggml/src/ggml-cpu/spacemit/ime2_kernels.cpp +5768 -0
  102. data/ext/sources/ggml/src/ggml-cpu/spacemit/ime_env.cpp +320 -0
  103. data/ext/sources/ggml/src/ggml-cpu/spacemit/ime_env.h +55 -0
  104. data/ext/sources/ggml/src/ggml-cpu/spacemit/ime_kernels.h +182 -19
  105. data/ext/sources/ggml/src/ggml-cpu/spacemit/repack.cpp +1795 -0
  106. data/ext/sources/ggml/src/ggml-cpu/spacemit/repack.h +14 -0
  107. data/ext/sources/ggml/src/ggml-cpu/spacemit/rvv_kernels.cpp +3178 -0
  108. data/ext/sources/ggml/src/ggml-cpu/spacemit/rvv_kernels.h +95 -0
  109. data/ext/sources/ggml/src/ggml-cpu/spacemit/spine_barrier.h +34 -0
  110. data/ext/sources/ggml/src/ggml-cpu/spacemit/spine_mem_pool.cpp +760 -0
  111. data/ext/sources/ggml/src/ggml-cpu/spacemit/spine_mem_pool.h +32 -0
  112. data/ext/sources/ggml/src/ggml-cpu/spacemit/spine_tcm.h +409 -0
  113. data/ext/sources/ggml/src/ggml-cpu/vec.cpp +39 -55
  114. data/ext/sources/ggml/src/ggml-cpu/vec.h +225 -240
  115. data/ext/sources/ggml/src/ggml-cuda/CMakeLists.txt +17 -7
  116. data/ext/sources/ggml/src/ggml-cuda/allreduce.cu +971 -0
  117. data/ext/sources/ggml/src/ggml-cuda/allreduce.cuh +29 -0
  118. data/ext/sources/ggml/src/ggml-cuda/argsort.cu +62 -26
  119. data/ext/sources/ggml/src/ggml-cuda/binbcast.cu +134 -64
  120. data/ext/sources/ggml/src/ggml-cuda/binbcast.cuh +1 -0
  121. data/ext/sources/ggml/src/ggml-cuda/col2im-1d.cu +81 -0
  122. data/ext/sources/ggml/src/ggml-cuda/col2im-1d.cuh +3 -0
  123. data/ext/sources/ggml/src/ggml-cuda/common.cuh +246 -28
  124. data/ext/sources/ggml/src/ggml-cuda/concat.cu +134 -116
  125. data/ext/sources/ggml/src/ggml-cuda/conv-transpose-1d.cu +14 -12
  126. data/ext/sources/ggml/src/ggml-cuda/conv2d-transpose.cu +45 -21
  127. data/ext/sources/ggml/src/ggml-cuda/conv2d-transpose.cuh +1 -0
  128. data/ext/sources/ggml/src/ggml-cuda/convert.cu +139 -34
  129. data/ext/sources/ggml/src/ggml-cuda/convert.cuh +10 -0
  130. data/ext/sources/ggml/src/ggml-cuda/cpy.cu +88 -29
  131. data/ext/sources/ggml/src/ggml-cuda/dequantize.cuh +22 -0
  132. data/ext/sources/ggml/src/ggml-cuda/fattn-common.cuh +287 -49
  133. data/ext/sources/ggml/src/ggml-cuda/fattn-mma-f16.cuh +335 -130
  134. data/ext/sources/ggml/src/ggml-cuda/fattn-tile.cu +12 -0
  135. data/ext/sources/ggml/src/ggml-cuda/fattn-tile.cuh +127 -24
  136. data/ext/sources/ggml/src/ggml-cuda/fattn-vec.cuh +40 -15
  137. data/ext/sources/ggml/src/ggml-cuda/fattn-wmma-f16.cu +18 -9
  138. data/ext/sources/ggml/src/ggml-cuda/fattn.cu +169 -60
  139. data/ext/sources/ggml/src/ggml-cuda/fattn.cuh +2 -0
  140. data/ext/sources/ggml/src/ggml-cuda/fwht.cu +101 -0
  141. data/ext/sources/ggml/src/ggml-cuda/fwht.cuh +4 -0
  142. data/ext/sources/ggml/src/ggml-cuda/gated_delta_net.cu +109 -45
  143. data/ext/sources/ggml/src/ggml-cuda/gated_delta_net.cuh +10 -0
  144. data/ext/sources/ggml/src/ggml-cuda/getrows.cu +48 -23
  145. data/ext/sources/ggml/src/ggml-cuda/ggml-cuda.cu +2034 -2104
  146. data/ext/sources/ggml/src/ggml-cuda/im2col.cu +32 -29
  147. data/ext/sources/ggml/src/ggml-cuda/mean.cu +4 -2
  148. data/ext/sources/ggml/src/ggml-cuda/mma.cuh +242 -195
  149. data/ext/sources/ggml/src/ggml-cuda/mmf.cuh +3 -3
  150. data/ext/sources/ggml/src/ggml-cuda/mmq.cu +25 -12
  151. data/ext/sources/ggml/src/ggml-cuda/mmq.cuh +502 -423
  152. data/ext/sources/ggml/src/ggml-cuda/mmvf.cu +19 -12
  153. data/ext/sources/ggml/src/ggml-cuda/mmvq.cu +562 -97
  154. data/ext/sources/ggml/src/ggml-cuda/mmvq.cuh +6 -1
  155. data/ext/sources/ggml/src/ggml-cuda/norm.cu +36 -10
  156. data/ext/sources/ggml/src/ggml-cuda/out-prod.cu +66 -7
  157. data/ext/sources/ggml/src/ggml-cuda/quantize.cu +133 -26
  158. data/ext/sources/ggml/src/ggml-cuda/quantize.cuh +1 -1
  159. data/ext/sources/ggml/src/ggml-cuda/reduce_rows.cuh +5 -1
  160. data/ext/sources/ggml/src/ggml-cuda/rope.cu +11 -4
  161. data/ext/sources/ggml/src/ggml-cuda/scale.cu +4 -1
  162. data/ext/sources/ggml/src/ggml-cuda/set-rows.cu +78 -10
  163. data/ext/sources/ggml/src/ggml-cuda/snake.cu +72 -0
  164. data/ext/sources/ggml/src/ggml-cuda/snake.cuh +8 -0
  165. data/ext/sources/ggml/src/ggml-cuda/softcap.cu +4 -1
  166. data/ext/sources/ggml/src/ggml-cuda/ssm-conv.cu +45 -13
  167. data/ext/sources/ggml/src/ggml-cuda/ssm-conv.cuh +1 -1
  168. data/ext/sources/ggml/src/ggml-cuda/ssm-scan.cu +40 -18
  169. data/ext/sources/ggml/src/ggml-cuda/sumrows.cu +8 -4
  170. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_1-ncols2_16.cu +1 -0
  171. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_1-ncols2_32.cu +1 -0
  172. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_1-ncols2_8.cu +2 -0
  173. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_16-ncols2_2.cu +1 -0
  174. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_16-ncols2_4.cu +1 -0
  175. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_2-ncols2_16.cu +1 -0
  176. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_2-ncols2_32.cu +1 -0
  177. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_2-ncols2_4.cu +1 -0
  178. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_2-ncols2_8.cu +2 -0
  179. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_32-ncols2_2.cu +1 -0
  180. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_4-ncols2_16.cu +1 -0
  181. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_4-ncols2_2.cu +1 -0
  182. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_4-ncols2_4.cu +1 -0
  183. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_4-ncols2_8.cu +2 -0
  184. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_8-ncols2_2.cu +1 -0
  185. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_8-ncols2_4.cu +1 -0
  186. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_8-ncols2_8.cu +2 -0
  187. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq192-dv128.cu +5 -0
  188. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq320-dv256.cu +5 -0
  189. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq512-dv512.cu +5 -0
  190. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-bf16.cu +7 -0
  191. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-f16.cu +7 -0
  192. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-q4_0.cu +7 -0
  193. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-q4_1.cu +7 -0
  194. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-q5_0.cu +7 -0
  195. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-q5_1.cu +7 -0
  196. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-q8_0.cu +7 -0
  197. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-f16-bf16.cu +7 -0
  198. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_0-bf16.cu +7 -0
  199. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_1-bf16.cu +7 -0
  200. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_0-bf16.cu +7 -0
  201. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_1-bf16.cu +7 -0
  202. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q8_0-bf16.cu +7 -0
  203. data/ext/sources/ggml/src/ggml-cuda/template-instances/mmq-instance-nvfp4.cu +5 -0
  204. data/ext/sources/ggml/src/ggml-cuda/template-instances/mmq-instance-q1_0.cu +5 -0
  205. data/ext/sources/ggml/src/ggml-cuda/top-k.cu +5 -4
  206. data/ext/sources/ggml/src/ggml-cuda/topk-moe.cu +33 -24
  207. data/ext/sources/ggml/src/ggml-cuda/unary.cu +31 -2
  208. data/ext/sources/ggml/src/ggml-cuda/unary.cuh +2 -0
  209. data/ext/sources/ggml/src/ggml-cuda/vecdotq.cuh +80 -0
  210. data/ext/sources/ggml/src/ggml-cuda/vendors/cuda.h +7 -2
  211. data/ext/sources/ggml/src/ggml-cuda/vendors/hip.h +23 -4
  212. data/ext/sources/ggml/src/ggml-cuda/vendors/musa.h +4 -0
  213. data/ext/sources/ggml/src/ggml-hexagon/CMakeLists.txt +1 -5
  214. data/ext/sources/ggml/src/ggml-hexagon/ggml-hexagon.cpp +2788 -1762
  215. data/ext/sources/ggml/src/ggml-hexagon/htp/CMakeLists.txt +13 -4
  216. data/ext/sources/ggml/src/ggml-hexagon/htp/act-ops.c +53 -84
  217. data/ext/sources/ggml/src/ggml-hexagon/htp/argsort-ops.c +25 -12
  218. data/ext/sources/ggml/src/ggml-hexagon/htp/binary-ops.c +165 -184
  219. data/ext/sources/ggml/src/ggml-hexagon/htp/cmake-toolchain.cmake +17 -19
  220. data/ext/sources/ggml/src/ggml-hexagon/htp/concat-ops.c +277 -0
  221. data/ext/sources/ggml/src/ggml-hexagon/htp/cpy-ops.c +170 -127
  222. data/ext/sources/ggml/src/ggml-hexagon/htp/cumsum-ops.c +270 -0
  223. data/ext/sources/ggml/src/ggml-hexagon/htp/diag-ops.c +216 -0
  224. data/ext/sources/ggml/src/ggml-hexagon/htp/fill-ops.c +123 -0
  225. data/ext/sources/ggml/src/ggml-hexagon/htp/flash-attn-ops.c +1774 -396
  226. data/ext/sources/ggml/src/ggml-hexagon/htp/flash-attn-ops.h +303 -0
  227. data/ext/sources/ggml/src/ggml-hexagon/htp/gated-delta-net-ops.c +1148 -0
  228. data/ext/sources/ggml/src/ggml-hexagon/htp/get-rows-ops.c +148 -42
  229. data/ext/sources/ggml/src/ggml-hexagon/htp/hex-common.h +80 -0
  230. data/ext/sources/ggml/src/ggml-hexagon/htp/hex-dma.c +2 -2
  231. data/ext/sources/ggml/src/ggml-hexagon/htp/hex-dma.h +255 -62
  232. data/ext/sources/ggml/src/ggml-hexagon/htp/hex-dump.h +9 -0
  233. data/ext/sources/ggml/src/ggml-hexagon/htp/hex-profile.h +64 -0
  234. data/ext/sources/ggml/src/ggml-hexagon/htp/hex-utils.h +25 -21
  235. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-fa-kernels.h +555 -0
  236. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-mm-kernels-tiled.h +1303 -0
  237. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-queue.c +167 -0
  238. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-queue.h +157 -0
  239. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-utils.h +222 -0
  240. data/ext/sources/ggml/src/ggml-hexagon/htp/htp-ctx.h +104 -13
  241. data/ext/sources/ggml/src/ggml-hexagon/htp/htp-ops.h +222 -57
  242. data/ext/sources/ggml/src/ggml-hexagon/htp/htp-vtcm.h +19 -0
  243. data/ext/sources/ggml/src/ggml-hexagon/htp/htp_iface.idl +10 -3
  244. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-base.h +78 -26
  245. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-copy.h +27 -10
  246. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-div.h +63 -23
  247. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-exp.h +48 -8
  248. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-fa-kernels.h +232 -0
  249. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-flash-attn.h +47 -0
  250. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-log.h +65 -0
  251. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-mm-kernels-flat.h +1511 -0
  252. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-mm-kernels-tiled.h +1200 -0
  253. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-pow.h +42 -0
  254. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-repl.h +74 -0
  255. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-sigmoid.h +40 -0
  256. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-sin-cos.h +90 -0
  257. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-utils.h +5 -8
  258. data/ext/sources/ggml/src/ggml-hexagon/htp/main.c +625 -816
  259. data/ext/sources/ggml/src/ggml-hexagon/htp/matmul-ops.c +3052 -2166
  260. data/ext/sources/ggml/src/ggml-hexagon/htp/matmul-ops.h +650 -0
  261. data/ext/sources/ggml/src/ggml-hexagon/htp/pad-ops.c +547 -0
  262. data/ext/sources/ggml/src/ggml-hexagon/htp/repeat-ops.c +148 -0
  263. data/ext/sources/ggml/src/ggml-hexagon/htp/rope-ops.c +337 -106
  264. data/ext/sources/ggml/src/ggml-hexagon/htp/set-rows-ops.c +59 -37
  265. data/ext/sources/ggml/src/ggml-hexagon/htp/softmax-ops.c +121 -133
  266. data/ext/sources/ggml/src/ggml-hexagon/htp/solve-tri-ops.c +267 -0
  267. data/ext/sources/ggml/src/ggml-hexagon/htp/ssm-conv.c +245 -151
  268. data/ext/sources/ggml/src/ggml-hexagon/htp/sum-rows-ops.c +6 -6
  269. data/ext/sources/ggml/src/ggml-hexagon/htp/unary-ops.c +719 -45
  270. data/ext/sources/ggml/src/ggml-hexagon/htp/worker-pool.c +15 -3
  271. data/ext/sources/ggml/src/ggml-hexagon/htp/worker-pool.h +8 -0
  272. data/ext/sources/ggml/src/ggml-hexagon/htp-opnode.h +390 -0
  273. data/ext/sources/ggml/src/ggml-hexagon/libggml-htp.inf +3 -5
  274. data/ext/sources/ggml/src/ggml-hip/CMakeLists.txt +27 -9
  275. data/ext/sources/ggml/src/ggml-impl.h +6 -1
  276. data/ext/sources/ggml/src/ggml-metal/ggml-metal-device.cpp +207 -18
  277. data/ext/sources/ggml/src/ggml-metal/ggml-metal-device.h +36 -2
  278. data/ext/sources/ggml/src/ggml-metal/ggml-metal-device.m +186 -29
  279. data/ext/sources/ggml/src/ggml-metal/ggml-metal-impl.h +118 -0
  280. data/ext/sources/ggml/src/ggml-metal/ggml-metal-ops.cpp +322 -21
  281. data/ext/sources/ggml/src/ggml-metal/ggml-metal-ops.h +4 -0
  282. data/ext/sources/ggml/src/ggml-metal/ggml-metal.cpp +39 -26
  283. data/ext/sources/ggml/src/ggml-metal/ggml-metal.metal +1226 -467
  284. data/ext/sources/ggml/src/ggml-musa/CMakeLists.txt +5 -6
  285. data/ext/sources/ggml/src/ggml-opencl/CMakeLists.txt +67 -5
  286. data/ext/sources/ggml/src/ggml-opencl/fa_tune.h +92 -0
  287. data/ext/sources/ggml/src/ggml-opencl/ggml-opencl.cpp +16290 -6246
  288. data/ext/sources/ggml/src/ggml-opencl/kernels/concat.cl +67 -0
  289. data/ext/sources/ggml/src/ggml-opencl/kernels/cpy.cl +59 -0
  290. data/ext/sources/ggml/src/ggml-opencl/kernels/cvt.cl +1997 -92
  291. data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_f16.cl +81 -41
  292. data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_f32.cl +88 -39
  293. data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_f32_f16.cl +1995 -96
  294. data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_f32_q4_0.cl +1615 -0
  295. data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_f32_q8_0.cl +1486 -0
  296. data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_pre_f16.cl +156 -0
  297. data/ext/sources/ggml/src/ggml-opencl/kernels/gated_delta_net.cl +249 -0
  298. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_mxfp4_f32_ns.cl +374 -0
  299. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q4_0_f32_ns.cl +324 -0
  300. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q4_1_f32_ns.cl +326 -0
  301. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q4_k_f32_ns.cl +348 -0
  302. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q5_0_f32_ns.cl +328 -0
  303. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q5_1_f32_ns.cl +330 -0
  304. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q5_k_f32_ns.cl +356 -0
  305. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q6_k_f32_ns.cl +335 -0
  306. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_noshuffle_iq4_nl_f32.cl +150 -0
  307. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_noshuffle_q1_0_f32.cl +94 -0
  308. data/ext/sources/ggml/src/ggml-opencl/kernels/{mul_mat_Ab_Bi_8x4.cl → gemm_noshuffle_q4_0_f32.cl} +1 -1
  309. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_noshuffle_q4_k_f32.cl +172 -0
  310. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_noshuffle_q5_0_f32.cl +131 -0
  311. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_noshuffle_q5_1_f32.cl +134 -0
  312. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_noshuffle_q5_k_f32.cl +176 -0
  313. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_noshuffle_q6_k_f32.cl +140 -0
  314. data/ext/sources/ggml/src/ggml-opencl/kernels/{mul_mm_q8_0_f32_8x4.cl → gemm_noshuffle_q8_0_f32.cl} +1 -1
  315. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_xmem_f16_f32_os8.cl +233 -0
  316. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_moe_mxfp4_f32_ns.cl +165 -0
  317. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_moe_q4_0_f32_ns.cl +120 -0
  318. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_moe_q4_1_f32_ns.cl +123 -0
  319. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_moe_q4_k_f32_ns.cl +155 -0
  320. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_moe_q5_0_f32_ns.cl +123 -0
  321. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_moe_q5_1_f32_ns.cl +125 -0
  322. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_moe_q5_k_f32_ns.cl +160 -0
  323. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_moe_q6_k_f32_ns.cl +141 -0
  324. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_noshuffle_iq4_nl_f32.cl +302 -0
  325. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_noshuffle_q1_0_f32.cl +121 -0
  326. data/ext/sources/ggml/src/ggml-opencl/kernels/{gemv_noshuffle_general.cl → gemv_noshuffle_q4_0_f32.cl} +5 -5
  327. data/ext/sources/ggml/src/ggml-opencl/kernels/{gemv_noshuffle.cl → gemv_noshuffle_q4_0_f32_spec.cl} +5 -5
  328. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_noshuffle_q4_k_f32.cl +318 -0
  329. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_noshuffle_q5_0_f32.cl +291 -0
  330. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_noshuffle_q5_1_f32.cl +294 -0
  331. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_noshuffle_q5_k_f32.cl +326 -0
  332. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_noshuffle_q6_k_f32.cl +293 -0
  333. data/ext/sources/ggml/src/ggml-opencl/kernels/{gemv_noshuffle_general_q8_0_f32.cl → gemv_noshuffle_q8_0_f32.cl} +1 -1
  334. data/ext/sources/ggml/src/ggml-opencl/kernels/get_rows.cl +15 -9
  335. data/ext/sources/ggml/src/ggml-opencl/kernels/moe_reorder_b.cl +30 -0
  336. data/ext/sources/ggml/src/ggml-opencl/kernels/moe_sort_by_expert.cl +82 -0
  337. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mm_iq4_nl_f32_l4_lm.cl +171 -0
  338. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mm_q1_0_f32_l4_lm.cl +156 -0
  339. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mm_q4_k_f32_l4_lm.cl +179 -0
  340. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mm_q5_0_f32_l4_lm.cl +173 -0
  341. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mm_q5_1_f32_l4_lm.cl +175 -0
  342. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mm_q5_k_f32_l4_lm.cl +192 -0
  343. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_f16_f32_l4.cl +1149 -0
  344. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_iq4_nl_f32.cl +164 -0
  345. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_iq4_nl_f32_flat.cl +202 -0
  346. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_q1_0_f32.cl +141 -0
  347. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_q1_0_f32_flat.cl +190 -0
  348. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_q4_k_f32_flat.cl +196 -0
  349. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_q5_0_f32.cl +241 -0
  350. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_q5_0_f32_flat.cl +243 -0
  351. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_q5_1_f32.cl +243 -0
  352. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_q5_1_f32_flat.cl +247 -0
  353. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_q5_k_f32.cl +187 -0
  354. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_q5_k_f32_flat.cl +203 -0
  355. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_q6_k_f32_flat.cl +48 -64
  356. data/ext/sources/ggml/src/ggml-opencl/kernels/norm.cl +5 -2
  357. data/ext/sources/ggml/src/ggml-opencl/kernels/set_rows.cl +500 -0
  358. data/ext/sources/ggml/src/ggml-opencl/libdl.h +79 -0
  359. data/ext/sources/ggml/src/ggml-openvino/.clang-format +0 -5
  360. data/ext/sources/ggml/src/ggml-openvino/CMakeLists.txt +2 -4
  361. data/ext/sources/ggml/src/ggml-openvino/ggml-decoder.cpp +740 -127
  362. data/ext/sources/ggml/src/ggml-openvino/ggml-decoder.h +76 -23
  363. data/ext/sources/ggml/src/ggml-openvino/ggml-openvino-extra.cpp +75 -14
  364. data/ext/sources/ggml/src/ggml-openvino/ggml-openvino-extra.h +29 -8
  365. data/ext/sources/ggml/src/ggml-openvino/ggml-openvino.cpp +339 -69
  366. data/ext/sources/ggml/src/ggml-openvino/ggml-quants.cpp +330 -192
  367. data/ext/sources/ggml/src/ggml-openvino/ggml-quants.h +10 -4
  368. data/ext/sources/ggml/src/ggml-openvino/openvino/decoder.h +56 -16
  369. data/ext/sources/ggml/src/ggml-openvino/openvino/frontend.h +1 -1
  370. data/ext/sources/ggml/src/ggml-openvino/openvino/input_model.h +4 -4
  371. data/ext/sources/ggml/src/ggml-openvino/openvino/node_context.h +94 -37
  372. data/ext/sources/ggml/src/ggml-openvino/openvino/op/add_id.cpp +76 -0
  373. data/ext/sources/ggml/src/ggml-openvino/openvino/op/argsort.cpp +47 -0
  374. data/ext/sources/ggml/src/ggml-openvino/openvino/op/clamp.cpp +33 -0
  375. data/ext/sources/ggml/src/ggml-openvino/openvino/op/concat.cpp +48 -0
  376. data/ext/sources/ggml/src/ggml-openvino/openvino/op/cont.cpp +8 -16
  377. data/ext/sources/ggml/src/ggml-openvino/openvino/op/cpy.cpp +14 -1
  378. data/ext/sources/ggml/src/ggml-openvino/openvino/op/div.cpp +146 -0
  379. data/ext/sources/ggml/src/ggml-openvino/openvino/op/flash_attn_ext.cpp +108 -21
  380. data/ext/sources/ggml/src/ggml-openvino/openvino/op/gated_delta_net.cpp +282 -0
  381. data/ext/sources/ggml/src/ggml-openvino/openvino/op/gated_delta_net.hpp +65 -0
  382. data/ext/sources/ggml/src/ggml-openvino/openvino/op/get_rows.cpp +2 -9
  383. data/ext/sources/ggml/src/ggml-openvino/openvino/op/glu_geglu.cpp +21 -7
  384. data/ext/sources/ggml/src/ggml-openvino/openvino/op/glu_swiglu.cpp +41 -8
  385. data/ext/sources/ggml/src/ggml-openvino/openvino/op/im2col.cpp +120 -0
  386. data/ext/sources/ggml/src/ggml-openvino/openvino/op/l2_norm.cpp +44 -0
  387. data/ext/sources/ggml/src/ggml-openvino/openvino/op/mul_mat_id.cpp +226 -0
  388. data/ext/sources/ggml/src/ggml-openvino/openvino/op/mulmat.cpp +19 -9
  389. data/ext/sources/ggml/src/ggml-openvino/openvino/op/norm.cpp +58 -0
  390. data/ext/sources/ggml/src/ggml-openvino/openvino/op/pad.cpp +95 -0
  391. data/ext/sources/ggml/src/ggml-openvino/openvino/op/permute.cpp +58 -13
  392. data/ext/sources/ggml/src/ggml-openvino/openvino/op/repeat.cpp +74 -0
  393. data/ext/sources/ggml/src/ggml-openvino/openvino/op/reshape.cpp +13 -6
  394. data/ext/sources/ggml/src/ggml-openvino/openvino/op/rms_norm.cpp +1 -1
  395. data/ext/sources/ggml/src/ggml-openvino/openvino/op/rope.cpp +161 -39
  396. data/ext/sources/ggml/src/ggml-openvino/openvino/op/set_rows.cpp +3 -3
  397. data/ext/sources/ggml/src/ggml-openvino/openvino/op/softmax.cpp +126 -49
  398. data/ext/sources/ggml/src/ggml-openvino/openvino/op/ssm_conv.cpp +59 -0
  399. data/ext/sources/ggml/src/ggml-openvino/openvino/op/sum_rows.cpp +27 -0
  400. data/ext/sources/ggml/src/ggml-openvino/openvino/op/transpose.cpp +32 -1
  401. data/ext/sources/ggml/src/ggml-openvino/openvino/op/unary_silu.cpp +1 -1
  402. data/ext/sources/ggml/src/ggml-openvino/openvino/op/unary_softplus.cpp +38 -0
  403. data/ext/sources/ggml/src/ggml-openvino/openvino/op/view.cpp +90 -25
  404. data/ext/sources/ggml/src/ggml-openvino/openvino/op_table.cpp +41 -22
  405. data/ext/sources/ggml/src/ggml-openvino/openvino/op_table.h +18 -4
  406. data/ext/sources/ggml/src/ggml-openvino/openvino/pass/mark_decompression_convert_constant_folding.h +1 -1
  407. data/ext/sources/ggml/src/ggml-openvino/openvino/rt_info/weightless_caching_attributes.hpp +41 -0
  408. data/ext/sources/ggml/src/ggml-openvino/openvino/translate_session.cpp +70 -43
  409. data/ext/sources/ggml/src/ggml-openvino/openvino/translate_session.h +5 -4
  410. data/ext/sources/ggml/src/ggml-openvino/openvino/utils.cpp +612 -36
  411. data/ext/sources/ggml/src/ggml-openvino/openvino/utils.h +29 -26
  412. data/ext/sources/ggml/src/ggml-openvino/utils.cpp +460 -114
  413. data/ext/sources/ggml/src/ggml-openvino/utils.h +32 -9
  414. data/ext/sources/ggml/src/ggml-opt.cpp +1 -0
  415. data/ext/sources/ggml/src/ggml-quants.c +365 -114
  416. data/ext/sources/ggml/src/ggml-quants.h +6 -0
  417. data/ext/sources/ggml/src/ggml-rpc/CMakeLists.txt +24 -0
  418. data/ext/sources/ggml/src/ggml-rpc/ggml-rpc.cpp +167 -311
  419. data/ext/sources/ggml/src/ggml-rpc/transport.cpp +683 -0
  420. data/ext/sources/ggml/src/ggml-rpc/transport.h +34 -0
  421. data/ext/sources/ggml/src/ggml-sycl/CMakeLists.txt +50 -4
  422. data/ext/sources/ggml/src/ggml-sycl/add-id.cpp +1 -1
  423. data/ext/sources/ggml/src/ggml-sycl/backend.hpp +5 -1
  424. data/ext/sources/ggml/src/ggml-sycl/binbcast.cpp +12 -0
  425. data/ext/sources/ggml/src/ggml-sycl/col2im-1d.cpp +102 -0
  426. data/ext/sources/ggml/src/ggml-sycl/col2im-1d.hpp +8 -0
  427. data/ext/sources/ggml/src/ggml-sycl/common.cpp +72 -2
  428. data/ext/sources/ggml/src/ggml-sycl/common.hpp +59 -2
  429. data/ext/sources/ggml/src/ggml-sycl/concat.cpp +21 -1
  430. data/ext/sources/ggml/src/ggml-sycl/conv2d-dw.cpp +158 -0
  431. data/ext/sources/ggml/src/ggml-sycl/conv2d-dw.hpp +10 -0
  432. data/ext/sources/ggml/src/ggml-sycl/conv2d-transpose.cpp +125 -0
  433. data/ext/sources/ggml/src/ggml-sycl/conv2d-transpose.hpp +10 -0
  434. data/ext/sources/ggml/src/ggml-sycl/conv2d.cpp +150 -0
  435. data/ext/sources/ggml/src/ggml-sycl/conv2d.hpp +10 -0
  436. data/ext/sources/ggml/src/ggml-sycl/conv3d.cpp +224 -0
  437. data/ext/sources/ggml/src/ggml-sycl/conv3d.hpp +8 -0
  438. data/ext/sources/ggml/src/ggml-sycl/convert.cpp +121 -13
  439. data/ext/sources/ggml/src/ggml-sycl/convert.hpp +9 -0
  440. data/ext/sources/ggml/src/ggml-sycl/cpy.cpp +706 -0
  441. data/ext/sources/ggml/src/ggml-sycl/cpy.hpp +281 -0
  442. data/ext/sources/ggml/src/ggml-sycl/cross_entropy_loss.cpp +255 -0
  443. data/ext/sources/ggml/src/ggml-sycl/cross_entropy_loss.hpp +7 -0
  444. data/ext/sources/ggml/src/ggml-sycl/cumsum.cpp +148 -0
  445. data/ext/sources/ggml/src/ggml-sycl/cumsum.hpp +5 -0
  446. data/ext/sources/ggml/src/ggml-sycl/dequantize.hpp +678 -0
  447. data/ext/sources/ggml/src/ggml-sycl/diag.cpp +67 -0
  448. data/ext/sources/ggml/src/ggml-sycl/diag.hpp +5 -0
  449. data/ext/sources/ggml/src/ggml-sycl/dmmv.cpp +997 -244
  450. data/ext/sources/ggml/src/ggml-sycl/dpct/helper.hpp +15 -7
  451. data/ext/sources/ggml/src/ggml-sycl/element_wise.cpp +215 -204
  452. data/ext/sources/ggml/src/ggml-sycl/element_wise.hpp +2 -2
  453. data/ext/sources/ggml/src/ggml-sycl/fattn-buffers.cpp +56 -0
  454. data/ext/sources/ggml/src/ggml-sycl/fattn-buffers.hpp +63 -0
  455. data/ext/sources/ggml/src/ggml-sycl/fattn-common.hpp +7 -5
  456. data/ext/sources/ggml/src/ggml-sycl/fattn-tile.cpp +4 -0
  457. data/ext/sources/ggml/src/ggml-sycl/fattn-tile.hpp +76 -168
  458. data/ext/sources/ggml/src/ggml-sycl/fattn-vec.hpp +7 -0
  459. data/ext/sources/ggml/src/ggml-sycl/fattn.cpp +3 -1
  460. data/ext/sources/ggml/src/ggml-sycl/fill.cpp +55 -0
  461. data/ext/sources/ggml/src/ggml-sycl/fill.hpp +5 -0
  462. data/ext/sources/ggml/src/ggml-sycl/gated_delta_net.cpp +69 -31
  463. data/ext/sources/ggml/src/ggml-sycl/gated_delta_net.hpp +1 -0
  464. data/ext/sources/ggml/src/ggml-sycl/gemm.hpp +3 -0
  465. data/ext/sources/ggml/src/ggml-sycl/getrows.cpp +79 -3
  466. data/ext/sources/ggml/src/ggml-sycl/ggml-sycl.cpp +1758 -455
  467. data/ext/sources/ggml/src/ggml-sycl/im2col.cpp +353 -89
  468. data/ext/sources/ggml/src/ggml-sycl/im2col.hpp +5 -3
  469. data/ext/sources/ggml/src/ggml-sycl/mmvq.cpp +1542 -39
  470. data/ext/sources/ggml/src/ggml-sycl/mmvq.hpp +33 -0
  471. data/ext/sources/ggml/src/ggml-sycl/norm.cpp +103 -49
  472. data/ext/sources/ggml/src/ggml-sycl/outprod.cpp +45 -9
  473. data/ext/sources/ggml/src/ggml-sycl/pad.cpp +27 -27
  474. data/ext/sources/ggml/src/ggml-sycl/pool.cpp +185 -0
  475. data/ext/sources/ggml/src/ggml-sycl/pool.hpp +22 -0
  476. data/ext/sources/ggml/src/ggml-sycl/presets.hpp +3 -1
  477. data/ext/sources/ggml/src/ggml-sycl/quants.hpp +71 -0
  478. data/ext/sources/ggml/src/ggml-sycl/set_rows.cpp +17 -3
  479. data/ext/sources/ggml/src/ggml-sycl/softmax.cpp +9 -10
  480. data/ext/sources/ggml/src/ggml-sycl/solve_tri.cpp +172 -0
  481. data/ext/sources/ggml/src/ggml-sycl/solve_tri.hpp +8 -0
  482. data/ext/sources/ggml/src/ggml-sycl/ssm_conv.cpp +6 -1
  483. data/ext/sources/ggml/src/ggml-sycl/ssm_scan.cpp +156 -0
  484. data/ext/sources/ggml/src/ggml-sycl/ssm_scan.hpp +5 -0
  485. data/ext/sources/ggml/src/ggml-sycl/sycl_hw.cpp +62 -10
  486. data/ext/sources/ggml/src/ggml-sycl/sycl_hw.hpp +18 -6
  487. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-tile-instance-dkq512-dv512.cpp +6 -0
  488. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-f16-f16.cpp +1 -0
  489. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-f16-q4_0.cpp +1 -0
  490. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-f16-q4_1.cpp +1 -0
  491. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-f16-q5_0.cpp +1 -0
  492. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-f16-q5_1.cpp +1 -0
  493. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-f16-q8_0.cpp +1 -0
  494. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_0-f16.cpp +1 -0
  495. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_0-q4_0.cpp +1 -0
  496. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_0-q4_1.cpp +1 -0
  497. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_0-q5_0.cpp +1 -0
  498. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_0-q5_1.cpp +1 -0
  499. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_0-q8_0.cpp +1 -0
  500. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_1-f16.cpp +1 -0
  501. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_1-q4_0.cpp +1 -0
  502. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_1-q4_1.cpp +1 -0
  503. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_1-q5_0.cpp +1 -0
  504. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_1-q5_1.cpp +1 -0
  505. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_1-q8_0.cpp +1 -0
  506. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_0-f16.cpp +1 -0
  507. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_0-q4_0.cpp +1 -0
  508. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_0-q4_1.cpp +1 -0
  509. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_0-q5_0.cpp +1 -0
  510. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_0-q5_1.cpp +1 -0
  511. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_0-q8_0.cpp +1 -0
  512. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_1-f16.cpp +1 -0
  513. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_1-q4_0.cpp +1 -0
  514. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_1-q4_1.cpp +1 -0
  515. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_1-q5_0.cpp +1 -0
  516. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_1-q5_1.cpp +1 -0
  517. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_1-q8_0.cpp +1 -0
  518. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q8_0-f16.cpp +1 -0
  519. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q8_0-q4_0.cpp +1 -0
  520. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q8_0-q4_1.cpp +1 -0
  521. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q8_0-q5_0.cpp +1 -0
  522. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q8_0-q5_1.cpp +1 -0
  523. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q8_0-q8_0.cpp +1 -0
  524. data/ext/sources/ggml/src/ggml-sycl/type.hpp +112 -0
  525. data/ext/sources/ggml/src/ggml-sycl/upscale.cpp +410 -0
  526. data/ext/sources/ggml/src/ggml-sycl/upscale.hpp +9 -0
  527. data/ext/sources/ggml/src/ggml-sycl/vecdotq.hpp +242 -45
  528. data/ext/sources/ggml/src/ggml-virtgpu/ggml-backend-buffer.cpp +4 -0
  529. data/ext/sources/ggml/src/ggml-virtgpu/ggml-backend-device.cpp +2 -0
  530. data/ext/sources/ggml/src/ggml-virtgpu/ggml-backend.cpp +2 -0
  531. data/ext/sources/ggml/src/ggml-virtgpu/virtgpu-shm.cpp +1 -0
  532. data/ext/sources/ggml/src/ggml-virtgpu/virtgpu.cpp +1 -0
  533. data/ext/sources/ggml/src/ggml-virtgpu/virtgpu.h +0 -2
  534. data/ext/sources/ggml/src/ggml-vulkan/CMakeLists.txt +16 -0
  535. data/ext/sources/ggml/src/ggml-vulkan/ggml-vulkan.cpp +2843 -700
  536. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/CMakeLists.txt +4 -0
  537. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/col2im_1d.comp +61 -0
  538. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/contig_copy.comp +6 -2
  539. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/conv2d_mm.comp +146 -13
  540. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/conv3d_mm.comp +431 -0
  541. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/copy.comp +3 -1
  542. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/copy_from_quant.comp +1 -1
  543. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/copy_to_quant.comp +25 -1
  544. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/dequant_funcs.glsl +88 -0
  545. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/dequant_funcs_cm2.glsl +643 -1
  546. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/dequant_nvfp4.comp +32 -0
  547. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/dequant_q1_0.comp +29 -0
  548. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/diag.comp +3 -4
  549. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/dot_product_funcs.glsl +27 -0
  550. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/feature-tests/coopmat2_decode_vector.comp +7 -0
  551. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/flash_attn.comp +198 -48
  552. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/flash_attn_base.glsl +60 -59
  553. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/flash_attn_cm1.comp +116 -113
  554. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/flash_attn_cm2.comp +122 -31
  555. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/flash_attn_dequant.glsl +131 -0
  556. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/flash_attn_mmq_funcs.glsl +203 -0
  557. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/fwht.comp +115 -0
  558. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/gated_delta_net.comp +125 -64
  559. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/generic_binary_head.glsl +0 -1
  560. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/generic_unary_head.glsl +21 -19
  561. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/get_rows_back.comp +25 -0
  562. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/glu_head.glsl +29 -1
  563. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/glu_main.glsl +17 -11
  564. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/im2col.comp +76 -54
  565. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/im2col_3d.comp +0 -1
  566. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/l2_norm.comp +4 -7
  567. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/log.comp +0 -1
  568. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec.comp +122 -27
  569. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_iface.glsl +6 -6
  570. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q2_k.comp +1 -1
  571. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q4_k.comp +1 -1
  572. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q5_k.comp +1 -1
  573. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vecq.comp +22 -24
  574. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vecq_funcs.glsl +88 -55
  575. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mm.comp +42 -40
  576. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mm_cm2.comp +49 -15
  577. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mm_funcs.glsl +222 -171
  578. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mmq_funcs.glsl +8 -8
  579. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mmq_shmem_types.glsl +24 -9
  580. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/multi_add.comp +0 -1
  581. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/norm.comp +10 -10
  582. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/repeat_back.comp +3 -3
  583. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/roll.comp +3 -3
  584. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/rope_funcs.glsl +5 -2
  585. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/rope_head.glsl +0 -1
  586. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/rope_params.glsl +3 -2
  587. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/snake.comp +49 -0
  588. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/ssm_conv.comp +11 -1
  589. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/tri.comp +3 -4
  590. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/types.glsl +79 -2
  591. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/unary.comp +168 -0
  592. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/vulkan-shaders-gen.cpp +282 -211
  593. data/ext/sources/ggml/src/ggml-webgpu/CMakeLists.txt +5 -2
  594. data/ext/sources/ggml/src/ggml-webgpu/ggml-webgpu-shader-lib.hpp +2209 -283
  595. data/ext/sources/ggml/src/ggml-webgpu/ggml-webgpu.cpp +2618 -1416
  596. data/ext/sources/ggml/src/ggml-webgpu/pre_wgsl.hpp +37 -7
  597. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/add_id.wgsl +64 -0
  598. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/binary.wgsl +8 -7
  599. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/common_decls.tmpl +90 -95
  600. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/concat.wgsl +19 -1
  601. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/conv2d.wgsl +165 -0
  602. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/{cpy.tmpl.wgsl → cpy.wgsl} +25 -50
  603. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/flash_attn.wgsl +107 -184
  604. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/flash_attn_quant_staging.tmpl +124 -0
  605. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/flash_attn_tile.wgsl +397 -0
  606. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/flash_attn_vec_blk.wgsl +101 -0
  607. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/flash_attn_vec_reduce.wgsl +84 -0
  608. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/flash_attn_vec_split.wgsl +619 -0
  609. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/gated_delta_net.wgsl +149 -0
  610. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/get_rows.wgsl +204 -78
  611. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/glu.wgsl +155 -0
  612. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/im2col.wgsl +101 -0
  613. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_decls.tmpl +805 -526
  614. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_id.wgsl +195 -0
  615. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_id_gather.wgsl +52 -0
  616. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_id_vec.wgsl +154 -0
  617. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_reg_tile.wgsl +8 -6
  618. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_subgroup_matrix.wgsl +5 -1
  619. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_vec.wgsl +90 -413
  620. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_vec_acc.tmpl +1553 -0
  621. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_vec_q_acc.tmpl +297 -0
  622. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/quant_inner_loops.tmpl +21 -0
  623. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/quantize_q8.wgsl +178 -0
  624. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/rms_norm_mul.wgsl +152 -0
  625. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/{rope.tmpl.wgsl → rope.wgsl} +71 -142
  626. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/row_norm.wgsl +153 -0
  627. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/scale.wgsl +6 -4
  628. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/set.wgsl +109 -0
  629. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/set_rows.wgsl +2 -3
  630. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/set_rows_quant.wgsl +224 -0
  631. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/{soft_max.tmpl.wgsl → soft_max.wgsl} +106 -206
  632. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/solve_tri.wgsl +121 -0
  633. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/ssm_conv.wgsl +65 -0
  634. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/ssm_scan.wgsl +193 -0
  635. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/unary.wgsl +68 -48
  636. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/upscale.wgsl +240 -0
  637. data/ext/sources/ggml/src/ggml-zdnn/ggml-zdnn.cpp +18 -14
  638. data/ext/sources/ggml/src/ggml-zendnn/CMakeLists.txt +1 -1
  639. data/ext/sources/ggml/src/ggml-zendnn/ggml-zendnn.cpp +244 -10
  640. data/ext/sources/ggml/src/ggml.c +146 -42
  641. data/ext/sources/ggml/src/gguf.cpp +173 -28
  642. data/ext/sources/include/parakeet.h +342 -0
  643. data/ext/sources/include/whisper.h +31 -0
  644. data/ext/sources/media/matmul.png +0 -0
  645. data/ext/sources/src/CMakeLists.txt +23 -0
  646. data/ext/sources/src/parakeet-arch.h +188 -0
  647. data/ext/sources/src/parakeet.cpp +3838 -0
  648. data/ext/sources/src/whisper.cpp +220 -26
  649. data/extsources.rb +26 -10
  650. data/lib/whisper/log_settable.rb +33 -0
  651. data/lib/whisper/model/uri.rb +13 -8
  652. data/lib/whisper/output.rb +74 -0
  653. data/sig/whisper.rbs +417 -62
  654. data/test/helper.rb +2 -0
  655. data/test/jfk_reader/jfk_reader.c +50 -7
  656. data/test/test_callback.rb +1 -0
  657. data/test/test_package.rb +6 -5
  658. data/test/test_parakeet.rb +28 -0
  659. data/test/test_parakeet_callback.rb +107 -0
  660. data/test/test_parakeet_context.rb +116 -0
  661. data/test/test_parakeet_context_params.rb +24 -0
  662. data/test/test_parakeet_model.rb +21 -0
  663. data/test/test_parakeet_params.rb +78 -0
  664. data/test/test_parakeet_segment.rb +42 -0
  665. data/test/test_parakeet_token.rb +73 -0
  666. data/test/test_params.rb +2 -0
  667. data/test/test_vad.rb +9 -0
  668. data/test/test_vad_context.rb +2 -2
  669. data/test/test_vad_segment.rb +1 -1
  670. data/test/test_whisper.rb +24 -6
  671. data/whispercpp.gemspec +2 -2
  672. metadata +263 -304
  673. data/ext/sources/bindings/javascript/CMakeLists.txt +0 -41
  674. data/ext/sources/bindings/javascript/emscripten.cpp +0 -93
  675. data/ext/sources/bindings/javascript/libwhisper.worker.js +0 -1
  676. data/ext/sources/bindings/javascript/package.json +0 -26
  677. data/ext/sources/bindings/javascript/whisper.js +0 -19
  678. data/ext/sources/examples/addon.node/CMakeLists.txt +0 -31
  679. data/ext/sources/examples/addon.node/__test__/whisper.spec.js +0 -133
  680. data/ext/sources/examples/addon.node/addon.cpp +0 -557
  681. data/ext/sources/examples/addon.node/index.js +0 -59
  682. data/ext/sources/examples/addon.node/package.json +0 -16
  683. data/ext/sources/examples/addon.node/vad-example.js +0 -132
  684. data/ext/sources/examples/bench.wasm/CMakeLists.txt +0 -49
  685. data/ext/sources/examples/bench.wasm/emscripten.cpp +0 -87
  686. data/ext/sources/examples/bench.wasm/index-tmpl.html +0 -285
  687. data/ext/sources/examples/coi-serviceworker.js +0 -146
  688. data/ext/sources/examples/command/CMakeLists.txt +0 -10
  689. data/ext/sources/examples/command/command.cpp +0 -802
  690. data/ext/sources/examples/command/commands.txt +0 -9
  691. data/ext/sources/examples/command.wasm/CMakeLists.txt +0 -50
  692. data/ext/sources/examples/command.wasm/emscripten.cpp +0 -327
  693. data/ext/sources/examples/command.wasm/index-tmpl.html +0 -415
  694. data/ext/sources/examples/generate-karaoke.sh +0 -57
  695. data/ext/sources/examples/helpers.js +0 -191
  696. data/ext/sources/examples/livestream.sh +0 -112
  697. data/ext/sources/examples/lsp/CMakeLists.txt +0 -10
  698. data/ext/sources/examples/lsp/lsp.cpp +0 -471
  699. data/ext/sources/examples/lsp/whisper.vim +0 -362
  700. data/ext/sources/examples/python/test_whisper_processor.py +0 -7
  701. data/ext/sources/examples/python/whisper_processor.py +0 -54
  702. data/ext/sources/examples/server/bench.js +0 -29
  703. data/ext/sources/examples/server.py +0 -120
  704. data/ext/sources/examples/stream/CMakeLists.txt +0 -10
  705. data/ext/sources/examples/stream/stream.cpp +0 -437
  706. data/ext/sources/examples/stream.wasm/CMakeLists.txt +0 -49
  707. data/ext/sources/examples/stream.wasm/emscripten.cpp +0 -216
  708. data/ext/sources/examples/stream.wasm/index-tmpl.html +0 -491
  709. data/ext/sources/examples/sycl/CMakeLists.txt +0 -9
  710. data/ext/sources/examples/sycl/build.sh +0 -22
  711. data/ext/sources/examples/sycl/ls-sycl-device.cpp +0 -11
  712. data/ext/sources/examples/sycl/run-whisper.sh +0 -17
  713. data/ext/sources/examples/talk-llama/CMakeLists.txt +0 -48
  714. data/ext/sources/examples/talk-llama/eleven-labs.py +0 -80
  715. data/ext/sources/examples/talk-llama/llama-adapter.cpp +0 -488
  716. data/ext/sources/examples/talk-llama/llama-adapter.h +0 -89
  717. data/ext/sources/examples/talk-llama/llama-arch.cpp +0 -2877
  718. data/ext/sources/examples/talk-llama/llama-arch.h +0 -628
  719. data/ext/sources/examples/talk-llama/llama-batch.cpp +0 -919
  720. data/ext/sources/examples/talk-llama/llama-batch.h +0 -173
  721. data/ext/sources/examples/talk-llama/llama-chat.cpp +0 -896
  722. data/ext/sources/examples/talk-llama/llama-chat.h +0 -71
  723. data/ext/sources/examples/talk-llama/llama-context.cpp +0 -3633
  724. data/ext/sources/examples/talk-llama/llama-context.h +0 -359
  725. data/ext/sources/examples/talk-llama/llama-cparams.cpp +0 -5
  726. data/ext/sources/examples/talk-llama/llama-cparams.h +0 -47
  727. data/ext/sources/examples/talk-llama/llama-ext.h +0 -12
  728. data/ext/sources/examples/talk-llama/llama-grammar.cpp +0 -1464
  729. data/ext/sources/examples/talk-llama/llama-grammar.h +0 -194
  730. data/ext/sources/examples/talk-llama/llama-graph.cpp +0 -2735
  731. data/ext/sources/examples/talk-llama/llama-graph.h +0 -1031
  732. data/ext/sources/examples/talk-llama/llama-hparams.cpp +0 -258
  733. data/ext/sources/examples/talk-llama/llama-hparams.h +0 -353
  734. data/ext/sources/examples/talk-llama/llama-impl.cpp +0 -171
  735. data/ext/sources/examples/talk-llama/llama-impl.h +0 -75
  736. data/ext/sources/examples/talk-llama/llama-io.cpp +0 -15
  737. data/ext/sources/examples/talk-llama/llama-io.h +0 -35
  738. data/ext/sources/examples/talk-llama/llama-kv-cache-iswa.cpp +0 -330
  739. data/ext/sources/examples/talk-llama/llama-kv-cache-iswa.h +0 -137
  740. data/ext/sources/examples/talk-llama/llama-kv-cache.cpp +0 -2285
  741. data/ext/sources/examples/talk-llama/llama-kv-cache.h +0 -389
  742. data/ext/sources/examples/talk-llama/llama-kv-cells.h +0 -533
  743. data/ext/sources/examples/talk-llama/llama-memory-hybrid-iswa.cpp +0 -275
  744. data/ext/sources/examples/talk-llama/llama-memory-hybrid-iswa.h +0 -140
  745. data/ext/sources/examples/talk-llama/llama-memory-hybrid.cpp +0 -268
  746. data/ext/sources/examples/talk-llama/llama-memory-hybrid.h +0 -139
  747. data/ext/sources/examples/talk-llama/llama-memory-recurrent.cpp +0 -1165
  748. data/ext/sources/examples/talk-llama/llama-memory-recurrent.h +0 -182
  749. data/ext/sources/examples/talk-llama/llama-memory.cpp +0 -59
  750. data/ext/sources/examples/talk-llama/llama-memory.h +0 -122
  751. data/ext/sources/examples/talk-llama/llama-mmap.cpp +0 -752
  752. data/ext/sources/examples/talk-llama/llama-mmap.h +0 -73
  753. data/ext/sources/examples/talk-llama/llama-model-loader.cpp +0 -1655
  754. data/ext/sources/examples/talk-llama/llama-model-loader.h +0 -206
  755. data/ext/sources/examples/talk-llama/llama-model-saver.cpp +0 -299
  756. data/ext/sources/examples/talk-llama/llama-model-saver.h +0 -40
  757. data/ext/sources/examples/talk-llama/llama-model.cpp +0 -9056
  758. data/ext/sources/examples/talk-llama/llama-model.h +0 -597
  759. data/ext/sources/examples/talk-llama/llama-quant.cpp +0 -1304
  760. data/ext/sources/examples/talk-llama/llama-quant.h +0 -1
  761. data/ext/sources/examples/talk-llama/llama-sampler.cpp +0 -3885
  762. data/ext/sources/examples/talk-llama/llama-sampler.h +0 -42
  763. data/ext/sources/examples/talk-llama/llama-vocab.cpp +0 -3970
  764. data/ext/sources/examples/talk-llama/llama-vocab.h +0 -187
  765. data/ext/sources/examples/talk-llama/llama.cpp +0 -1194
  766. data/ext/sources/examples/talk-llama/llama.h +0 -1573
  767. data/ext/sources/examples/talk-llama/models/afmoe.cpp +0 -190
  768. data/ext/sources/examples/talk-llama/models/apertus.cpp +0 -125
  769. data/ext/sources/examples/talk-llama/models/arcee.cpp +0 -135
  770. data/ext/sources/examples/talk-llama/models/arctic.cpp +0 -137
  771. data/ext/sources/examples/talk-llama/models/arwkv7.cpp +0 -86
  772. data/ext/sources/examples/talk-llama/models/baichuan.cpp +0 -123
  773. data/ext/sources/examples/talk-llama/models/bailingmoe.cpp +0 -143
  774. data/ext/sources/examples/talk-llama/models/bailingmoe2.cpp +0 -133
  775. data/ext/sources/examples/talk-llama/models/bert.cpp +0 -184
  776. data/ext/sources/examples/talk-llama/models/bitnet.cpp +0 -145
  777. data/ext/sources/examples/talk-llama/models/bloom.cpp +0 -101
  778. data/ext/sources/examples/talk-llama/models/chameleon.cpp +0 -178
  779. data/ext/sources/examples/talk-llama/models/chatglm.cpp +0 -132
  780. data/ext/sources/examples/talk-llama/models/codeshell.cpp +0 -111
  781. data/ext/sources/examples/talk-llama/models/cogvlm.cpp +0 -102
  782. data/ext/sources/examples/talk-llama/models/cohere2-iswa.cpp +0 -134
  783. data/ext/sources/examples/talk-llama/models/command-r.cpp +0 -122
  784. data/ext/sources/examples/talk-llama/models/dbrx.cpp +0 -122
  785. data/ext/sources/examples/talk-llama/models/deci.cpp +0 -135
  786. data/ext/sources/examples/talk-llama/models/deepseek.cpp +0 -142
  787. data/ext/sources/examples/talk-llama/models/deepseek2.cpp +0 -262
  788. data/ext/sources/examples/talk-llama/models/delta-net-base.cpp +0 -445
  789. data/ext/sources/examples/talk-llama/models/dots1.cpp +0 -132
  790. data/ext/sources/examples/talk-llama/models/dream.cpp +0 -105
  791. data/ext/sources/examples/talk-llama/models/ernie4-5-moe.cpp +0 -148
  792. data/ext/sources/examples/talk-llama/models/ernie4-5.cpp +0 -110
  793. data/ext/sources/examples/talk-llama/models/eurobert.cpp +0 -97
  794. data/ext/sources/examples/talk-llama/models/exaone-moe.cpp +0 -145
  795. data/ext/sources/examples/talk-llama/models/exaone.cpp +0 -114
  796. data/ext/sources/examples/talk-llama/models/exaone4.cpp +0 -123
  797. data/ext/sources/examples/talk-llama/models/falcon-h1.cpp +0 -111
  798. data/ext/sources/examples/talk-llama/models/falcon.cpp +0 -120
  799. data/ext/sources/examples/talk-llama/models/gemma-embedding.cpp +0 -116
  800. data/ext/sources/examples/talk-llama/models/gemma.cpp +0 -112
  801. data/ext/sources/examples/talk-llama/models/gemma2-iswa.cpp +0 -128
  802. data/ext/sources/examples/talk-llama/models/gemma3.cpp +0 -155
  803. data/ext/sources/examples/talk-llama/models/gemma3n-iswa.cpp +0 -384
  804. data/ext/sources/examples/talk-llama/models/glm4-moe.cpp +0 -170
  805. data/ext/sources/examples/talk-llama/models/glm4.cpp +0 -157
  806. data/ext/sources/examples/talk-llama/models/gpt2.cpp +0 -105
  807. data/ext/sources/examples/talk-llama/models/gptneox.cpp +0 -144
  808. data/ext/sources/examples/talk-llama/models/granite-hybrid.cpp +0 -195
  809. data/ext/sources/examples/talk-llama/models/granite.cpp +0 -210
  810. data/ext/sources/examples/talk-llama/models/grok.cpp +0 -159
  811. data/ext/sources/examples/talk-llama/models/grovemoe.cpp +0 -139
  812. data/ext/sources/examples/talk-llama/models/hunyuan-dense.cpp +0 -132
  813. data/ext/sources/examples/talk-llama/models/hunyuan-moe.cpp +0 -153
  814. data/ext/sources/examples/talk-llama/models/internlm2.cpp +0 -120
  815. data/ext/sources/examples/talk-llama/models/jais.cpp +0 -86
  816. data/ext/sources/examples/talk-llama/models/jais2.cpp +0 -123
  817. data/ext/sources/examples/talk-llama/models/jamba.cpp +0 -106
  818. data/ext/sources/examples/talk-llama/models/kimi-linear.cpp +0 -381
  819. data/ext/sources/examples/talk-llama/models/lfm2.cpp +0 -196
  820. data/ext/sources/examples/talk-llama/models/llada-moe.cpp +0 -122
  821. data/ext/sources/examples/talk-llama/models/llada.cpp +0 -99
  822. data/ext/sources/examples/talk-llama/models/llama-iswa.cpp +0 -178
  823. data/ext/sources/examples/talk-llama/models/llama.cpp +0 -175
  824. data/ext/sources/examples/talk-llama/models/maincoder.cpp +0 -117
  825. data/ext/sources/examples/talk-llama/models/mamba-base.cpp +0 -289
  826. data/ext/sources/examples/talk-llama/models/mamba.cpp +0 -54
  827. data/ext/sources/examples/talk-llama/models/mimo2-iswa.cpp +0 -129
  828. data/ext/sources/examples/talk-llama/models/minicpm3.cpp +0 -200
  829. data/ext/sources/examples/talk-llama/models/minimax-m2.cpp +0 -123
  830. data/ext/sources/examples/talk-llama/models/mistral3.cpp +0 -160
  831. data/ext/sources/examples/talk-llama/models/models.h +0 -704
  832. data/ext/sources/examples/talk-llama/models/modern-bert.cpp +0 -109
  833. data/ext/sources/examples/talk-llama/models/mpt.cpp +0 -126
  834. data/ext/sources/examples/talk-llama/models/nemotron-h.cpp +0 -162
  835. data/ext/sources/examples/talk-llama/models/nemotron.cpp +0 -122
  836. data/ext/sources/examples/talk-llama/models/neo-bert.cpp +0 -104
  837. data/ext/sources/examples/talk-llama/models/olmo.cpp +0 -121
  838. data/ext/sources/examples/talk-llama/models/olmo2.cpp +0 -150
  839. data/ext/sources/examples/talk-llama/models/olmoe.cpp +0 -124
  840. data/ext/sources/examples/talk-llama/models/openai-moe-iswa.cpp +0 -127
  841. data/ext/sources/examples/talk-llama/models/openelm.cpp +0 -124
  842. data/ext/sources/examples/talk-llama/models/orion.cpp +0 -123
  843. data/ext/sources/examples/talk-llama/models/paddleocr.cpp +0 -122
  844. data/ext/sources/examples/talk-llama/models/pangu-embedded.cpp +0 -121
  845. data/ext/sources/examples/talk-llama/models/phi2.cpp +0 -121
  846. data/ext/sources/examples/talk-llama/models/phi3.cpp +0 -152
  847. data/ext/sources/examples/talk-llama/models/plamo.cpp +0 -110
  848. data/ext/sources/examples/talk-llama/models/plamo2.cpp +0 -320
  849. data/ext/sources/examples/talk-llama/models/plamo3.cpp +0 -128
  850. data/ext/sources/examples/talk-llama/models/plm.cpp +0 -169
  851. data/ext/sources/examples/talk-llama/models/qwen.cpp +0 -108
  852. data/ext/sources/examples/talk-llama/models/qwen2.cpp +0 -126
  853. data/ext/sources/examples/talk-llama/models/qwen2moe.cpp +0 -151
  854. data/ext/sources/examples/talk-llama/models/qwen2vl.cpp +0 -117
  855. data/ext/sources/examples/talk-llama/models/qwen3.cpp +0 -120
  856. data/ext/sources/examples/talk-llama/models/qwen35.cpp +0 -381
  857. data/ext/sources/examples/talk-llama/models/qwen35moe.cpp +0 -422
  858. data/ext/sources/examples/talk-llama/models/qwen3moe.cpp +0 -131
  859. data/ext/sources/examples/talk-llama/models/qwen3next.cpp +0 -525
  860. data/ext/sources/examples/talk-llama/models/qwen3vl-moe.cpp +0 -140
  861. data/ext/sources/examples/talk-llama/models/qwen3vl.cpp +0 -132
  862. data/ext/sources/examples/talk-llama/models/refact.cpp +0 -94
  863. data/ext/sources/examples/talk-llama/models/rnd1.cpp +0 -126
  864. data/ext/sources/examples/talk-llama/models/rwkv6-base.cpp +0 -164
  865. data/ext/sources/examples/talk-llama/models/rwkv6.cpp +0 -94
  866. data/ext/sources/examples/talk-llama/models/rwkv6qwen2.cpp +0 -86
  867. data/ext/sources/examples/talk-llama/models/rwkv7-base.cpp +0 -137
  868. data/ext/sources/examples/talk-llama/models/rwkv7.cpp +0 -90
  869. data/ext/sources/examples/talk-llama/models/seed-oss.cpp +0 -124
  870. data/ext/sources/examples/talk-llama/models/smallthinker.cpp +0 -126
  871. data/ext/sources/examples/talk-llama/models/smollm3.cpp +0 -128
  872. data/ext/sources/examples/talk-llama/models/stablelm.cpp +0 -146
  873. data/ext/sources/examples/talk-llama/models/starcoder.cpp +0 -100
  874. data/ext/sources/examples/talk-llama/models/starcoder2.cpp +0 -121
  875. data/ext/sources/examples/talk-llama/models/step35-iswa.cpp +0 -165
  876. data/ext/sources/examples/talk-llama/models/t5-dec.cpp +0 -166
  877. data/ext/sources/examples/talk-llama/models/t5-enc.cpp +0 -96
  878. data/ext/sources/examples/talk-llama/models/wavtokenizer-dec.cpp +0 -149
  879. data/ext/sources/examples/talk-llama/models/xverse.cpp +0 -108
  880. data/ext/sources/examples/talk-llama/prompts/talk-alpaca.txt +0 -23
  881. data/ext/sources/examples/talk-llama/speak +0 -40
  882. data/ext/sources/examples/talk-llama/speak.bat +0 -1
  883. data/ext/sources/examples/talk-llama/speak.ps1 +0 -14
  884. data/ext/sources/examples/talk-llama/talk-llama.cpp +0 -813
  885. data/ext/sources/examples/talk-llama/unicode-data.cpp +0 -7034
  886. data/ext/sources/examples/talk-llama/unicode-data.h +0 -20
  887. data/ext/sources/examples/talk-llama/unicode.cpp +0 -1103
  888. data/ext/sources/examples/talk-llama/unicode.h +0 -111
  889. data/ext/sources/examples/wchess/CMakeLists.txt +0 -10
  890. data/ext/sources/examples/wchess/libwchess/CMakeLists.txt +0 -19
  891. data/ext/sources/examples/wchess/libwchess/Chessboard.cpp +0 -803
  892. data/ext/sources/examples/wchess/libwchess/Chessboard.h +0 -33
  893. data/ext/sources/examples/wchess/libwchess/WChess.cpp +0 -193
  894. data/ext/sources/examples/wchess/libwchess/WChess.h +0 -63
  895. data/ext/sources/examples/wchess/libwchess/test-chessboard.cpp +0 -117
  896. data/ext/sources/examples/wchess/wchess.cmd/CMakeLists.txt +0 -8
  897. data/ext/sources/examples/wchess/wchess.cmd/wchess.cmd.cpp +0 -253
  898. data/ext/sources/examples/whisper.wasm/CMakeLists.txt +0 -50
  899. data/ext/sources/examples/whisper.wasm/emscripten.cpp +0 -118
  900. data/ext/sources/examples/whisper.wasm/index-tmpl.html +0 -659
  901. data/ext/sources/ggml/src/ggml-cuda/template-instances/generate_cu_files.py +0 -99
  902. data/ext/sources/ggml/src/ggml-hexagon/htp/htp-msg.h +0 -155
  903. data/ext/sources/ggml/src/ggml-hexagon/op-desc.h +0 -153
  904. data/ext/sources/ggml/src/ggml-opencl/kernels/embed_kernel.py +0 -26
  905. data/ext/sources/ggml/src/ggml-openvino/openvino/pass/eliminate_zp.cpp +0 -123
  906. data/ext/sources/ggml/src/ggml-openvino/openvino/pass/eliminate_zp.h +0 -17
  907. data/ext/sources/ggml/src/ggml-virtgpu/regenerate_remoting.py +0 -333
  908. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/abs.comp +0 -21
  909. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/ceil.comp +0 -22
  910. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/clamp.comp +0 -17
  911. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/cos.comp +0 -17
  912. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/elu.comp +0 -27
  913. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/exp.comp +0 -21
  914. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/floor.comp +0 -22
  915. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/gelu.comp +0 -25
  916. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/gelu_erf.comp +0 -39
  917. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/gelu_quick.comp +0 -23
  918. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/hardsigmoid.comp +0 -22
  919. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/hardswish.comp +0 -22
  920. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/leaky_relu.comp +0 -22
  921. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/neg.comp +0 -20
  922. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/relu.comp +0 -21
  923. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/round.comp +0 -29
  924. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/rte.glsl +0 -5
  925. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/sgn.comp +0 -21
  926. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/sigmoid.comp +0 -20
  927. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/silu.comp +0 -22
  928. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/sin.comp +0 -17
  929. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/softplus.comp +0 -23
  930. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/sqrt.comp +0 -17
  931. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/square.comp +0 -17
  932. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/step.comp +0 -22
  933. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/tanh.comp +0 -20
  934. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/trunc.comp +0 -22
  935. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/xielu.comp +0 -35
  936. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/embed_wgsl.py +0 -182
  937. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/glu.tmpl.wgsl +0 -323
  938. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat.wgsl +0 -718
  939. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/rms_norm.wgsl +0 -123
  940. data/ext/sources/tests/CMakeLists.txt +0 -112
  941. data/ext/sources/tests/earnings21/eval.mk +0 -58
  942. data/ext/sources/tests/earnings21/eval.py +0 -68
  943. data/ext/sources/tests/earnings21/normalizers/__init__.py +0 -2
  944. data/ext/sources/tests/earnings21/normalizers/basic.py +0 -80
  945. data/ext/sources/tests/earnings21/normalizers/english.json +0 -1741
  946. data/ext/sources/tests/earnings21/normalizers/english.py +0 -550
  947. data/ext/sources/tests/earnings21/requirements.txt +0 -6
  948. data/ext/sources/tests/en-0-ref.txt +0 -1
  949. data/ext/sources/tests/en-1-ref.txt +0 -1
  950. data/ext/sources/tests/en-2-ref.txt +0 -1
  951. data/ext/sources/tests/es-0-ref.txt +0 -1
  952. data/ext/sources/tests/librispeech/eval.mk +0 -39
  953. data/ext/sources/tests/librispeech/eval.py +0 -47
  954. data/ext/sources/tests/librispeech/normalizers/__init__.py +0 -2
  955. data/ext/sources/tests/librispeech/normalizers/basic.py +0 -80
  956. data/ext/sources/tests/librispeech/normalizers/english.json +0 -1741
  957. data/ext/sources/tests/librispeech/normalizers/english.py +0 -550
  958. data/ext/sources/tests/librispeech/requirements.txt +0 -6
  959. data/ext/sources/tests/run-tests.sh +0 -130
  960. data/ext/sources/tests/test-c.c +0 -3
  961. data/ext/sources/tests/test-vad-full.cpp +0 -56
  962. data/ext/sources/tests/test-vad.cpp +0 -83
  963. data/ext/sources/tests/test-whisper.js +0 -58
  964. data/lib/whisper/context.rb +0 -15
  965. data/lib/whisper/segment.rb +0 -58
@@ -3,217 +3,41 @@
3
3
  #pragma clang diagnostic ignored "-Wunused-but-set-variable"
4
4
 
5
5
  #include <assert.h>
6
+ #include <HAP_compute_res.h>
6
7
  #include <HAP_farf.h>
7
8
  #include <HAP_perf.h>
8
9
  #include <math.h>
10
+ #include <stdbool.h>
11
+ #include <stdatomic.h>
12
+ #include <stddef.h>
13
+ #include <stdint.h>
9
14
  #include <string.h>
10
15
 
11
16
  #include "hex-dma.h"
17
+ #include "hex-fastdiv.h"
18
+ #include "hex-profile.h"
19
+ #include "hmx-queue.h"
20
+ #include "hmx-utils.h"
12
21
  #include "hvx-utils.h"
13
22
  #include "hvx-dump.h"
23
+ #include "hvx-copy.h"
24
+ #include "hvx-reduce.h"
25
+ #include "hvx-flash-attn.h"
26
+ #include "htp-vtcm.h"
27
+ #include "worker-pool.h"
14
28
 
15
29
  #define GGML_COMMON_DECL_C
16
30
  #include "ggml-common.h"
17
31
  #include "htp-ctx.h"
18
- #include "htp-msg.h"
19
32
  #include "htp-ops.h"
20
33
 
34
+ #include "flash-attn-ops.h"
35
+ #include "hvx-fa-kernels.h"
36
+ #include "hmx-fa-kernels.h"
37
+
21
38
  // Must be multiple of 32
22
39
  #define FLASH_ATTN_BLOCK_SIZE (32 * 2)
23
40
 
24
- // This is a bit of a hack because the compiler is strugling to properly inline
25
- // the default hvx_vec_f32_to_f16 with output into the local array.
26
- static void __attribute__((noinline)) hvx_vec_f32_to_f16_a(void *ptr, HVX_Vector v0, HVX_Vector v1)
27
- {
28
- *(HVX_Vector *) ptr = hvx_vec_f32_to_f16(v0, v1);
29
- }
30
-
31
- // Dot product of two F16 vectors, accumulating to float
32
- static inline void hvx_dot_f16_f16_aa(float * restrict r, const void * restrict x, const void * restrict y, unsigned int n, float s) {
33
- const HVX_Vector * restrict vx = (const HVX_Vector * restrict) x; // fp16
34
- const HVX_Vector * restrict vy = (const HVX_Vector * restrict) y; // fp16
35
-
36
- uint32_t nvec = n / VLEN_FP16; // num full fp16 hvx vectors
37
- uint32_t nloe = n % VLEN_FP16; // leftover elements
38
-
39
- HVX_VectorPair rsum_p = Q6_W_vcombine_VV(Q6_V_vsplat_R(0), Q6_V_vsplat_R(0));
40
-
41
- uint32_t i = 0;
42
-
43
- #pragma unroll(4)
44
- for (i = 0; i < nvec; i++) {
45
- rsum_p = hvx_vec_mpyacc_f32_f16(rsum_p, vx[i], vy[i]);
46
- }
47
-
48
- if (nloe) {
49
- HVX_VectorPred bmask = Q6_Q_vsetq_R(nloe * 2);
50
- HVX_Vector y_hf = Q6_V_vand_QV(bmask, vy[i]);
51
- HVX_Vector x_hf = Q6_V_vand_QV(bmask, vx[i]);
52
-
53
- rsum_p = hvx_vec_mpyacc_f32_f16(rsum_p, x_hf, y_hf);
54
- }
55
-
56
- HVX_Vector rsum = Q6_Vsf_equals_Vqf32(Q6_Vqf32_vadd_VsfVsf(Q6_V_lo_W(rsum_p), Q6_V_hi_W(rsum_p)));
57
- rsum = Q6_Vsf_equals_Vqf32(Q6_Vqf32_vmpy_VsfVsf(hvx_vec_splat_f32(s), hvx_vec_reduce_sum_f32(rsum)));
58
- hvx_vec_store_u(r, 4, rsum);
59
- }
60
-
61
- static inline HVX_Vector hvx_dot_f16_f16_aa_rx4(const void * restrict y,
62
- const uint8_t * restrict x,
63
- const size_t stride_x,
64
- const size_t nvec,
65
- const size_t nloe) {
66
- const HVX_Vector * restrict vx0 = (const HVX_Vector * restrict) x; // fp16
67
- const HVX_Vector * restrict vx1 = (const HVX_Vector * restrict) (x + stride_x); // fp16
68
- const HVX_Vector * restrict vx2 = (const HVX_Vector * restrict) (x + stride_x * 2); // fp16
69
- const HVX_Vector * restrict vx3 = (const HVX_Vector * restrict) (x + stride_x * 3); // fp16
70
- const HVX_Vector * restrict vy = (const HVX_Vector * restrict) y; // fp16
71
-
72
- HVX_VectorPair rsum0_p = Q6_W_vcombine_VV(Q6_V_vsplat_R(0), Q6_V_vsplat_R(0));
73
- HVX_VectorPair rsum1_p = Q6_W_vcombine_VV(Q6_V_vsplat_R(0), Q6_V_vsplat_R(0));
74
- HVX_VectorPair rsum2_p = Q6_W_vcombine_VV(Q6_V_vsplat_R(0), Q6_V_vsplat_R(0));
75
- HVX_VectorPair rsum3_p = Q6_W_vcombine_VV(Q6_V_vsplat_R(0), Q6_V_vsplat_R(0));
76
-
77
- uint32_t i = 0;
78
-
79
- for (i = 0; i < nvec; i++) {
80
- HVX_Vector y_hf = vy[i];
81
- HVX_Vector x0_hf = vx0[i];
82
- HVX_Vector x1_hf = vx1[i];
83
- HVX_Vector x2_hf = vx2[i];
84
- HVX_Vector x3_hf = vx3[i];
85
-
86
- rsum0_p = hvx_vec_mpyacc_f32_f16(rsum0_p, x0_hf, y_hf);
87
- rsum1_p = hvx_vec_mpyacc_f32_f16(rsum1_p, x1_hf, y_hf);
88
- rsum2_p = hvx_vec_mpyacc_f32_f16(rsum2_p, x2_hf, y_hf);
89
- rsum3_p = hvx_vec_mpyacc_f32_f16(rsum3_p, x3_hf, y_hf);
90
- }
91
-
92
- if (nloe) {
93
- // Load x (fp16) and zero-out unused elements
94
- HVX_VectorPred bmask = Q6_Q_vsetq_R(nloe * 2);
95
- HVX_Vector y_hf = Q6_V_vand_QV(bmask, vy[i]);
96
- HVX_Vector x0_hf = Q6_V_vand_QV(bmask, vx0[i]);
97
- HVX_Vector x1_hf = Q6_V_vand_QV(bmask, vx1[i]);
98
- HVX_Vector x2_hf = Q6_V_vand_QV(bmask, vx2[i]);
99
- HVX_Vector x3_hf = Q6_V_vand_QV(bmask, vx3[i]);
100
-
101
- rsum0_p = hvx_vec_mpyacc_f32_f16(rsum0_p, x0_hf, y_hf);
102
- rsum1_p = hvx_vec_mpyacc_f32_f16(rsum1_p, x1_hf, y_hf);
103
- rsum2_p = hvx_vec_mpyacc_f32_f16(rsum2_p, x2_hf, y_hf);
104
- rsum3_p = hvx_vec_mpyacc_f32_f16(rsum3_p, x3_hf, y_hf);
105
- }
106
-
107
- HVX_Vector rsum0 = Q6_Vsf_equals_Vqf32(Q6_Vqf32_vadd_VsfVsf(Q6_V_lo_W(rsum0_p), Q6_V_hi_W(rsum0_p)));
108
- HVX_Vector rsum1 = Q6_Vsf_equals_Vqf32(Q6_Vqf32_vadd_VsfVsf(Q6_V_lo_W(rsum1_p), Q6_V_hi_W(rsum1_p)));
109
- HVX_Vector rsum2 = Q6_Vsf_equals_Vqf32(Q6_Vqf32_vadd_VsfVsf(Q6_V_lo_W(rsum2_p), Q6_V_hi_W(rsum2_p)));
110
- HVX_Vector rsum3 = Q6_Vsf_equals_Vqf32(Q6_Vqf32_vadd_VsfVsf(Q6_V_lo_W(rsum3_p), Q6_V_hi_W(rsum3_p)));
111
-
112
- HVX_Vector_x4 rsum0123 = { .v = { rsum0, rsum1, rsum2, rsum3 } };
113
- return hvx_vec_reduce_sum_f32x4(rsum0123);
114
- }
115
-
116
- static inline HVX_Vector hvx_dot_f16_f16_aa_rx32(const void * restrict y,
117
- const uint8_t * restrict x,
118
- const size_t stride_x,
119
- const size_t n,
120
- float s) {
121
-
122
- const size_t nvec = n / VLEN_FP16; // num full fp16 hvx vectors
123
- const size_t nloe = n % VLEN_FP16; // leftover elements
124
-
125
- HVX_Vector sums; // initialize at j = 0
126
- const size_t stride_x_4 = stride_x * 4;
127
- for (uint32_t j = 0; j < VLEN_FP32; j += 4) {
128
- HVX_Vector sums_x4 = hvx_dot_f16_f16_aa_rx4(y, x, stride_x, nvec, nloe);
129
- HVX_VectorPred pred = Q6_Q_vsetq_R(j * SIZEOF_FP32);
130
- sums = Q6_V_vmux_QVV(pred, sums, sums_x4);
131
- x += stride_x_4;
132
- }
133
-
134
- sums = Q6_Vqf32_vmpy_VsfVsf(hvx_vec_splat_f32(s), sums);
135
- return Q6_Vsf_equals_Vqf32(sums);
136
- }
137
-
138
- // MAD: y (F32) += x (F16) * s (F16)
139
- static inline void hvx_mad_f32_f16_aa(float * restrict y, const void * restrict x, const __fp16 * restrict s, int n) {
140
- const HVX_Vector * restrict vx0 = (const HVX_Vector *) x;
141
-
142
- HVX_VectorPair * restrict vy_p = (HVX_VectorPair *) y;
143
- HVX_Vector * restrict vy = (HVX_Vector *) y;
144
-
145
- uint32_t nvec = n / VLEN_FP16; // num full fp16 hvx vectors
146
- uint32_t nloe = n % VLEN_FP16; // leftover elements
147
-
148
- HVX_Vector S0 = hvx_vec_splat_f16(*s);
149
-
150
- uint32_t i = 0;
151
-
152
- #pragma unroll(2)
153
- for (i = 0; i < nvec; ++i) {
154
- vy_p[i] = hvx_vec_mpyacc_f32_f16(vy_p[i], Q6_Vh_vshuff_Vh(vx0[i]), S0);
155
- }
156
-
157
- if (nloe) {
158
- HVX_VectorPair xy_p = vy_p[i];
159
- xy_p = hvx_vec_mpyacc_f32_f16(xy_p, Q6_Vh_vshuff_Vh(vx0[i]), S0);
160
-
161
- HVX_Vector xy = Q6_V_lo_W(xy_p);
162
- i = 2 * i; // index for vy
163
-
164
- if (nloe >= VLEN_FP32) {
165
- vy[i] = xy;
166
- nloe -= VLEN_FP32; ++i; xy = Q6_V_hi_W(xy_p);
167
- }
168
-
169
- if (nloe) {
170
- hvx_vec_store_a(&vy[i], nloe * 4, xy);
171
- }
172
- }
173
- }
174
-
175
- // MAD: y (F32) += x0 (F16) * s0 (F16) + x1 (F16) * s1 (F16)
176
- static inline void hvx_mad_f32_f16_aa_rx2(float * restrict y, const void * restrict x0, const void * restrict x1,
177
- const __fp16 * restrict s0, const __fp16 * restrict s1, int n) {
178
- const HVX_Vector * restrict vx0 = (const HVX_Vector *) x0;
179
- const HVX_Vector * restrict vx1 = (const HVX_Vector *) x1;
180
-
181
- HVX_VectorPair * restrict vy_p = (HVX_VectorPair *) y;
182
- HVX_Vector * restrict vy = (HVX_Vector *) y;
183
-
184
- uint32_t nvec = n / VLEN_FP16; // num full fp16 hvx vectors
185
- uint32_t nloe = n % VLEN_FP16; // leftover elements
186
-
187
- HVX_Vector S0 = hvx_vec_splat_f16(*s0);
188
- HVX_Vector S1 = hvx_vec_splat_f16(*s1);
189
-
190
- uint32_t i = 0;
191
-
192
- #pragma unroll(2)
193
- for (i = 0; i < nvec; ++i) {
194
- vy_p[i] = hvx_vec_mpyacc_f32_f16(vy_p[i], Q6_Vh_vshuff_Vh(vx0[i]), S0);
195
- vy_p[i] = hvx_vec_mpyacc_f32_f16(vy_p[i], Q6_Vh_vshuff_Vh(vx1[i]), S1);
196
- }
197
-
198
- if (nloe) {
199
- HVX_VectorPair xy_p = vy_p[i];
200
- xy_p = hvx_vec_mpyacc_f32_f16(xy_p, Q6_Vh_vshuff_Vh(vx0[i]), S0);
201
- xy_p = hvx_vec_mpyacc_f32_f16(xy_p, Q6_Vh_vshuff_Vh(vx1[i]), S1);
202
-
203
- HVX_Vector xy = Q6_V_lo_W(xy_p);
204
- i = 2 * i; // index for vy
205
-
206
- if (nloe >= VLEN_FP32) {
207
- vy[i] = xy;
208
- nloe -= VLEN_FP32; ++i; xy = Q6_V_hi_W(xy_p);
209
- }
210
-
211
- if (nloe) {
212
- hvx_vec_store_a(&vy[i], nloe * 4, xy);
213
- }
214
- }
215
- }
216
-
217
41
  struct htp_fa_context {
218
42
  const struct htp_ops_context * octx;
219
43
 
@@ -230,11 +54,12 @@ struct htp_fa_context {
230
54
 
231
55
  float scale;
232
56
  float max_bias;
233
- float logit_softcap;
57
+ __fp16 logit_softcap;
234
58
 
235
59
  uint32_t n_head_log2;
236
60
  float m0;
237
61
  float m1;
62
+ __fp16 slopes[512];
238
63
 
239
64
  uint32_t n_blocks;
240
65
 
@@ -251,39 +76,90 @@ struct htp_fa_context {
251
76
 
252
77
  bool is_q_fp32;
253
78
 
254
- uint64_t t_start;
255
- };
256
-
257
- static inline void hvx_scale_vec_f32_aa(uint8_t * restrict dst, const uint8_t * restrict src, const int n, HVX_Vector vs) {
258
- assert((size_t) dst % 128 == 0);
259
- assert((size_t) src % 128 == 0);
79
+ size_t size_q_block;
80
+ size_t size_vkq_acc;
260
81
 
261
- const HVX_Vector * restrict vsrc = (const HVX_Vector * restrict) src;
262
- HVX_Vector * restrict vdst = (HVX_Vector * restrict) dst;
82
+ uint8_t * spad_q;
83
+ uint8_t * spad_k;
84
+ uint8_t * spad_v;
85
+ uint8_t * spad_m;
86
+ uint8_t * spad_a;
263
87
 
264
- const uint32_t nvec = n / VLEN_FP32;
265
- const uint32_t nloe = n % VLEN_FP32;
88
+ uint64_t t_start;
89
+ };
266
90
 
267
- uint32_t i = 0;
268
- #pragma unroll(4)
269
- for (; i < nvec; ++i) {
270
- vdst[i] = Q6_Vsf_equals_Vqf32(Q6_Vqf32_vmpy_VsfVsf(vsrc[i], vs));
271
- }
272
- if (nloe) {
273
- HVX_Vector v = Q6_Vqf32_vmpy_VsfVsf(vsrc[i], vs);
274
- hvx_vec_store_a(&vdst[i], nloe * sizeof(float), Q6_Vsf_equals_Vqf32(v));
275
- }
276
- }
91
+ struct hmx_fa_context {
92
+ const struct htp_ops_context * octx;
93
+ const struct htp_tensor * sinks; // attention sinks (src[4]), NULL if absent
94
+ bool pipeline; // true when n_kv_blocks >= FA_MIN_KV_BLOCKS && n_threads >= 2
95
+ uint32_t n_threads;
96
+
97
+ // Op parameters
98
+ __fp16 scale;
99
+ float max_bias;
100
+ __fp16 logit_softcap;
101
+ uint32_t n_head_log2;
102
+ float m0, m1;
103
+
104
+ // Dimensions
105
+ uint32_t DK, DV;
106
+ uint32_t n_kv; // kv_len
107
+ uint32_t n_kv_heads; // number of KV heads
108
+ uint32_t n_heads; // number of Q heads
109
+ uint32_t G; // GQA factor = n_heads / n_kv_heads
110
+ struct fastdiv_values div_G;
111
+ struct fastdiv_values src3_div2;
112
+ struct fastdiv_values src3_div3;
113
+ uint32_t n_kv_blocks;
114
+ uint32_t neq1; // Q token count
115
+
116
+ // Types
117
+ bool is_q_fp32;
118
+ bool is_dst_fp32;
119
+
120
+ // Dynamic block sizes
121
+ uint32_t Br; // Q tokens per block (before GQA expansion)
122
+ uint32_t Bc;
123
+ uint32_t g_br; // hex_align_up(G * Br, 32) - actual tile row dim
124
+
125
+ // VTCM buffers (allocated by vtcm_seq_alloc)
126
+ __fp16 * vtcm_q_tiles; // Q tile format [g_br, D]
127
+ __fp16 * vtcm_o_tiles[2]; // O ping-pong [g_br, D]
128
+ __fp16 * vtcm_k_fp16[2]; // K DMA double-buffer [Bc, D]
129
+ __fp16 * vtcm_v_fp16[2]; // V DMA double-buffer [Bc, D]
130
+ __fp16 * vtcm_k_tiles; // K tiles (transposed)
131
+ __fp16 * vtcm_v_tiles[2]; // V tiles (column-major, double-buffered)
132
+ __fp16 * vtcm_s_tiles; // S = QK^T [g_br, Bc]
133
+ __fp16 * vtcm_p_tiles; // P = softmax(S) [g_br, Bc]
134
+ __fp16 * vtcm_d_tiles; // Diagonal rescale [g_br, g_br]
135
+ HVX_Vector * vtcm_m_vec; // Row max [g_br]
136
+ HVX_Vector * vtcm_l_vec; // Row sum [g_br]
137
+ HVX_Vector * vtcm_s_rowmax; // Softmax intermediate [g_br]
138
+ HVX_Vector * vtcm_p_rowsum; // Softmax intermediate [g_br]
139
+ HVX_Vector * vtcm_row_bufs; // Per-thread softmax row scratch [n_threads][2][Bc/64]
140
+ uint8_t * vtcm_hmx_scales_id; // HMX output scales (identity)
141
+ uint8_t * vtcm_hmx_scales_qk; // HMX output scales (qk_scale)
142
+ __fp16 * vtcm_mask_buf; // VTCM mask buffer [Br * m_line], DMA'd per KV block
143
+ __fp16 * vtcm_slopes; // ALiBi slopes [g_br]
144
+ size_t row_buf_stride; // HVX vectors per row buffer (Bc/64)
145
+ size_t mask_buf_row_stride; // elements (__fp16) per row in mask buffer
146
+ size_t q_tile_bytes;
147
+ size_t o_tile_bytes;
148
+ size_t col_vec_bytes;
149
+ size_t d_tile_bytes;
150
+ bool mask_broadcast; // true when mask->ne[2] == 1 (head-independent, single 2D DMA)
151
+ dma_cache m_cache;
152
+ };
277
153
 
278
154
  static void flash_attn_ext_f16_thread(unsigned int nth, unsigned int ith, void * data) {
279
155
  struct htp_fa_context * factx = (struct htp_fa_context *) data;
280
156
  const struct htp_ops_context * octx = factx->octx;
281
- const struct htp_tensor * q = &octx->src0;
282
- const struct htp_tensor * k = &octx->src1;
283
- const struct htp_tensor * v = &octx->src2;
284
- const struct htp_tensor * mask = (octx->src3.data) ? &octx->src3 : NULL;
285
- const struct htp_tensor * sinks = (octx->src4.data) ? &octx->src4 : NULL;
286
- const struct htp_tensor * dst = &octx->dst;
157
+ const struct htp_tensor * q = octx->src[0];
158
+ const struct htp_tensor * k = octx->src[1];
159
+ const struct htp_tensor * v = octx->src[2];
160
+ const struct htp_tensor * mask = octx->src[3];
161
+ const struct htp_tensor * sinks = octx->src[4];
162
+ const struct htp_tensor * dst = octx->dst;
287
163
 
288
164
  const uint32_t neq0 = q->ne[0];
289
165
  const uint32_t neq1 = q->ne[1];
@@ -328,6 +204,8 @@ static void flash_attn_ext_f16_thread(unsigned int nth, unsigned int ith, void *
328
204
 
329
205
  if (ir0 >= ir1) return;
330
206
 
207
+ struct htp_thread_trace * tr = octx->ctx ? &octx->ctx->trace[ith] : NULL;
208
+
331
209
  dma_queue * dma = octx->ctx->dma[ith];
332
210
 
333
211
  const uint32_t DK = nek0;
@@ -338,13 +216,14 @@ static void flash_attn_ext_f16_thread(unsigned int nth, unsigned int ith, void *
338
216
  const size_t size_v_row = DV * sizeof(__fp16);
339
217
 
340
218
  // Scratchpad buffers for Q, K, V, Mask, and VKQ32 accumulator
341
- uint8_t * spad_q = octx->src0_spad.data + octx->src0_spad.size_per_thread * ith;
342
- uint8_t * spad_k = octx->src1_spad.data + octx->src1_spad.size_per_thread * ith;
343
- uint8_t * spad_v = octx->src2_spad.data + octx->src2_spad.size_per_thread * ith;
344
- uint8_t * spad_m = octx->src3_spad.data + octx->src3_spad.size_per_thread * ith;
345
- uint8_t * spad_a = octx->dst_spad.data + octx->dst_spad.size_per_thread * ith;
219
+ uint8_t * spad_q = factx->spad_q + factx->size_q_block * ith;
220
+ uint8_t * spad_k = factx->spad_k + factx->size_k_block * 2 * ith;
221
+ uint8_t * spad_v = factx->spad_v + factx->size_v_block * 2 * ith;
222
+ uint8_t * spad_m = factx->spad_m + (mask ? factx->size_m_block * HVX_FA_DMA_CACHE_SIZE : 0) * ith;
223
+ uint8_t * spad_a = factx->spad_a + factx->size_vkq_acc * ith;
346
224
 
347
- const HVX_Vector logit_cap = hvx_vec_splat_f32(factx->logit_softcap);
225
+ dma_cache m_cache;
226
+ dma_cache_init(&m_cache, spad_m, factx->size_m_block, HVX_FA_DMA_CACHE_SIZE);
348
227
 
349
228
  for (uint32_t ir = ir0; ir < ir1; ++ir) {
350
229
  const uint32_t iq3 = fastdiv(ir, &factx->src0_div21);
@@ -361,9 +240,6 @@ static void flash_attn_ext_f16_thread(unsigned int nth, unsigned int ith, void *
361
240
  const uint8_t * q_row_ptr = (const uint8_t *) q->data + (iq1*nbq1 + iq2*nbq2 + iq3*nbq3);
362
241
  dma_queue_push(dma, dma_make_ptr(spad_q, q_row_ptr), factx->size_q_row_padded, nbq1, size_q_row, 1);
363
242
 
364
- // FARF(HIGH, "fa %u: prefetch Q: ir %u iq1 %u iq2 %u iq3 %u q_row_ptr %p size %u : usec %u", ith, ir, iq1, iq2, iq3, q_row_ptr, size_q_row,
365
- // (unsigned)HAP_perf_qtimer_count_to_us(HAP_perf_get_qtimer_count() - factx->t_start));
366
-
367
243
  const __fp16 * mp_base = NULL;
368
244
  if (mask) {
369
245
  const uint32_t im2 = fastmodulo(iq2, mask->ne[2], &factx->src3_div2);
@@ -389,22 +265,16 @@ static void flash_attn_ext_f16_thread(unsigned int nth, unsigned int ith, void *
389
265
  // Mask
390
266
  if (mask) {
391
267
  const uint8_t * m_src = (const uint8_t *) (mp_base + ic_start);
392
- uint8_t * m_dst = spad_m + (ib % 2) * factx->size_m_block;
393
268
  // Mask is 1D contiguous for this row
394
- dma_queue_push(dma, dma_make_ptr(m_dst, m_src), current_block_size * 2, current_block_size * 2, current_block_size * 2, 1);
269
+ dma_cache_push(dma, &m_cache, m_src, current_block_size * 2, current_block_size * 2, current_block_size * 2, 1);
395
270
  }
396
-
397
- // FARF(HIGH, "fa %u: prefetch KVM: ir %u ib %u iq1 %u iq2 %u iq3 %u : size_k_row %u size_v_row %u bs %u: usec %u",
398
- // ith, ir, ib, iq1, iq2, iq3,
399
- // size_k_row, size_v_row, current_block_size,
400
- // (unsigned)HAP_perf_qtimer_count_to_us(HAP_perf_get_qtimer_count() - factx->t_start));
401
271
  }
402
272
 
403
273
  const uint32_t h = iq2; // head index
404
- const float slope = (factx->max_bias > 0.0f) ? (h < factx->n_head_log2 ? powf(factx->m0, h + 1) : powf(factx->m1, 2*(h - factx->n_head_log2) + 1)) : 1.0f;
274
+ const __fp16 slope = factx->slopes[h];
405
275
 
406
276
  HVX_Vector S_vec = hvx_vec_splat_f32(0.0f);
407
- HVX_Vector M_vec = hvx_vec_splat_f32(-INFINITY);
277
+ HVX_Vector M_vec = hvx_vec_splat_f32(HTP_FA_M_INITIAL_VAL);
408
278
 
409
279
  // Clear accumulator
410
280
  hvx_splat_f32_a(spad_a, 0, DV);
@@ -416,6 +286,7 @@ static void flash_attn_ext_f16_thread(unsigned int nth, unsigned int ith, void *
416
286
  }
417
287
 
418
288
  const HVX_Vector slope_vec = hvx_vec_splat_f16(slope);
289
+ const HVX_Vector v_neg_inf = Q6_Vh_vsplat_R(0xfbff);
419
290
  for (uint32_t ib = 0; ib < factx->n_blocks; ++ib) {
420
291
  const uint32_t ic_start = ib * FLASH_ATTN_BLOCK_SIZE;
421
292
  const uint32_t current_block_size = MIN(FLASH_ATTN_BLOCK_SIZE, nek1 - ic_start);
@@ -425,117 +296,101 @@ static void flash_attn_ext_f16_thread(unsigned int nth, unsigned int ith, void *
425
296
  uint8_t * v_base = dma_queue_pop(dma).dst; // V
426
297
  __fp16 * m_base = mask ? dma_queue_pop(dma).dst : NULL; // M
427
298
 
428
- // FARF(HIGH, "fa %u: process: ir %u ib %u : iq1 %u iq2 %u iq3 %u q_ptr_vtcm %p : usec %u",
429
- // ith, ir, ib, iq1, iq2, iq3, q_ptr_vtcm,
430
- // (unsigned)HAP_perf_qtimer_count_to_us(HAP_perf_get_qtimer_count() - factx->t_start));
299
+ htp_trace_event_start(tr, HTP_TRACE_EVT_HVX_FA_QK, ir);
431
300
 
432
301
  // Inner loop processing the block from VTCM
433
- uint32_t ic = 0;
434
-
435
- // Process in sub-blocks of 32 (VLEN_FP32)
436
- HVX_Vector sb_scores[FLASH_ATTN_BLOCK_SIZE / VLEN_FP32];
437
- HVX_Vector v_max = hvx_vec_splat_f32(-INFINITY);
438
- for (uint32_t iv = 0; ic + VLEN_FP32 <= current_block_size; ic += VLEN_FP32, ++iv) {
439
- // 1. Compute scores
440
- HVX_Vector scores = hvx_dot_f16_f16_aa_rx32(q_ptr_vtcm, k_base + ic * factx->size_k_row_padded, factx->size_k_row_padded, DK, factx->scale);
441
-
442
- // 2. Softcap
443
- if (factx->logit_softcap != 0.0f) {
444
- scores = hvx_vec_tanh_f32(scores);
445
- scores = Q6_Vqf32_vmpy_VsfVsf(scores, logit_cap);
446
- scores = Q6_Vsf_equals_Vqf32(scores);
447
- }
302
+ // 1. Compute scores (64 elements FP16)
303
+ HVX_Vector scores_f16 = Q6_V_vzero();
304
+ if (current_block_size > 0) {
305
+ HVX_Vector scores0 = hvx_dot_f16_f16_aa_rx32(q_ptr_vtcm, k_base, factx->size_k_row_padded, DK, factx->scale);
306
+ HVX_Vector scores1 = (current_block_size > 32) ? hvx_dot_f16_f16_aa_rx32(q_ptr_vtcm, k_base + 32 * factx->size_k_row_padded, factx->size_k_row_padded, DK, factx->scale) : Q6_V_vzero();
307
+ scores_f16 = hvx_vec_f32_to_f16(scores0, scores1);
308
+ }
448
309
 
449
- // 3. Mask
450
- if (mask) {
451
- const __fp16 * mp = m_base + ic;
452
- HVX_Vector m_vals_f16 = *(const HVX_UVector *) mp;
453
- HVX_VectorPair m_vals_f32_pair = Q6_Wqf32_vmpy_VhfVhf(Q6_Vh_vshuff_Vh(m_vals_f16), slope_vec);
454
- HVX_Vector add_val = Q6_V_lo_W(m_vals_f32_pair);
455
- scores = Q6_Vqf32_vadd_Vqf32Vsf(add_val, scores);
456
- scores = Q6_Vsf_equals_Vqf32(scores);
457
- }
310
+ // 2. Softcap (in FP16)
311
+ if (factx->logit_softcap != 0.0f) {
312
+ const HVX_Vector v_cap = hvx_vec_splat_f16(factx->logit_softcap);
313
+ scores_f16 = hvx_vec_tanh_f16(scores_f16);
314
+ scores_f16 = hvx_vec_mul_f16_f16(scores_f16, v_cap);
315
+ }
458
316
 
459
- sb_scores[iv] = scores;
460
- v_max = hvx_vec_reduce_max2_f32(scores, v_max); // All lanes have block max
317
+ HVX_VectorPred q_tail_keep = Q6_Q_vsetq2_R(current_block_size * sizeof(__fp16));
318
+
319
+ // 3. Mask (in FP16)
320
+ if (mask) {
321
+ HVX_Vector m_vals_f16 = *(const HVX_UVector *) m_base;
322
+ HVX_Vector vinf = Q6_Vh_vsplat_R(0xFC00);
323
+ HVX_Vector vmin = Q6_Vh_vsplat_R(0xFBFF);
324
+ HVX_VectorPred is_inf = Q6_Q_vcmp_eq_VhVh(m_vals_f16, vinf);
325
+ m_vals_f16 = Q6_V_vmux_QVV(is_inf, vmin, m_vals_f16);
326
+
327
+ HVX_Vector m_scaled = hvx_vec_mul_f16_f16(m_vals_f16, slope_vec);
328
+ scores_f16 = Q6_V_vmux_QVV(q_tail_keep, hvx_vec_add_f16_f16(scores_f16, m_scaled), v_neg_inf);
329
+ } else {
330
+ scores_f16 = Q6_V_vmux_QVV(q_tail_keep, scores_f16, v_neg_inf);
461
331
  }
462
332
 
333
+ // Compute block max in FP16
334
+ HVX_Vector v_max_f16 = hvx_vec_reduce_max_f16(scores_f16);
335
+ HVX_Vector v_max = Q6_V_lo_W(hvx_vec_f16_to_f32(v_max_f16)); // splat block max in FP32
336
+ htp_trace_event_stop(tr, HTP_TRACE_EVT_HVX_FA_QK, ir);
337
+
338
+ htp_trace_event_start(tr, HTP_TRACE_EVT_HVX_FA_SFM, ir);
463
339
  {
340
+ const HVX_Vector v_log2e = hvx_vec_splat_f16(EXP_LOG2E_F);
341
+
464
342
  // 4. Online Softmax Update
465
343
  HVX_Vector M_new_vec = Q6_Vsf_vmax_VsfVsf(v_max, M_vec);
466
- HVX_Vector diff_vec = Q6_Vsf_equals_Vqf32(Q6_Vqf32_vsub_VsfVsf(M_vec, M_new_vec));
467
- HVX_Vector ms_vec = hvx_vec_exp_f32(diff_vec);
344
+ HVX_Vector diff_vec = HVX_OP_SUB_F32(M_vec, M_new_vec);
345
+
346
+ HVX_Vector diff_f16 = hvx_vec_f32_to_f16(diff_vec, diff_vec);
347
+ HVX_Vector diff_base2 = hvx_vec_mul_f16_f16(diff_f16, v_log2e);
348
+ HVX_Vector ms_f16 = hvx_vec_exp2_f16(diff_base2);
349
+ HVX_Vector ms_vec = Q6_V_lo_W(hvx_vec_f16_to_f32(ms_f16));
350
+
468
351
  M_vec = M_new_vec;
469
352
 
470
353
  hvx_scale_vec_f32_aa((uint8_t *) VKQ32, (const uint8_t *) VKQ32, DV, ms_vec);
471
354
 
472
- HVX_Vector p_sum_vec = hvx_vec_splat_f32(0.0f);
473
- for (uint32_t ic2 = 0, iv = 0; ic2 + VLEN_FP32 <= current_block_size; ic2 += VLEN_FP32, ++iv) {
474
- HVX_Vector scores = sb_scores[iv];
475
- HVX_Vector scores_shifted = Q6_Vqf32_vsub_VsfVsf(scores, M_vec);
476
- HVX_Vector P = hvx_vec_exp_f32(Q6_Vsf_equals_Vqf32(scores_shifted));
355
+ // Compute P = exp2((S - M) * log2(e)) in FP16
356
+ HVX_Vector v_m_vec_f16 = hvx_vec_f32_to_f16(M_vec, M_vec);
357
+ HVX_Vector v_s_minus_m = Q6_Vqf16_vsub_VhfVhf(scores_f16, v_m_vec_f16);
477
358
 
478
- p_sum_vec = Q6_Vsf_equals_Vqf32(Q6_Vqf32_vadd_VsfVsf(p_sum_vec, P));
359
+ HVX_Vector v_s_minus_m_base2 = hvx_vec_mul_f16_f16(Q6_Vhf_equals_Vqf16(v_s_minus_m), v_log2e);
479
360
 
480
- // 5. Accumulate V
481
- __fp16 __attribute__((aligned(VLEN))) p_arr[VLEN_FP16];
482
- hvx_vec_f32_to_f16_a(p_arr, P, hvx_vec_splat_f32(0));
361
+ HVX_Vector P = hvx_vec_exp2_f16(v_s_minus_m_base2);
362
+ P = Q6_V_vmux_QVV(q_tail_keep, P, Q6_V_vzero());
483
363
 
484
- for (uint32_t j = 0; j < VLEN_FP32; j += 2) {
485
- const uint32_t cur_ic = ic2 + j;
486
- const uint8_t * v_ptr = v_base + cur_ic * factx->size_v_row_padded;
487
- hvx_mad_f32_f16_aa_rx2(VKQ32, v_ptr, v_ptr + factx->size_v_row_padded, (p_arr + j), (p_arr + j + 1), DV);
488
- }
489
- }
364
+ // Convert P to FP32 to update the running sum S_vec
365
+ HVX_VectorPair P_pair = hvx_vec_f16_to_f32(P);
366
+ HVX_Vector P0 = Q6_V_lo_W(P_pair);
367
+ HVX_Vector P1 = Q6_V_hi_W(P_pair);
368
+ HVX_Vector p_sum_vec = hvx_vec_reduce_sum_f32(HVX_OP_ADD_F32(P0, P1));
490
369
 
491
- p_sum_vec = hvx_vec_reduce_sum_f32(p_sum_vec);
492
- S_vec = Q6_Vsf_equals_Vqf32(Q6_Vqf32_vadd_VsfVsf(Q6_Vsf_equals_Vqf32(Q6_Vqf32_vmpy_VsfVsf(S_vec, ms_vec)), p_sum_vec));
493
- }
370
+ S_vec = HVX_OP_ADD_F32(HVX_OP_MUL_F32(S_vec, ms_vec), p_sum_vec);
494
371
 
495
- if (ic < current_block_size) {
496
- // Sync scalars for leftover/next block if needed
497
- float M = hvx_vec_get_f32(M_vec);
498
- float S = hvx_vec_get_f32(S_vec);
499
-
500
- // Leftover
501
- for (; ic < current_block_size; ++ic) {
502
- float s_val;
503
- const uint8_t * k_ptr = k_base + ic * factx->size_k_row_padded;
504
- hvx_dot_f16_f16_aa(&s_val, q_ptr_vtcm, k_ptr, DK, factx->scale);
505
- if (factx->logit_softcap != 0.0f) {
506
- s_val = factx->logit_softcap * tanhf(s_val);
507
- }
372
+ // 5. Accumulate V (F16 * F16 -> F32 accumulator)
373
+ __fp16 __attribute__((aligned(128))) p_arr[VLEN_FP16];
374
+ hvx_vec_store_a(p_arr, 128, P);
508
375
 
509
- if (mask) {
510
- const float m_val = m_base[ic];
511
- s_val += slope * m_val;
376
+ for (uint32_t j = 0; j < current_block_size; j += 2) {
377
+ if (j + 1 == current_block_size) {
378
+ if (p_arr[j] != 0.0f) {
379
+ const uint8_t * v_ptr = v_base + j * factx->size_v_row_padded;
380
+ hvx_mad_f32_f16_aa(VKQ32, v_ptr, (p_arr + j), DV);
381
+ }
382
+ break;
512
383
  }
513
384
 
514
- const float Mold = M;
515
- __fp16 vs = 1.0f;
516
-
517
- if (s_val > M) {
518
- M = s_val;
519
- HVX_Vector diff_vec = hvx_vec_splat_f32(Mold - M);
520
- HVX_Vector ms_vec = hvx_vec_exp_f32(diff_vec);
521
- hvx_scale_vec_f32_aa((uint8_t *) VKQ32, (const uint8_t *) VKQ32, DV, ms_vec);
522
-
523
- float ms = hvx_vec_get_f32(ms_vec);
524
- S = S * ms + vs;
525
- } else {
526
- HVX_Vector diff_vec = hvx_vec_splat_f32(s_val - M);
527
- vs = hvx_vec_get_f32(hvx_vec_exp_f32(diff_vec));
528
- S += vs;
385
+ if (p_arr[j] == 0.0f && p_arr[j + 1] == 0.0f) {
386
+ continue;
529
387
  }
530
388
 
531
- const uint8_t * v_ptr = v_base + ic * factx->size_v_row_padded;
532
-
533
- hvx_mad_f32_f16_aa(VKQ32, v_ptr, &vs, DV);
389
+ const uint8_t * v_ptr = v_base + j * factx->size_v_row_padded;
390
+ hvx_mad_f32_f16_aa_rx2(VKQ32, v_ptr, v_ptr + factx->size_v_row_padded, (p_arr + j), (p_arr + j + 1), DV);
534
391
  }
535
-
536
- M_vec = hvx_vec_splat_f32(M);
537
- S_vec = hvx_vec_splat_f32(S);
538
392
  }
393
+ htp_trace_event_stop(tr, HTP_TRACE_EVT_HVX_FA_SFM, ir);
539
394
 
540
395
  // Issue DMA for next+1 block (if exists)
541
396
  if (ib + 2 < factx->n_blocks) {
@@ -554,16 +409,12 @@ static void flash_attn_ext_f16_thread(unsigned int nth, unsigned int ith, void *
554
409
  // Mask
555
410
  if (mask) {
556
411
  const uint8_t * m_src = (const uint8_t *) (mp_base + next_ic_start);
557
- dma_queue_push(dma, dma_make_ptr(m_base, m_src), next_block_size * 2, next_block_size * 2, next_block_size * 2, 1);
412
+ dma_cache_push(dma, &m_cache, m_src, next_block_size * 2, next_block_size * 2, next_block_size * 2, 1);
558
413
  }
559
-
560
- // FARF(HIGH, "fa %u: prefetch KVM: ir %u ib %u : iq1 %u iq2 %u iq3 %u : size_k_row %u size_v_row %u bs %u: usec %u",
561
- // ith, ir, next_ib, iq1, iq2, iq3,
562
- // size_k_row, size_v_row, next_block_size,
563
- // (unsigned)HAP_perf_qtimer_count_to_us(HAP_perf_get_qtimer_count() - factx->t_start));
564
414
  }
565
415
  }
566
416
 
417
+ htp_trace_event_start(tr, HTP_TRACE_EVT_HVX_O_PROC, ir);
567
418
  // sinks
568
419
  float M = hvx_vec_get_f32(M_vec);
569
420
  float S = hvx_vec_get_f32(S_vec);
@@ -592,119 +443,1646 @@ static void flash_attn_ext_f16_thread(unsigned int nth, unsigned int ith, void *
592
443
 
593
444
  // Store result
594
445
  // dst indices
595
- const int i1 = iq1;
596
- const int i2 = iq2;
597
- const int i3 = iq3;
446
+ const uint32_t i1 = iq1;
447
+ const uint32_t i2 = iq2;
448
+ const uint32_t i3 = iq3;
598
449
 
599
- // dst is permuted
600
- uint8_t * dst_ptr = (uint8_t *) dst->data + (i3*ne2*ne1 + i2 + i1*ne1) * nb1;
450
+ // dst is permuted: [DV, n_heads, n_tokens, n_seq]
451
+ // head stride is nb[1], token stride is nb[2], batch stride is nb[3]
452
+ uint8_t * dst_ptr = (uint8_t *) dst->data + i2 * dst->nb[1] + i1 * dst->nb[2] + i3 * dst->nb[3];
601
453
 
602
454
  if (dst->type == HTP_TYPE_F32) {
603
455
  hvx_copy_f32_ua(dst_ptr, (uint8_t *) VKQ32, DV);
604
456
  } else if (dst->type == HTP_TYPE_F16) {
605
457
  hvx_copy_f16_f32_ua(dst_ptr, (uint8_t *) VKQ32, DV);
606
458
  }
459
+ htp_trace_event_stop(tr, HTP_TRACE_EVT_HVX_O_PROC, ir);
460
+ }
461
+ }
462
+
463
+ // ============================================================================
464
+ // HMX Phase args and thread logic
465
+ // ============================================================================
466
+
467
+ typedef struct {
468
+ struct hmx_fa_context * factx;
469
+ uint32_t kv_rows;
470
+ size_t src_stride;
471
+ void * curr_k;
472
+ uint32_t kv_start;
473
+ uint32_t rows_per_t;
474
+ } fa_k_int_args_t;
475
+
476
+ static void fa_k_interleave_thread(unsigned int n, unsigned int i, void * data) {
477
+ fa_k_int_args_t * args = (fa_k_int_args_t *) data;
478
+ struct hmx_fa_context * factx = args->factx;
479
+
480
+ const uint32_t total_rows = args->kv_rows;
481
+ const uint32_t rows_per_t = args->rows_per_t;
482
+ const uint32_t start = i * rows_per_t;
483
+ const uint32_t end = (uint32_t) hex_smin(start + rows_per_t, total_rows);
484
+
485
+ if (start >= total_rows) {
486
+ return;
487
+ }
488
+
489
+ struct htp_thread_trace * tr = factx->octx->ctx ? &factx->octx->ctx->trace[i] : NULL;
490
+ htp_trace_event_start(tr, HTP_TRACE_EVT_HVX_FA_K_PREP, (uint16_t) (args->kv_start + start));
491
+ hmx_interleave_rows_to_tiles(factx->vtcm_k_tiles, (const __fp16 *) args->curr_k, total_rows, factx->DK,
492
+ args->src_stride, start, end);
493
+ htp_trace_event_stop(tr, HTP_TRACE_EVT_HVX_FA_K_PREP, (uint16_t) (args->kv_start + start));
494
+ }
495
+
496
+ static void fa_phase_k_interleave(struct hmx_fa_context * factx, uint32_t kv_rows, size_t src_stride, void * curr_k, uint32_t kv_start) {
497
+ worker_pool_context_t wp = factx->octx->ctx->worker_pool;
498
+ uint32_t n = 1;
499
+ if (factx->n_threads > 1 && kv_rows >= factx->n_threads * 2) {
500
+ n = factx->n_threads;
501
+ }
502
+ uint32_t rows_per_t = hex_align_up(hmx_ceil_div(kv_rows, n), 2);
503
+ fa_k_int_args_t args = { factx, kv_rows, src_stride, curr_k, kv_start, rows_per_t };
504
+ if (n > 1) {
505
+ worker_pool_run_func(wp, fa_k_interleave_thread, &args, n);
506
+ } else {
507
+ fa_k_interleave_thread(1, 0, &args);
508
+ }
509
+ }
510
+
511
+ typedef struct {
512
+ struct hmx_fa_context * factx;
513
+ uint32_t kv_rows;
514
+ size_t src_stride;
515
+ void * v_src;
516
+ void * v_tiles_dst;
517
+ size_t n_col_tiles;
518
+ uint32_t kv_start;
519
+ uint32_t rows_per_t;
520
+ } fa_v_int_args_t;
521
+
522
+ static void fa_v_interleave_thread(unsigned int n, unsigned int i, void * data) {
523
+ fa_v_int_args_t * args = (fa_v_int_args_t *) data;
524
+ struct hmx_fa_context * factx = args->factx;
525
+
526
+ const uint32_t total_rows = args->kv_rows;
527
+ const uint32_t rows_per_t = args->rows_per_t;
528
+ const uint32_t start = i * rows_per_t;
529
+ const uint32_t end = (uint32_t) hex_smin(start + rows_per_t, total_rows);
530
+
531
+ if (start >= total_rows) {
532
+ return;
533
+ }
534
+
535
+ __fp16 * v_tiles_dst = (__fp16 *) args->v_tiles_dst;
536
+
537
+ struct htp_thread_trace * tr = factx->octx->ctx ? &factx->octx->ctx->trace[i] : NULL;
538
+ htp_trace_event_start(tr, HTP_TRACE_EVT_HVX_FA_V_PREP, (uint16_t) (args->kv_start + start));
539
+ hmx_interleave_cols_to_tiles(v_tiles_dst, (const __fp16 *) args->v_src, total_rows, factx->DV,
540
+ args->src_stride, (uint32_t) args->n_col_tiles, start, end);
541
+ htp_trace_event_stop(tr, HTP_TRACE_EVT_HVX_FA_V_PREP, (uint16_t) (args->kv_start + start));
542
+ }
543
+
544
+ static void fa_phase_v_interleave(struct hmx_fa_context * factx,
545
+ uint32_t kv_rows,
546
+ size_t src_stride,
547
+ void * v_src,
548
+ void * v_tiles_dst,
549
+ size_t n_col_tiles,
550
+ uint32_t kv_start) {
551
+ worker_pool_context_t wp = factx->octx->ctx->worker_pool;
552
+ uint32_t n = 1;
553
+ if (factx->n_threads > 1 && kv_rows >= factx->n_threads * 2) {
554
+ n = factx->n_threads;
555
+ }
556
+ uint32_t rows_per_t = hex_align_up(hmx_ceil_div(kv_rows, n), 2);
557
+ fa_v_int_args_t args = { factx, kv_rows, src_stride, v_src, v_tiles_dst, n_col_tiles, kv_start, rows_per_t };
558
+ if (n > 1) {
559
+ worker_pool_run_func(wp, fa_v_interleave_thread, &args, n);
560
+ } else {
561
+ fa_v_interleave_thread(1, 0, &args);
562
+ }
563
+ }
564
+
565
+ typedef struct {
566
+ struct hmx_fa_context * factx;
567
+ const struct htp_tensor * q;
568
+ uint32_t q_start;
569
+ uint32_t kv_head;
570
+ uint32_t ib3;
571
+ size_t n_rows_g;
572
+ size_t rows_per_t;
573
+ size_t n_rows_q;
574
+ bool q_transposed;
575
+ atomic_uint barrier;
576
+ } fa_q_load_args_t;
577
+
578
+ static void fa_q_load_thread(unsigned int n, unsigned int i, void * data) {
579
+ fa_q_load_args_t * args = (fa_q_load_args_t *) data;
580
+ struct hmx_fa_context * factx = args->factx;
581
+
582
+ const size_t n_rows_g = args->n_rows_g;
583
+ const size_t G = factx->G;
584
+ const size_t DK = factx->DK;
585
+
586
+ // Partition the padded Q rows (g_br) across threads.
587
+ // Keep start/end even so r and r+1 are always in the same thread's range.
588
+ const size_t rows_per_t = args->rows_per_t;
589
+ const size_t start = (size_t) i * rows_per_t;
590
+ const size_t end = hex_smin(start + rows_per_t, factx->g_br);
591
+
592
+ struct htp_thread_trace * tr = factx->octx->ctx ? &factx->octx->ctx->trace[i] : NULL;
593
+ htp_trace_event_start(tr, HTP_TRACE_EVT_HVX_FA_Q_PREP, (uint16_t) (args->q_start * G + start));
594
+
595
+ // Parallel initialization of per-block state
596
+ {
597
+ const uint32_t g_br = factx->g_br;
598
+ const uint32_t DV = factx->DV;
599
+
600
+ const size_t col_vec_bytes = factx->col_vec_bytes;
601
+ const size_t d_tile_bytes = factx->d_tile_bytes;
602
+
603
+ // Initialize vtcm_l_vec & vtcm_m_vec
604
+ const size_t l_bytes_per_t = hex_align_up(col_vec_bytes / n, 128);
605
+ const size_t l_start = i * l_bytes_per_t;
606
+ const size_t l_end = hex_smin(l_start + l_bytes_per_t, col_vec_bytes);
607
+
608
+ const size_t m_bytes_per_t = hex_align_up(col_vec_bytes / n, 128);
609
+ const size_t m_start = i * m_bytes_per_t;
610
+ const size_t m_end = hex_smin(m_start + m_bytes_per_t, col_vec_bytes);
611
+
612
+ if (factx->sinks) {
613
+ const float * sinks_data = (const float *) (uintptr_t) factx->sinks->data;
614
+ float * m_vec = (float *) factx->vtcm_m_vec;
615
+ const size_t r_start = l_start / sizeof(float);
616
+ const size_t r_end = l_end / sizeof(float);
617
+ const float scale_factor = EXP_LOG2E_F;
618
+
619
+ const HVX_Vector v_scale = hvx_vec_splat_f32(scale_factor);
620
+
621
+ for (size_t r = r_start; r < r_end; r += 32) {
622
+ HVX_VectorAlias local_m;
623
+ for (size_t j = 0; j < 32; ++j) {
624
+ size_t curr_r = r + j;
625
+ if (curr_r < n_rows_g) {
626
+ const size_t h_idx = fastmodulo(curr_r, G, &factx->div_G);
627
+ const size_t head = args->kv_head * G + h_idx;
628
+ local_m.fp32[j] = sinks_data[head];
629
+ } else {
630
+ local_m.fp32[j] = HTP_FA_M_INITIAL_VAL;
631
+ }
632
+ }
633
+ HVX_Vector v_scaled = HVX_OP_MUL_F32(local_m.v, v_scale);
634
+ *(HVX_Vector *) (m_vec + r) = v_scaled;
635
+ }
636
+ if (l_start < col_vec_bytes) {
637
+ hvx_splat_u8_a((char *) factx->vtcm_l_vec + l_start, 0, l_end - l_start);
638
+ }
639
+ } else {
640
+ if (l_start < col_vec_bytes) {
641
+ hvx_splat_u8_a((char *) factx->vtcm_l_vec + l_start, 0, l_end - l_start);
642
+ }
643
+ if (m_start < col_vec_bytes) {
644
+ hvx_splat_f32_a((char *) factx->vtcm_m_vec + m_start, HTP_FA_M_INITIAL_VAL, (m_end - m_start) / sizeof(float));
645
+ }
646
+ }
647
+
648
+ // Initialize vtcm_d_tiles to 0
649
+ const size_t d_bytes_per_t = hex_align_up(d_tile_bytes / n, 128);
650
+ const size_t d_start = i * d_bytes_per_t;
651
+ const size_t d_end = hex_smin(d_start + d_bytes_per_t, d_tile_bytes);
652
+ if (d_start < d_tile_bytes) {
653
+ hvx_splat_u8_a((char *) factx->vtcm_d_tiles + d_start, 0, d_end - d_start);
654
+ }
655
+ }
656
+
657
+ if (start < factx->g_br) {
658
+ const struct htp_tensor * q = args->q;
659
+ const uint32_t q_start = args->q_start;
660
+ const uint32_t kv_head = args->kv_head;
661
+ const uint32_t ib3 = args->ib3;
662
+
663
+ assert(factx->DK == factx->DV);
664
+
665
+ const size_t o_tile_bytes = factx->o_tile_bytes;
666
+ const bool use_q_dma = (2 * o_tile_bytes >= factx->g_br * DK * (factx->is_q_fp32 ? 4 : 2));
667
+
668
+ __fp16 * q_tiles = factx->vtcm_q_tiles;
669
+ if (use_q_dma) {
670
+ const size_t g_rows_end = hex_smin(end, n_rows_g);
671
+ const uint32_t d_limit = factx->is_q_fp32 ? DK / 32 : DK / 64;
672
+
673
+ uint8_t * q_flat = (uint8_t *) factx->vtcm_o_tiles[0];
674
+ if (factx->is_q_fp32) {
675
+ switch (d_limit) {
676
+ case 2: hmx_fa_q_prep_fp32_d2(q_tiles, q_flat, start, end, g_rows_end, DK, G, args->n_rows_q, &factx->div_G, args->q_transposed); break;
677
+ case 4: hmx_fa_q_prep_fp32_d4(q_tiles, q_flat, start, end, g_rows_end, DK, G, args->n_rows_q, &factx->div_G, args->q_transposed); break;
678
+ default: hmx_fa_q_prep_fp32( q_tiles, q_flat, start, end, g_rows_end, DK, G, args->n_rows_q, &factx->div_G, d_limit, args->q_transposed); break;
679
+ }
680
+ } else {
681
+ switch (d_limit) {
682
+ case 1: hmx_fa_q_prep_fp16_d1(q_tiles, q_flat, start, end, g_rows_end, DK, G, args->n_rows_q, &factx->div_G, args->q_transposed); break;
683
+ case 2: hmx_fa_q_prep_fp16_d2(q_tiles, q_flat, start, end, g_rows_end, DK, G, args->n_rows_q, &factx->div_G, args->q_transposed); break;
684
+ default: hmx_fa_q_prep_fp16( q_tiles, q_flat, start, end, g_rows_end, DK, G, args->n_rows_q, &factx->div_G, d_limit, args->q_transposed); break;
685
+ }
686
+ }
687
+ } else {
688
+ // Fallback: direct-from-DDR/L2 path
689
+ hmx_fa_q_prep_fallback(q_tiles, q->data, q->nb[1], q->nb[2], q->nb[3],
690
+ q_start, kv_head, ib3, start, end, n_rows_g, G, DK, factx->is_q_fp32, &factx->div_G);
691
+ }
692
+ }
693
+
694
+ // Synchronize threads before zeroing out vtcm_o_tiles[0] to prevent race condition
695
+ if (n > 1) {
696
+ atomic_fetch_sub(&args->barrier, 1);
697
+ while (atomic_load(&args->barrier) > 0) {
698
+ // spin wait
699
+ }
700
+ }
701
+
702
+ // Zero out vtcm_o_tiles[0] as it was used as temp_q_vtcm
703
+ {
704
+ const uint32_t g_br = factx->g_br;
705
+ const uint32_t DV = factx->DV;
706
+ const size_t o_tile_bytes = factx->o_tile_bytes;
707
+ const size_t o_bytes_per_t = hex_align_up(o_tile_bytes / n, 128);
708
+ const size_t o_start = i * o_bytes_per_t;
709
+ const size_t o_end = hex_smin(o_start + o_bytes_per_t, o_tile_bytes);
710
+ if (o_start < o_tile_bytes) {
711
+ hvx_splat_u8_a((char *) factx->vtcm_o_tiles[0] + o_start, 0, o_end - o_start);
712
+ }
713
+ }
714
+ htp_trace_event_stop(tr, HTP_TRACE_EVT_HVX_FA_Q_PREP, (uint16_t) (args->q_start * G + start));
715
+ }
716
+
717
+ static void fa_phase_q_load(struct hmx_fa_context * factx,
718
+ const struct htp_tensor * q,
719
+ uint32_t q_start,
720
+ uint32_t kv_head,
721
+ uint32_t ib3,
722
+ size_t n_rows_g) {
723
+ worker_pool_context_t wp = factx->octx->ctx->worker_pool;
724
+ uint32_t n = 1;
725
+ if (factx->n_threads > 1 && n_rows_g >= (size_t) (factx->n_threads * 2)) {
726
+ n = factx->n_threads;
727
+ }
728
+ size_t rows_per_t = hex_align_up(hmx_ceil_div(factx->g_br, n), 2);
729
+ const uint32_t n_rows_q = hex_smin(factx->Br, factx->neq1 - q_start);
730
+ fa_q_load_args_t args;
731
+ args.factx = factx;
732
+ args.q = q;
733
+ args.q_start = q_start;
734
+ args.kv_head = kv_head;
735
+ args.ib3 = ib3;
736
+ args.n_rows_g = n_rows_g;
737
+ args.rows_per_t = rows_per_t;
738
+ args.n_rows_q = n_rows_q;
739
+ args.q_transposed = q->nb[1] < q->nb[2];
740
+ atomic_init(&args.barrier, n);
741
+ if (n > 1) {
742
+ worker_pool_run_func(wp, fa_q_load_thread, &args, n);
743
+ } else {
744
+ fa_q_load_thread(1, 0, &args);
745
+ }
746
+ }
747
+
748
+ typedef struct {
749
+ struct hmx_fa_context * factx;
750
+ const struct htp_tensor * dst;
751
+ const __fp16 * o_tile_src;
752
+ uint32_t q_start;
753
+ uint32_t kv_head;
754
+ uint32_t ib3;
755
+ size_t n_rows_g;
756
+ size_t rows_per_t;
757
+ } fa_o_store_args_t;
758
+
759
+ static void fa_o_store_thread_f32(unsigned int n, unsigned int i, void * data) {
760
+ fa_o_store_args_t * args = (fa_o_store_args_t *) data;
761
+ struct hmx_fa_context * factx = args->factx;
762
+
763
+ const size_t n_rows_g = args->n_rows_g;
764
+ const size_t G = factx->G;
765
+ const size_t DV = factx->DV;
766
+
767
+ const size_t rows_per_t = args->rows_per_t;
768
+ const size_t start = (size_t) i * rows_per_t;
769
+ const size_t end = hex_smin(start + rows_per_t, n_rows_g);
770
+
771
+ if (start >= n_rows_g) {
772
+ return;
773
+ }
774
+
775
+ struct htp_thread_trace * tr = factx->octx->ctx ? &factx->octx->ctx->trace[i] : NULL;
776
+ htp_trace_event_start(tr, HTP_TRACE_EVT_HVX_O_PROC, (uint16_t) (args->q_start * G + start));
777
+
778
+ const struct htp_tensor * dst = args->dst;
779
+ const __fp16 * o_tile_src = args->o_tile_src;
780
+ const uint32_t q_start = args->q_start;
781
+ const uint32_t kv_head = args->kv_head;
782
+ const uint32_t ib3 = args->ib3;
783
+
784
+ for (size_t r = start; r < end; ++r) {
785
+ const size_t q_idx = fastdiv(r, &factx->div_G);
786
+ const size_t h_idx = fastmodulo(r, G, &factx->div_G);
787
+
788
+ float * out = (float *) ((uint8_t *) dst->data + (kv_head * G + h_idx) * dst->nb[1] +
789
+ (q_start + q_idx) * dst->nb[2] + ib3 * dst->nb[3]);
790
+
791
+ size_t r0 = r / HMX_FP16_TILE_N_ROWS;
792
+ size_t r1 = r % HMX_FP16_TILE_N_ROWS;
793
+ const __fp16 * tile_row_base = o_tile_src + r0 * HMX_FP16_TILE_N_ROWS * DV;
794
+
795
+ for (uint32_t d = 0; d < DV / 32; ++d) {
796
+ const HVX_Vector * in_tile = (const HVX_Vector *) (tile_row_base + d * HMX_FP16_TILE_N_ELMS);
797
+ HVX_VectorPair vp = hvx_vec_f16_to_f32_shuff(in_tile[r1 / 2]);
798
+ if (r1 % 2 == 0) {
799
+ *(HVX_UVector *) (out + d * 32) = Q6_V_lo_W(vp);
800
+ } else {
801
+ *(HVX_UVector *) (out + d * 32) = Q6_V_hi_W(vp);
802
+ }
803
+ }
804
+ }
805
+ htp_trace_event_stop(tr, HTP_TRACE_EVT_HVX_O_PROC, (uint16_t) (args->q_start * G + start));
806
+ }
807
+
808
+ static void fa_o_store_thread_f16(unsigned int n, unsigned int i, void * data) {
809
+ fa_o_store_args_t * args = (fa_o_store_args_t *) data;
810
+ struct hmx_fa_context * factx = args->factx;
811
+
812
+ const size_t n_rows_g = args->n_rows_g;
813
+ const size_t rows_per_t = args->rows_per_t;
814
+ const size_t G = factx->G;
815
+ const size_t DV = factx->DV;
816
+ const size_t start = (size_t) i * rows_per_t;
817
+ const size_t end = hex_smin(start + rows_per_t, n_rows_g);
818
+
819
+ if (start >= n_rows_g) {
820
+ return;
821
+ }
822
+
823
+ struct htp_thread_trace * tr = factx->octx->ctx ? &factx->octx->ctx->trace[i] : NULL;
824
+ htp_trace_event_start(tr, HTP_TRACE_EVT_HVX_O_PROC, (uint16_t) (args->q_start * G + start));
825
+
826
+ const struct htp_tensor * dst = args->dst;
827
+ const __fp16 * o_tile_src = args->o_tile_src;
828
+ const uint32_t q_start = args->q_start;
829
+ const uint32_t kv_head = args->kv_head;
830
+ const uint32_t ib3 = args->ib3;
831
+
832
+ for (size_t r = start; r < end; ++r) {
833
+ const size_t q_idx = fastdiv(r, &factx->div_G);
834
+ const size_t h_idx = fastmodulo(r, G, &factx->div_G);
835
+
836
+ __fp16 * out = (__fp16 *) ((uint8_t *) dst->data + (kv_head * G + h_idx) * dst->nb[1] +
837
+ (q_start + q_idx) * dst->nb[2] + ib3 * dst->nb[3]);
838
+
839
+ size_t r0 = r / HMX_FP16_TILE_N_ROWS;
840
+ size_t r1 = r % HMX_FP16_TILE_N_ROWS;
841
+ const __fp16 * tile_row_base = o_tile_src + r0 * HMX_FP16_TILE_N_ROWS * DV;
842
+
843
+ for (uint32_t d = 0; d < DV / 64; ++d) {
844
+ const __fp16 * in_dtile = tile_row_base + d * HMX_FP16_TILE_N_ELMS * 2;
845
+ const HVX_Vector * pv_in0 = ((const HVX_Vector *) in_dtile) + r1 / 2;
846
+ const HVX_Vector * pv_in1 = pv_in0 + 16;
847
+ HVX_VectorPair vp = Q6_W_vdeal_VVR(*pv_in1, *pv_in0, -2);
848
+ if (r1 % 2 == 0) {
849
+ *(HVX_UVector *) (out + d * 64) = Q6_V_lo_W(vp);
850
+ } else {
851
+ *(HVX_UVector *) (out + d * 64) = Q6_V_hi_W(vp);
852
+ }
853
+ }
854
+ }
855
+ htp_trace_event_stop(tr, HTP_TRACE_EVT_HVX_O_PROC, (uint16_t) (args->q_start * G + start));
856
+ }
857
+
858
+ static void fa_phase_o_store(struct hmx_fa_context * factx,
859
+ const struct htp_tensor * dst,
860
+ const __fp16 * o_tile_src,
861
+ uint32_t q_start,
862
+ uint32_t kv_head,
863
+ uint32_t ib3,
864
+ size_t n_rows_g) {
865
+ worker_pool_context_t wp = factx->octx->ctx->worker_pool;
866
+ uint32_t n = 1;
867
+ if (factx->n_threads > 1 && n_rows_g >= (size_t) (factx->n_threads * 2)) {
868
+ n = factx->n_threads;
869
+ }
870
+ size_t rows_per_t = hmx_ceil_div(n_rows_g, n);
871
+ fa_o_store_args_t args = { factx, dst, o_tile_src, q_start, kv_head, ib3, n_rows_g, rows_per_t };
872
+ worker_callback_t store_fn = factx->is_dst_fp32 ? fa_o_store_thread_f32 : fa_o_store_thread_f16;
873
+ if (n > 1) {
874
+ worker_pool_run_func(wp, store_fn, &args, n);
875
+ } else {
876
+ store_fn(1, 0, &args);
877
+ }
878
+ }
879
+
880
+ typedef struct {
881
+ struct hmx_fa_context * factx;
882
+ size_t kv_rows;
883
+ size_t n_rows_g;
884
+ size_t n_col_tiles;
885
+ size_t n_tiles_per_bc;
886
+ size_t n_row_tiles;
887
+ size_t n_row_tiles_g_br;
888
+ uint32_t Bc;
889
+ uint32_t G;
890
+ uint32_t kv_head;
891
+ uint32_t kv_start;
892
+ uint32_t q_start;
893
+ uint32_t ib3;
894
+ bool has_alibi; // true when max_bias != 0 (need slope * mask + add)
895
+ __fp16 * slopes;
896
+ const struct htp_tensor * mask;
897
+ const __fp16 * mask_vtcm; // VTCM mask buffer base (NULL = DDR fallback)
898
+ size_t mask_vtcm_row_stride; // elements (__fp16) per row in VTCM mask buffer
899
+ struct fastdiv_values thread_div;
900
+ } fa_softmax_args_t;
901
+
902
+ static inline void fa_softmax_impl(
903
+ unsigned int n, unsigned int i, void * data,
904
+ const bool has_mask,
905
+ const bool mask_broadcast,
906
+ const bool is_g1,
907
+ const bool has_alibi,
908
+ const bool has_softcap
909
+ ) {
910
+ fa_softmax_args_t * args = (fa_softmax_args_t *) data;
911
+ struct hmx_fa_context * factx = args->factx;
912
+
913
+ const size_t n_rows_g = args->n_rows_g;
914
+ const size_t kv_rows = args->kv_rows;
915
+ const size_t Bc = args->Bc;
916
+ const size_t G = args->G;
917
+ const size_t n_tiles_per_bc = args->n_tiles_per_bc;
918
+ const size_t n_row_vec_cnt = hmx_ceil_div(n_rows_g, 64);
919
+ const uint32_t im3 = has_mask ? fastmodulo(args->ib3, args->mask->ne[3], &factx->src3_div3) : 0;
920
+
921
+ size_t vec_start = 0;
922
+ size_t vec_end = n_row_vec_cnt;
923
+ if (n > 1) {
924
+ const size_t vecs_per_t = fastdiv(n_row_vec_cnt + n - 1, &args->thread_div);
925
+ vec_start = i * vecs_per_t;
926
+ vec_end = hex_smin(vec_start + vecs_per_t, n_row_vec_cnt);
927
+ }
928
+
929
+ if (vec_start >= n_row_vec_cnt) {
930
+ return;
931
+ }
932
+
933
+ struct htp_thread_trace * tr = factx->octx->ctx ? &factx->octx->ctx->trace[i] : NULL;
934
+ htp_trace_event_start(tr, HTP_TRACE_EVT_HVX_FA_SFM, (uint16_t) (args->q_start * G + vec_start * 64));
935
+
936
+ // Per-thread row scratch: thread i uses bufs at offset i * 2 * stride
937
+ const size_t row_buf_stride = factx->row_buf_stride;
938
+ HVX_Vector * my_row_buf0 = factx->vtcm_row_bufs + i * 2 * row_buf_stride;
939
+ HVX_Vector * my_row_buf1 = my_row_buf0 + row_buf_stride;
940
+
941
+ const HVX_Vector v_neg_inf = Q6_Vh_vsplat_R(0xfbff);
942
+
943
+ for (size_t r_vec_idx = vec_start; r_vec_idx < vec_end; ++r_vec_idx) {
944
+ HVX_Vector rowmax_acc_v = v_neg_inf;
945
+ HVX_Vector rowsum_acc_v = Q6_V_vzero();
946
+ HVX_Vector m_prev_v0 = factx->vtcm_m_vec[r_vec_idx * 2 + 0];
947
+ HVX_Vector m_prev_v1 = factx->vtcm_m_vec[r_vec_idx * 2 + 1];
948
+
949
+ HVX_Vector v_slopes = Q6_V_vzero();
950
+ if (has_alibi) {
951
+ v_slopes = hvx_vmem(args->slopes + r_vec_idx * 64);
952
+ }
953
+
954
+ for (uint32_t r_vec_off = 0; r_vec_off < 64; r_vec_off += 2) {
955
+ uint32_t r = r_vec_idx * 64 + r_vec_off;
956
+ if (r >= hex_align_up(n_rows_g, 2)) {
957
+ break;
958
+ }
959
+
960
+ uint32_t r0 = r / HMX_FP16_TILE_N_ROWS;
961
+ uint32_t r1 = r % HMX_FP16_TILE_N_ROWS;
962
+
963
+ const __fp16 * s_ld_base = factx->vtcm_s_tiles + r0 * HMX_FP16_TILE_N_ROWS * Bc;
964
+ __fp16 * p_st_base = factx->vtcm_p_tiles + r0 * HMX_FP16_TILE_N_ROWS * Bc;
965
+
966
+ // Decode 2 rows from S tiles into per-thread row buffers
967
+ if (has_softcap) {
968
+ const HVX_Vector v_cap = hvx_vec_splat_f16(factx->logit_softcap);
969
+ for (size_t c = 0; c < kv_rows; c += 64) {
970
+ size_t ci = c / 64;
971
+ const __fp16 * in_dtile = s_ld_base + ci * HMX_FP16_TILE_N_ELMS * 2;
972
+ const HVX_Vector * pv_s_in0 = ((const HVX_Vector *) in_dtile) + r1 / 2;
973
+ const HVX_Vector * pv_s_in1 = pv_s_in0 + 16;
974
+
975
+ HVX_VectorPair vp_s_drow = Q6_W_vdeal_VVR(*pv_s_in1, *pv_s_in0, -2);
976
+ HVX_Vector v_s_row0 = Q6_V_lo_W(vp_s_drow);
977
+ HVX_Vector v_s_row1 = Q6_V_hi_W(vp_s_drow);
978
+
979
+ HVX_Vector t0 = hvx_vec_tanh_f16(v_s_row0);
980
+ my_row_buf0[ci] = hvx_vec_mul_f16_f16(t0, v_cap);
981
+
982
+ HVX_Vector t1 = hvx_vec_tanh_f16(v_s_row1);
983
+ my_row_buf1[ci] = hvx_vec_mul_f16_f16(t1, v_cap);
984
+ }
985
+ } else {
986
+ for (size_t c = 0; c < kv_rows; c += 64) {
987
+ size_t ci = c / 64;
988
+ const __fp16 * in_dtile = s_ld_base + ci * HMX_FP16_TILE_N_ELMS * 2;
989
+ const HVX_Vector * pv_s_in0 = ((const HVX_Vector *) in_dtile) + r1 / 2;
990
+ const HVX_Vector * pv_s_in1 = pv_s_in0 + 16;
991
+
992
+ HVX_VectorPair vp_s_drow = Q6_W_vdeal_VVR(*pv_s_in1, *pv_s_in0, -2);
993
+ my_row_buf0[ci] = Q6_V_lo_W(vp_s_drow);
994
+ my_row_buf1[ci] = Q6_V_hi_W(vp_s_drow);
995
+ }
996
+ }
997
+
998
+ // Apply mask & compute rowmax(S)
999
+ HVX_Vector v_slope0 = Q6_V_vzero();
1000
+ HVX_Vector v_slope1 = Q6_V_vzero();
1001
+ if (has_alibi) {
1002
+ v_slope0 = hvx_vec_repl_f16(Q6_V_vror_VR(v_slopes, r_vec_off * 2));
1003
+ v_slope1 = (r + 1 < n_rows_g) ? hvx_vec_repl_f16(Q6_V_vror_VR(v_slopes, (r_vec_off + 1) * 2)) : Q6_V_vzero();
1004
+ }
1005
+
1006
+ const HVX_Vector v_threshold = Q6_Vh_vsplat_R(0xcc00); // fp16 -16.0
1007
+
1008
+ HVX_Vector v_s_rowmax0 = v_neg_inf;
1009
+ HVX_Vector v_s_rowmax1 = v_neg_inf;
1010
+ for (size_t c = 0; c < kv_rows; c += 64) {
1011
+ size_t ci = c / 64;
1012
+ const size_t ne = hex_smin(kv_rows - c, 64);
1013
+ HVX_VectorPred q_tail_keep = Q6_Q_vsetq2_R(ne * sizeof(__fp16));
1014
+
1015
+ if (has_mask) {
1016
+ HVX_Vector v_mask0, v_mask1;
1017
+
1018
+ if (mask_broadcast) {
1019
+ if (is_g1) {
1020
+ const size_t qi0 = r + 0;
1021
+ v_mask0 = *(const HVX_Vector *) (args->mask_vtcm + qi0 * args->mask_vtcm_row_stride + c);
1022
+ v_mask1 = v_neg_inf;
1023
+ if (r + 1 < n_rows_g) {
1024
+ const size_t qi1 = r + 1;
1025
+ v_mask1 = *(const HVX_Vector *) (args->mask_vtcm + qi1 * args->mask_vtcm_row_stride + c);
1026
+ }
1027
+ } else {
1028
+ const size_t qi0 = fastdiv(r + 0, &factx->div_G);
1029
+ v_mask0 = *(const HVX_Vector *) (args->mask_vtcm + qi0 * args->mask_vtcm_row_stride + c);
1030
+ v_mask1 = v_neg_inf;
1031
+ if (r + 1 < n_rows_g) {
1032
+ const size_t qi1 = fastdiv(r + 1, &factx->div_G);
1033
+ if (qi1 == qi0) {
1034
+ v_mask1 = v_mask0;
1035
+ } else {
1036
+ v_mask1 = *(const HVX_Vector *) (args->mask_vtcm + qi1 * args->mask_vtcm_row_stride + c);
1037
+ }
1038
+ }
1039
+ }
1040
+ } else {
1041
+ // Head-dependent mask: pre-interleaved per row r.
1042
+ const size_t r0 = r + 0;
1043
+ v_mask0 = *(const HVX_Vector *) (args->mask_vtcm + r0 * args->mask_vtcm_row_stride + c);
1044
+ v_mask1 = v_neg_inf;
1045
+ if (r + 1 < n_rows_g) {
1046
+ const size_t r1 = r + 1;
1047
+ v_mask1 = *(const HVX_Vector *) (args->mask_vtcm + r1 * args->mask_vtcm_row_stride + c);
1048
+ }
1049
+ }
1050
+
1051
+ // Threshold: mask values below -16.0 are treated as -inf (causal mask).
1052
+ HVX_VectorPred q_keep0 = Q6_Q_and_QQ(Q6_Q_vcmp_gt_VhfVhf(v_mask0, v_threshold), q_tail_keep);
1053
+ HVX_VectorPred q_keep1 = Q6_Q_and_QQ(Q6_Q_vcmp_gt_VhfVhf(v_mask1, v_threshold), q_tail_keep);
1054
+
1055
+ // Scale mask values by log2(e) for base-2 calculations
1056
+ const HVX_Vector v_log2e = hvx_vec_splat_f16(EXP_LOG2E_F);
1057
+ HVX_Vector v_mask0_scaled = hvx_vec_mul_f16_f16(v_mask0, v_log2e);
1058
+ HVX_Vector v_mask1_scaled = hvx_vec_mul_f16_f16(v_mask1, v_log2e);
1059
+
1060
+ if (has_alibi) {
1061
+ HVX_Vector v_sm0 = hvx_vec_mul_f16_f16(v_mask0_scaled, v_slope0);
1062
+ HVX_Vector v_sm1 = hvx_vec_mul_f16_f16(v_mask1_scaled, v_slope1);
1063
+ my_row_buf0[ci] = Q6_V_vmux_QVV(q_keep0, hvx_vec_add_f16_f16(my_row_buf0[ci], v_sm0), v_neg_inf);
1064
+ my_row_buf1[ci] = Q6_V_vmux_QVV(q_keep1, hvx_vec_add_f16_f16(my_row_buf1[ci], v_sm1), v_neg_inf);
1065
+ } else {
1066
+ my_row_buf0[ci] = Q6_V_vmux_QVV(q_keep0, hvx_vec_add_f16_f16(my_row_buf0[ci], v_mask0_scaled), v_neg_inf);
1067
+ my_row_buf1[ci] = Q6_V_vmux_QVV(q_keep1, hvx_vec_add_f16_f16(my_row_buf1[ci], v_mask1_scaled), v_neg_inf);
1068
+ }
1069
+ } else {
1070
+ if (ne < 64) {
1071
+ my_row_buf0[ci] = Q6_V_vmux_QVV(q_tail_keep, my_row_buf0[ci], v_neg_inf);
1072
+ my_row_buf1[ci] = Q6_V_vmux_QVV(q_tail_keep, my_row_buf1[ci], v_neg_inf);
1073
+ }
1074
+ }
1075
+
1076
+ v_s_rowmax0 = Q6_Vhf_vmax_VhfVhf(v_s_rowmax0, my_row_buf0[ci]);
1077
+ v_s_rowmax1 = Q6_Vhf_vmax_VhfVhf(v_s_rowmax1, my_row_buf1[ci]);
1078
+ }
1079
+
1080
+ v_s_rowmax0 = hvx_vec_reduce_max_f16(v_s_rowmax0);
1081
+ v_s_rowmax1 = hvx_vec_reduce_max_f16(v_s_rowmax1);
1082
+
1083
+ // Splat m_prev[r], m_prev[r+1] from the float per-row accumulators and convert to fp16 vectors
1084
+ HVX_Vector v_m_prev0, v_m_prev1;
1085
+ if (r_vec_off < 32) {
1086
+ HVX_Vector v0 = hvx_vec_repl_f32(Q6_V_vror_VR(m_prev_v0, r_vec_off * 4));
1087
+ v_m_prev0 = hvx_vec_f32_to_f16(v0, v0);
1088
+ if (r + 1 < n_rows_g) {
1089
+ HVX_Vector v1 = hvx_vec_repl_f32(Q6_V_vror_VR(m_prev_v0, (r_vec_off + 1) * 4));
1090
+ v_m_prev1 = hvx_vec_f32_to_f16(v1, v1);
1091
+ } else {
1092
+ v_m_prev1 = Q6_V_vzero();
1093
+ }
1094
+ } else {
1095
+ HVX_Vector v0 = hvx_vec_repl_f32(Q6_V_vror_VR(m_prev_v1, (r_vec_off - 32) * 4));
1096
+ v_m_prev0 = hvx_vec_f32_to_f16(v0, v0);
1097
+ if (r + 1 < n_rows_g) {
1098
+ HVX_Vector v1 = hvx_vec_repl_f32(Q6_V_vror_VR(m_prev_v1, (r_vec_off + 1 - 32) * 4));
1099
+ v_m_prev1 = hvx_vec_f32_to_f16(v1, v1);
1100
+ } else {
1101
+ v_m_prev1 = Q6_V_vzero();
1102
+ }
1103
+ }
1104
+
1105
+ HVX_Vector v_dup_m0 = Q6_Vhf_vmax_VhfVhf(v_m_prev0, v_s_rowmax0);
1106
+ HVX_Vector v_dup_m1 = Q6_Vhf_vmax_VhfVhf(v_m_prev1, v_s_rowmax1);
1107
+
1108
+ // Insert row r, r+1 rowmax into rowmax_acc_v
1109
+ {
1110
+ HVX_VectorPred p_start = Q6_Q_vsetq_R(r_vec_off * 2);
1111
+ HVX_VectorPred p_mid = Q6_Q_vsetq_R((r_vec_off + 1) * 2);
1112
+ HVX_VectorPred p_end = Q6_Q_vsetq2_R((r_vec_off + 2) * 2);
1113
+ HVX_VectorPred p_lane0 = Q6_Q_and_QQn(p_mid, p_start);
1114
+ HVX_VectorPred p_lane1 = Q6_Q_and_QQn(p_end, p_mid);
1115
+ rowmax_acc_v = Q6_V_vmux_QVV(p_lane0, v_dup_m0, rowmax_acc_v);
1116
+ rowmax_acc_v = Q6_V_vmux_QVV(p_lane1, v_dup_m1, rowmax_acc_v);
1117
+ }
1118
+
1119
+ // Compute P = exp(S - m_new)
1120
+ const HVX_Vector v_zero = Q6_V_vzero();
1121
+ HVX_Vector v_p_rowsum0 = v_zero;
1122
+ HVX_Vector v_p_rowsum1 = v_zero;
1123
+
1124
+ for (size_t c = 0; c < kv_rows; c += 64) {
1125
+ size_t ci = c / 64;
1126
+ HVX_Vector v_s_minus_m0 = Q6_Vqf16_vsub_VhfVhf(my_row_buf0[ci], v_dup_m0);
1127
+ HVX_Vector v_s_minus_m1 = Q6_Vqf16_vsub_VhfVhf(my_row_buf1[ci], v_dup_m1);
1128
+
1129
+ HVX_Vector v_p_row0_hf = hvx_vec_exp2_f16(Q6_Vhf_equals_Vqf16(v_s_minus_m0));
1130
+ HVX_Vector v_p_row1_hf = hvx_vec_exp2_f16(Q6_Vhf_equals_Vqf16(v_s_minus_m1));
1131
+ __fp16 * out_dtile = p_st_base + ci * HMX_FP16_TILE_N_ELMS * 2;
1132
+ HVX_Vector * pv_p_out0 = ((HVX_Vector *) out_dtile) + r1 / 2;
1133
+ HVX_Vector * pv_p_out1 = pv_p_out0 + 16;
1134
+
1135
+ HVX_VectorPair vp_p_dual = Q6_W_vshuff_VVR(v_p_row1_hf, v_p_row0_hf, -2);
1136
+ *pv_p_out0 = Q6_V_lo_W(vp_p_dual);
1137
+ *pv_p_out1 = Q6_V_hi_W(vp_p_dual);
1138
+
1139
+ HVX_VectorPair vp_p0 = hvx_vec_f16_to_f32_shuff(v_p_row0_hf);
1140
+ HVX_VectorPair vp_p1 = hvx_vec_f16_to_f32_shuff(v_p_row1_hf);
1141
+
1142
+ v_p_rowsum0 = Q6_Vqf32_vadd_Vqf32Vqf32(v_p_rowsum0, Q6_Vqf32_vadd_VsfVsf(Q6_V_lo_W(vp_p0), Q6_V_hi_W(vp_p0)));
1143
+ v_p_rowsum1 = Q6_Vqf32_vadd_Vqf32Vqf32(v_p_rowsum1, Q6_Vqf32_vadd_VsfVsf(Q6_V_lo_W(vp_p1), Q6_V_hi_W(vp_p1)));
1144
+ }
1145
+
1146
+ HVX_Vector rowsum0_sf = hvx_vec_reduce_sum_f32(Q6_Vsf_equals_Vqf32(v_p_rowsum0));
1147
+ HVX_Vector rowsum1_sf = hvx_vec_reduce_sum_f32(Q6_Vsf_equals_Vqf32(v_p_rowsum1));
1148
+ {
1149
+ HVX_Vector rv0_v = hvx_vec_f32_to_f16(rowsum0_sf, rowsum0_sf);
1150
+ HVX_Vector rv1_v = hvx_vec_f32_to_f16(rowsum1_sf, rowsum1_sf);
1151
+
1152
+ HVX_VectorPred p_start = Q6_Q_vsetq_R(r_vec_off * 2);
1153
+ HVX_VectorPred p_mid = Q6_Q_vsetq_R((r_vec_off + 1) * 2);
1154
+ HVX_VectorPred p_end = Q6_Q_vsetq2_R((r_vec_off + 2) * 2);
1155
+ HVX_VectorPred p_lane0 = Q6_Q_and_QQn(p_mid, p_start);
1156
+ HVX_VectorPred p_lane1 = Q6_Q_and_QQn(p_end, p_mid);
1157
+ rowsum_acc_v = Q6_V_vmux_QVV(p_lane0, rv0_v, rowsum_acc_v);
1158
+ rowsum_acc_v = Q6_V_vmux_QVV(p_lane1, rv1_v, rowsum_acc_v);
1159
+ }
1160
+ }
1161
+
1162
+ // Inline fa_ml_update_and_build_d for this vector (lock-free and in parallel)
1163
+ HVX_VectorPair rowmax_acc_pair = hvx_vec_f16_to_f32(rowmax_acc_v);
1164
+ HVX_Vector v_rowmax_acc_f32_0 = Q6_V_lo_W(rowmax_acc_pair);
1165
+ HVX_Vector v_rowmax_acc_f32_1 = Q6_V_hi_W(rowmax_acc_pair);
1166
+
1167
+ HVX_Vector v_m_curr0 = Q6_Vsf_vmax_VsfVsf(m_prev_v0, v_rowmax_acc_f32_0);
1168
+ HVX_Vector v_m_curr1 = Q6_Vsf_vmax_VsfVsf(m_prev_v1, v_rowmax_acc_f32_1);
1169
+
1170
+ HVX_Vector v_m_diff0 = HVX_OP_SUB_F32(m_prev_v0, v_m_curr0);
1171
+ HVX_Vector v_m_diff1 = HVX_OP_SUB_F32(m_prev_v1, v_m_curr1);
1172
+
1173
+ HVX_Vector v_m_diff_f16 = hvx_vec_f32_to_f16(v_m_diff0, v_m_diff1);
1174
+ HVX_Vector exp_m_diff_f16 = hvx_vec_exp2_f16(v_m_diff_f16);
1175
+
1176
+ HVX_VectorPair exp_m_diff_pair = hvx_vec_f16_to_f32(exp_m_diff_f16);
1177
+ HVX_Vector exp_m_diff0 = Q6_V_lo_W(exp_m_diff_pair);
1178
+ HVX_Vector exp_m_diff1 = Q6_V_hi_W(exp_m_diff_pair);
1179
+
1180
+ HVX_VectorPair rowsum_acc_pair = hvx_vec_f16_to_f32(rowsum_acc_v);
1181
+ HVX_Vector v_rowsum_acc_f32_0 = Q6_V_lo_W(rowsum_acc_pair);
1182
+ HVX_Vector v_rowsum_acc_f32_1 = Q6_V_hi_W(rowsum_acc_pair);
1183
+
1184
+ HVX_Vector v_l_curr0;
1185
+ HVX_Vector v_l_curr1;
1186
+ if (args->kv_start == 0 && factx->sinks != NULL) {
1187
+ // First KV block with sinks: m_prev holds the seeded sink value (not -inf),
1188
+ // so exp_m_diff = exp2(sink - m_curr) is the sink's contribution to the
1189
+ // denominator. l_prev is 0 here, so add exp_m_diff directly instead of
1190
+ // multiplying the (uninitialized) l_prev term.
1191
+ v_l_curr0 = HVX_OP_ADD_F32(exp_m_diff0, v_rowsum_acc_f32_0);
1192
+ v_l_curr1 = HVX_OP_ADD_F32(exp_m_diff1, v_rowsum_acc_f32_1);
1193
+ } else {
1194
+ HVX_Vector l_prev_v0 = factx->vtcm_l_vec[r_vec_idx * 2 + 0];
1195
+ HVX_Vector l_prev_v1 = factx->vtcm_l_vec[r_vec_idx * 2 + 1];
1196
+ v_l_curr0 = HVX_OP_ADD_F32(HVX_OP_MUL_F32(l_prev_v0, exp_m_diff0), v_rowsum_acc_f32_0);
1197
+ v_l_curr1 = HVX_OP_ADD_F32(HVX_OP_MUL_F32(l_prev_v1, exp_m_diff1), v_rowsum_acc_f32_1);
1198
+ }
1199
+
1200
+ factx->vtcm_m_vec[r_vec_idx * 2 + 0] = v_m_curr0;
1201
+ factx->vtcm_m_vec[r_vec_idx * 2 + 1] = v_m_curr1;
1202
+ factx->vtcm_l_vec[r_vec_idx * 2 + 0] = v_l_curr0;
1203
+ factx->vtcm_l_vec[r_vec_idx * 2 + 1] = v_l_curr1;
1204
+
1205
+ // Build diagonal tile D = diag(exp(m_diff))
1206
+ const HVX_Vector v_offsets = *(const HVX_Vector *) d_tile_scatter_offsets;
1207
+ const HVX_VectorPred q_32_mask = Q6_Q_vsetq_R(32 * sizeof(__fp16));
1208
+ HVX_Vector v_exp_m_diff = exp_m_diff_f16;
1209
+
1210
+ size_t t0 = r_vec_idx * 2;
1211
+ if (t0 < args->n_row_tiles) {
1212
+ const HVX_Vector v_content = v_exp_m_diff;
1213
+ __fp16 * out_base = factx->vtcm_d_tiles + t0 * (args->n_row_tiles_g_br + 1) * HMX_FP16_TILE_N_ELMS;
1214
+ Q6_vscatter_QRMVhV(q_32_mask, (size_t) out_base, HMX_FP16_TILE_SIZE - 1, v_offsets, v_content);
1215
+ }
1216
+
1217
+ size_t t1 = r_vec_idx * 2 + 1;
1218
+ if (t1 < args->n_row_tiles) {
1219
+ const HVX_Vector v_content = Q6_V_vror_VR(v_exp_m_diff, 64);
1220
+ __fp16 * out_base = factx->vtcm_d_tiles + t1 * (args->n_row_tiles_g_br + 1) * HMX_FP16_TILE_N_ELMS;
1221
+ Q6_vscatter_QRMVhV(q_32_mask, (size_t) out_base, HMX_FP16_TILE_SIZE - 1, v_offsets, v_content);
1222
+ }
1223
+ }
1224
+ htp_trace_event_stop(tr, HTP_TRACE_EVT_HVX_FA_SFM, (uint16_t) (args->q_start * G + vec_start * 64));
1225
+ }
1226
+
1227
+ static void fa_softmax_thread_nomask(unsigned int n, unsigned int i, void * data) {
1228
+ fa_softmax_impl(n, i, data,
1229
+ /*has_mask=*/false,
1230
+ /*mask_broadcast=*/false,
1231
+ /*is_g1=*/false,
1232
+ /*has_alibi=*/false,
1233
+ /*has_softcap=*/false);
1234
+ }
1235
+
1236
+ static void fa_softmax_thread_mask_broadcast_g1(unsigned int n, unsigned int i, void * data) {
1237
+ fa_softmax_impl(n, i, data,
1238
+ /*has_mask=*/true,
1239
+ /*mask_broadcast=*/true,
1240
+ /*is_g1=*/true,
1241
+ /*has_alibi=*/false,
1242
+ /*has_softcap=*/false);
1243
+ }
1244
+
1245
+ static void fa_softmax_thread_mask_broadcast_gn(unsigned int n, unsigned int i, void * data) {
1246
+ fa_softmax_impl(n, i, data,
1247
+ /*has_mask=*/true,
1248
+ /*mask_broadcast=*/true,
1249
+ /*is_g1=*/false,
1250
+ /*has_alibi=*/false,
1251
+ /*has_softcap=*/false);
1252
+ }
1253
+
1254
+ static void fa_softmax_thread(unsigned int n, unsigned int i, void * data) {
1255
+ fa_softmax_args_t * args = (fa_softmax_args_t *) data;
1256
+ struct hmx_fa_context * factx = args->factx;
1257
+
1258
+ const bool has_mask = (args->mask != NULL);
1259
+ const bool mask_broadcast = factx->mask_broadcast;
1260
+ const bool is_g1 = (args->G == 1);
1261
+ const bool has_alibi = args->has_alibi;
1262
+ const bool has_softcap = (factx->logit_softcap != 0.0f);
1263
+
1264
+ fa_softmax_impl(n, i, data, has_mask, mask_broadcast, is_g1, has_alibi, has_softcap);
1265
+ }
1266
+
1267
+ static __attribute__((noinline)) void fa_build_d_diag_inv_l(struct hmx_fa_context * factx,
1268
+ size_t n_row_tiles,
1269
+ size_t n_row_tiles_g_br) {
1270
+ const HVX_Vector v_offsets = *(const HVX_Vector *) d_tile_scatter_offsets;
1271
+ const HVX_VectorPred q_32_mask = Q6_Q_vsetq_R(32 * sizeof(__fp16));
1272
+ const HVX_Vector one = hvx_vec_splat_f32(1.0f);
1273
+
1274
+ HVX_Vector v_content = Q6_V_vzero();
1275
+ for (size_t i = 0; i < n_row_tiles; ++i) {
1276
+ if ((i % 2) == 0) {
1277
+ HVX_Vector inv_lo = HVX_OP_MUL_F32(one, hvx_vec_inverse_f32(factx->vtcm_l_vec[i]));
1278
+ HVX_Vector inv_hi = (i + 1 < n_row_tiles) ? HVX_OP_MUL_F32(one, hvx_vec_inverse_f32(factx->vtcm_l_vec[i + 1])) : Q6_V_vzero();
1279
+ v_content = hvx_vec_f32_to_f16(inv_lo, inv_hi);
1280
+ } else {
1281
+ v_content = Q6_V_vror_VR(v_content, 64);
1282
+ }
1283
+
1284
+ __fp16 * out_base = factx->vtcm_d_tiles + i * (n_row_tiles_g_br + 1) * HMX_FP16_TILE_N_ELMS;
1285
+ Q6_vscatter_QRMVhV(q_32_mask, (size_t) out_base, HMX_FP16_TILE_SIZE - 1, v_offsets, v_content);
1286
+ }
1287
+ }
1288
+
1289
+ static void fa_phase_softmax_and_build_d(struct hmx_fa_context * factx,
1290
+ fa_softmax_args_t * sargs,
1291
+ size_t n_row_tiles,
1292
+ size_t n_row_tiles_g_br) {
1293
+ worker_pool_context_t wp = factx->octx->ctx->worker_pool;
1294
+ const size_t n_row_vec_cnt = hmx_ceil_div(sargs->n_rows_g, 64);
1295
+
1296
+ worker_callback_t softmax_fn = fa_softmax_thread;
1297
+ if (sargs->mask == NULL && factx->logit_softcap == 0.0f && !sargs->has_alibi) {
1298
+ softmax_fn = fa_softmax_thread_nomask;
1299
+ } else if (sargs->mask != NULL && factx->mask_broadcast && factx->logit_softcap == 0.0f && !sargs->has_alibi) {
1300
+ if (sargs->G == 1) {
1301
+ softmax_fn = fa_softmax_thread_mask_broadcast_g1;
1302
+ } else {
1303
+ softmax_fn = fa_softmax_thread_mask_broadcast_gn;
1304
+ }
1305
+ }
1306
+
1307
+ if (factx->n_threads > 1 && n_row_vec_cnt >= 2) {
1308
+ uint32_t n_use = (uint32_t) hex_smin((size_t) factx->n_threads, n_row_vec_cnt);
1309
+ sargs->thread_div = init_fastdiv_values(n_use);
1310
+ worker_pool_run_func(wp, softmax_fn, sargs, n_use);
1311
+ } else {
1312
+ softmax_fn(1, 0, sargs);
1313
+ }
1314
+ }
1315
+
1316
+ // ============================================================================
1317
+ // HMX job structs and worker functions
1318
+ // ============================================================================
1319
+
1320
+ typedef struct {
1321
+ const __fp16 * q_tiles;
1322
+ const __fp16 * k_tiles;
1323
+ __fp16 * s_tiles;
1324
+ size_t n_row_tiles;
1325
+ size_t n_col_tiles;
1326
+ size_t n_dot_tiles; // DK / 32
1327
+ size_t n_tiles_per_bc;
1328
+ uint8_t * hmx_scales;
1329
+ } hmx_fa_qk_job_t;
1330
+
1331
+ static void hmx_fa_qk_dot_worker(void * data) {
1332
+ hmx_fa_qk_job_t * job = (hmx_fa_qk_job_t *) data;
1333
+ const size_t n_row_tiles = job->n_row_tiles;
1334
+ const size_t n_col_tiles = job->n_col_tiles;
1335
+ const size_t n_dot_tiles = job->n_dot_tiles;
1336
+ const size_t n_tiles_per_bc = job->n_tiles_per_bc;
1337
+ const __fp16 * restrict q_tiles = job->q_tiles;
1338
+ const __fp16 * restrict k_tiles = job->k_tiles;
1339
+ __fp16 * restrict s_tiles = job->s_tiles;
1340
+ __builtin_assume(n_row_tiles > 0);
1341
+ __builtin_assume(n_col_tiles > 0);
1342
+ __builtin_assume(n_dot_tiles > 0);
1343
+
1344
+ asm volatile(HMX_SET_BIAS("%0") :: "r"((unsigned int)job->hmx_scales));
1345
+ const size_t dot_stride = n_dot_tiles * HMX_FP16_TILE_N_ELMS;
1346
+ for (size_t r = 0; r < n_row_tiles; ++r) {
1347
+ const __fp16 * row_tiles = q_tiles + r * dot_stride;
1348
+ const __fp16 * col_tiles = k_tiles;
1349
+ __fp16 * out_tile = s_tiles + r * n_tiles_per_bc * HMX_FP16_TILE_N_ELMS;
1350
+
1351
+ for (size_t c = 0; c < n_col_tiles; ++c) {
1352
+ hmx_fa_qk_dot_tile(row_tiles, col_tiles, out_tile, n_dot_tiles);
1353
+ col_tiles += dot_stride;
1354
+ out_tile += HMX_FP16_TILE_N_ELMS;
1355
+ }
1356
+ }
1357
+ }
1358
+
1359
+ typedef struct {
1360
+ __fp16 * o_curr;
1361
+ const __fp16 * o_prev;
1362
+ const __fp16 * p_tiles;
1363
+ const __fp16 * v_tiles;
1364
+ const __fp16 * d_tiles;
1365
+ uint8_t * hmx_scales;
1366
+ size_t n_row_tiles;
1367
+ size_t n_col_tiles;
1368
+ size_t n_row_tiles_g_br;
1369
+ size_t n_tiles_per_bc;
1370
+ size_t DV;
1371
+ } hmx_fa_o_update_job_t;
1372
+
1373
+ static void hmx_fa_o_update_worker(void * data) {
1374
+ hmx_fa_o_update_job_t * job = (hmx_fa_o_update_job_t *) data;
1375
+ const size_t n_row_tiles = job->n_row_tiles;
1376
+ const size_t n_col_tiles = job->n_col_tiles;
1377
+ const size_t n_row_tiles_g_br = job->n_row_tiles_g_br;
1378
+ const size_t n_tiles_per_bc = job->n_tiles_per_bc;
1379
+ const size_t DV_tiles = job->DV / 32;
1380
+ const __fp16 * restrict d_tiles = job->d_tiles;
1381
+ const __fp16 * restrict p_tiles = job->p_tiles;
1382
+ const __fp16 * restrict v_tiles = job->v_tiles;
1383
+ const __fp16 * restrict o_prev = job->o_prev;
1384
+ __fp16 * restrict o_curr = job->o_curr;
1385
+ __builtin_assume(n_row_tiles > 0);
1386
+ __builtin_assume(n_col_tiles > 0);
1387
+ __builtin_assume(DV_tiles > 0);
1388
+
1389
+ asm volatile(HMX_SET_BIAS("%0") :: "r"((unsigned int)job->hmx_scales));
1390
+ const size_t o_stride = n_row_tiles_g_br * HMX_FP16_TILE_N_ELMS;
1391
+ const size_t v_stride = n_tiles_per_bc * HMX_FP16_TILE_N_ELMS;
1392
+ for (size_t r = 0; r < n_row_tiles; ++r) {
1393
+ const __fp16 * d_diag = d_tiles + r * (n_row_tiles_g_br + 1) * HMX_FP16_TILE_N_ELMS;
1394
+ const __fp16 * p_tile_in = p_tiles + (r * n_tiles_per_bc) * HMX_FP16_TILE_N_ELMS;
1395
+ const __fp16 * o_rc = o_prev + r * HMX_FP16_TILE_N_ELMS;
1396
+ const __fp16 * v_tile_in = v_tiles;
1397
+ __fp16 * o_tile_out = o_curr + r * HMX_FP16_TILE_N_ELMS;
1398
+
1399
+ for (size_t c = 0; c < DV_tiles; ++c) {
1400
+ hmx_fa_o_update_tile(d_diag, o_rc, p_tile_in, v_tile_in, o_tile_out, n_col_tiles);
1401
+ o_rc += o_stride;
1402
+ v_tile_in += v_stride;
1403
+ o_tile_out += o_stride;
1404
+ }
607
1405
  }
608
1406
  }
609
1407
 
1408
+ typedef struct {
1409
+ __fp16 * o_curr; // output (row-major tile layout)
1410
+ const __fp16 * o_prev; // input (column-major tile layout)
1411
+ const __fp16 * d_tiles; // diag(1/l) tiles
1412
+ uint8_t * hmx_scales;
1413
+ size_t n_row_tiles;
1414
+ size_t n_row_tiles_g_br;
1415
+ size_t DV;
1416
+ } hmx_fa_o_norm_job_t;
1417
+
1418
+ static void hmx_fa_o_norm_worker(void * data) {
1419
+ hmx_fa_o_norm_job_t * job = (hmx_fa_o_norm_job_t *) data;
1420
+ const size_t n_row_tiles = job->n_row_tiles;
1421
+ const size_t n_row_tiles_g_br = job->n_row_tiles_g_br;
1422
+ const size_t DV_tiles = job->DV / 32;
1423
+ const __fp16 * restrict d_tiles = job->d_tiles;
1424
+ const __fp16 * restrict o_prev = job->o_prev;
1425
+ __fp16 * restrict o_curr = job->o_curr;
1426
+ __builtin_assume(n_row_tiles > 0);
1427
+ __builtin_assume(DV_tiles > 0);
1428
+
1429
+ asm volatile(HMX_SET_BIAS("%0") :: "r"((unsigned int)job->hmx_scales));
1430
+ const size_t o_stride = n_row_tiles_g_br * HMX_FP16_TILE_N_ELMS;
1431
+ for (size_t r = 0; r < n_row_tiles; ++r) {
1432
+ const __fp16 * d_diag = d_tiles + r * (n_row_tiles_g_br + 1) * HMX_FP16_TILE_N_ELMS;
1433
+ const __fp16 * o_rc = o_prev + r * HMX_FP16_TILE_N_ELMS;
1434
+ __fp16 * o_out = o_curr + r * DV_tiles * HMX_FP16_TILE_N_ELMS;
1435
+
1436
+ for (size_t c = 0; c < DV_tiles; ++c) {
1437
+ hmx_fa_o_norm_tile(d_diag, o_rc, o_out);
1438
+ o_rc += o_stride;
1439
+ o_out += HMX_FP16_TILE_N_ELMS;
1440
+ }
1441
+ }
1442
+ }
1443
+
1444
+ // Populate per-GQA-row ALiBi slopes for a given KV head.
1445
+ static __attribute__((noinline)) void fa_compute_slopes(
1446
+ const struct hmx_fa_context * factx,
1447
+ uint32_t kv_head,
1448
+ size_t n_rows_g) {
1449
+ __fp16 * slopes = factx->vtcm_slopes;
1450
+ if (factx->max_bias == 0.0f) {
1451
+ hvx_splat_f16_a(slopes, 1.0f, n_rows_g);
1452
+ return;
1453
+ }
1454
+
1455
+ const uint32_t G = factx->G;
1456
+ const uint32_t n_head_log2 = factx->n_head_log2;
1457
+ const float m0 = factx->m0;
1458
+ const float m1 = factx->m1;
1459
+
1460
+ __fp16 temp_slopes[512] __attribute__((aligned(128)));
1461
+ if (G <= 32) {
1462
+ // Fast path: Compute G unique slope values in vector registers
1463
+ HVX_Vector v_val = hvx_alibi_slopes(kv_head, G, n_head_log2, m0, m1);
1464
+
1465
+ __fp16 temp_slopes_aligned[64] __attribute__((aligned(128)));
1466
+ hvx_vmem(temp_slopes_aligned) = hvx_vec_f32_to_f16(v_val, Q6_V_vzero());
1467
+
1468
+ for (uint32_t i = 0; i < G; ++i) {
1469
+ temp_slopes[i] = temp_slopes_aligned[i];
1470
+ }
1471
+ } else {
1472
+ // Fallback path: G > 32 (rare configurations)
1473
+ for (uint32_t i = 0; i < G; ++i) {
1474
+ temp_slopes[i] = (__fp16)alibi_slope(kv_head * G + i, n_head_log2, m0, m1);
1475
+ }
1476
+ }
1477
+
1478
+ // Allocate stack buffer to avoid scalar writes to VTCM (which generates L2 misses)
1479
+ __fp16 local_slopes[n_rows_g] __attribute__((aligned(128)));
1480
+ for (size_t r = 0; r < n_rows_g; ++r) {
1481
+ local_slopes[r] = temp_slopes[fastmodulo(r, G, &factx->div_G)];
1482
+ }
1483
+
1484
+ // Copy to VTCM slopes using HVX block copy (both are aligned to 128 bytes)
1485
+ hvx_copy_f16_aa((uint8_t *)slopes, (const uint8_t *)local_slopes, n_rows_g);
1486
+ }
1487
+
1488
+ static void fa_push_mask_dma_gqa(
1489
+ dma_queue * dma,
1490
+ const struct htp_tensor * mask,
1491
+ uint32_t q_start,
1492
+ uint32_t im3,
1493
+ uint32_t kv_start,
1494
+ uint32_t kv_head,
1495
+ uint32_t G,
1496
+ uint32_t m_line_bytes,
1497
+ uint32_t kv_rows,
1498
+ uint32_t n_rows_q,
1499
+ struct hmx_fa_context * factx
1500
+ ) {
1501
+ for (uint32_t g = 0; g < G; ++g) {
1502
+ const uint32_t h_idx = kv_head * G + g;
1503
+ const uint32_t im2 = fastmodulo(h_idx, mask->ne[2], &factx->src3_div2);
1504
+ const uint8_t * ms_src = (const uint8_t *) mask->data + q_start * mask->nb[1] +
1505
+ im2 * mask->nb[2] + im3 * mask->nb[3] + kv_start * sizeof(__fp16);
1506
+ uint8_t * ms_dst = (uint8_t *) factx->vtcm_mask_buf + g * m_line_bytes;
1507
+ dma_queue_push(dma, dma_make_ptr(ms_dst, ms_src), G * m_line_bytes, mask->nb[1], kv_rows * sizeof(__fp16), n_rows_q);
1508
+ }
1509
+ }
1510
+
1511
+ static void fa_pop_mask_dma_gqa(dma_queue * dma, uint32_t G) {
1512
+ for (uint32_t g = 0; g < G; ++g) {
1513
+ dma_queue_pop(dma);
1514
+ }
1515
+ }
1516
+
1517
+ // ============================================================================
1518
+ // Core HMX flash attention algorithm (GQA-merged)
1519
+ // ============================================================================
1520
+
1521
+ int hmx_flash_attn_ext(struct htp_ops_context * octx) {
1522
+ struct htp_thread_trace * tr_hvx = octx->ctx ? &octx->ctx->trace[0] : NULL;
1523
+ struct htp_thread_trace * tr_hmx = octx->ctx ? &octx->ctx->trace[HTP_MAX_NTHREADS] : NULL;
1524
+ const struct htp_tensor * q = octx->src[0];
1525
+ const struct htp_tensor * k = octx->src[1];
1526
+ const struct htp_tensor * v = octx->src[2];
1527
+ const struct htp_tensor * mask = (octx->src[3] && octx->src[3]->data) ? octx->src[3] : NULL;
1528
+ const struct htp_tensor * dst = octx->dst;
1529
+
1530
+ struct htp_context * const ctx = octx->ctx;
1531
+
1532
+ if (!ctx->hmx_enabled) {
1533
+ return HTP_STATUS_NO_SUPPORT;
1534
+ }
1535
+
1536
+ // Dimensions
1537
+ const uint32_t neq0 = q->ne[0]; // head_dim (DK)
1538
+ const uint32_t neq1 = q->ne[1]; // n_tokens
1539
+ const uint32_t neq2 = q->ne[2]; // n_heads
1540
+ const uint32_t neq3 = q->ne[3]; // n_seqs
1541
+
1542
+ const uint32_t nek0 = k->ne[0]; // head_dim
1543
+ const uint32_t nek1 = k->ne[1]; // kv_len
1544
+
1545
+ const uint32_t nev0 = v->ne[0]; // head_dim (DV)
1546
+
1547
+ const uint32_t DK = neq0;
1548
+ const uint32_t DV = nev0;
1549
+
1550
+ // HMX requires head_dim to be multiple of 32
1551
+ if (DK % 32 != 0 || DV % 32 != 0) {
1552
+ return HTP_STATUS_NO_SUPPORT;
1553
+ }
1554
+
1555
+ const struct htp_fa_kernel_params * kparams = (const struct htp_fa_kernel_params *) octx->kernel_params;
1556
+ const uint32_t n_kv_heads = k->ne[2];
1557
+
1558
+ // ======== Build context ========
1559
+ struct hmx_fa_context factx;
1560
+ memset(&factx, 0, sizeof(factx));
1561
+ factx.octx = octx;
1562
+ factx.sinks = octx->src[4]; // NULL if this op has no attention sinks
1563
+ factx.n_threads = kparams->n_threads;
1564
+ factx.DK = DK;
1565
+ factx.DV = DV;
1566
+ factx.n_kv = nek1;
1567
+ factx.n_kv_heads = n_kv_heads;
1568
+ factx.n_heads = neq2;
1569
+ factx.G = kparams->G;
1570
+ factx.div_G = kparams->u.hmx.div_G;
1571
+ factx.neq1 = neq1;
1572
+ factx.Br = kparams->Br;
1573
+ factx.Bc = kparams->Bc;
1574
+ factx.g_br = kparams->u.hmx.g_br;
1575
+ factx.n_kv_blocks = kparams->n_kv_blocks;
1576
+ factx.is_q_fp32 = (kparams->is_q_fp32 != 0);
1577
+ factx.is_dst_fp32 = (kparams->is_dst_fp32 != 0);
1578
+ factx.pipeline = (kparams->u.hmx.pipeline != 0);
1579
+ factx.mask_broadcast = (kparams->u.hmx.mask_broadcast != 0);
1580
+ if (mask) {
1581
+ factx.src3_div2 = kparams->src3_div2;
1582
+ factx.src3_div3 = kparams->src3_div3;
1583
+ }
1584
+
1585
+ if (kparams->logit_softcap == 0.0f) {
1586
+ factx.scale = (__fp16) (kparams->scale * EXP_LOG2E_F); // log2(e)
1587
+ } else {
1588
+ factx.scale = (__fp16) kparams->scale;
1589
+ }
1590
+ factx.max_bias = kparams->max_bias;
1591
+ factx.logit_softcap = (__fp16) (kparams->logit_softcap * EXP_LOG2E_F);
1592
+
1593
+ factx.n_head_log2 = kparams->n_head_log2;
1594
+ factx.m0 = kparams->m0;
1595
+ factx.m1 = kparams->m1;
1596
+
1597
+ const uint32_t Br = factx.Br;
1598
+ const uint32_t Bc = factx.Bc;
1599
+ const uint32_t g_br = factx.g_br;
1600
+ const bool pipeline = factx.pipeline;
1601
+ const uint32_t n_threads = factx.n_threads;
1602
+ const uint32_t G = factx.G;
1603
+
1604
+ // ======== VTCM allocation (GQA-aware) ========
1605
+ // K/V row sizes drive the DMA descriptors (not the VTCM layout) and are used
1606
+ // throughout the KV loop below.
1607
+ const size_t size_k_row = DK * sizeof(__fp16);
1608
+ const size_t size_v_row = DV * sizeof(__fp16);
1609
+ const size_t size_k_row_padded = hex_round_up(size_k_row, 128);
1610
+ const size_t size_v_row_padded = hex_round_up(size_v_row, 128);
1611
+
1612
+ // Build the VTCM layout once (shared with the host estimator) and place every
1613
+ // scratch buffer at its computed offset.
1614
+ struct hmx_fa_vtcm_layout L;
1615
+ hmx_fa_vtcm_layout_build(&L, G, DK, DV, Br, Bc, n_threads, pipeline);
1616
+
1617
+ if (L.total_bytes > ctx->vtcm_size) {
1618
+ return HTP_STATUS_VTCM_TOO_SMALL;
1619
+ }
1620
+
1621
+ uint8_t * const base = ctx->vtcm_base;
1622
+
1623
+ factx.vtcm_q_tiles = VTCM_LAYOUT_PTR(__fp16, base, L.off_q_tiles);
1624
+ factx.vtcm_o_tiles[0] = VTCM_LAYOUT_PTR(__fp16, base, L.off_o_tiles[0]);
1625
+ factx.vtcm_o_tiles[1] = VTCM_LAYOUT_PTR(__fp16, base, L.off_o_tiles[1]);
1626
+ factx.vtcm_k_fp16[0] = VTCM_LAYOUT_PTR(__fp16, base, L.off_k_fp16[0]);
1627
+ factx.vtcm_k_fp16[1] = VTCM_LAYOUT_PTR(__fp16, base, L.off_k_fp16[1]);
1628
+ factx.vtcm_v_fp16[0] = VTCM_LAYOUT_PTR(__fp16, base, L.off_v_fp16[0]);
1629
+ factx.vtcm_v_fp16[1] = VTCM_LAYOUT_PTR(__fp16, base, L.off_v_fp16[1]);
1630
+ factx.vtcm_k_tiles = VTCM_LAYOUT_PTR(__fp16, base, L.off_k_tiles);
1631
+ factx.vtcm_v_tiles[0] = VTCM_LAYOUT_PTR(__fp16, base, L.off_v_tiles[0]);
1632
+ factx.vtcm_v_tiles[1] = VTCM_LAYOUT_PTR_OPTIONAL(__fp16, base, L.off_v_tiles[1], pipeline);
1633
+ factx.vtcm_s_tiles = VTCM_LAYOUT_PTR(__fp16, base, L.off_s_tiles);
1634
+ factx.vtcm_p_tiles = VTCM_LAYOUT_PTR(__fp16, base, L.off_p_tiles);
1635
+ factx.vtcm_d_tiles = VTCM_LAYOUT_PTR(__fp16, base, L.off_d_tiles);
1636
+ factx.vtcm_m_vec = VTCM_LAYOUT_PTR(HVX_Vector, base, L.off_m_vec);
1637
+ factx.vtcm_l_vec = VTCM_LAYOUT_PTR(HVX_Vector, base, L.off_l_vec);
1638
+ factx.vtcm_s_rowmax = VTCM_LAYOUT_PTR(HVX_Vector, base, L.off_s_rowmax);
1639
+ factx.vtcm_p_rowsum = VTCM_LAYOUT_PTR(HVX_Vector, base, L.off_p_rowsum);
1640
+ factx.vtcm_row_bufs = VTCM_LAYOUT_PTR(HVX_Vector, base, L.off_row_bufs);
1641
+ factx.row_buf_stride = L.row_buf_stride;
1642
+ factx.vtcm_hmx_scales_id = VTCM_LAYOUT_PTR(uint8_t, base, L.off_hmx_scales_id);
1643
+ factx.vtcm_hmx_scales_qk = VTCM_LAYOUT_PTR(uint8_t, base, L.off_hmx_scales_qk);
1644
+ factx.vtcm_mask_buf = VTCM_LAYOUT_PTR(__fp16, base, L.off_mask_buf);
1645
+ factx.mask_buf_row_stride = L.mask_buf_row_stride;
1646
+ factx.q_tile_bytes = L.q_tile_bytes;
1647
+ factx.o_tile_bytes = L.o_tile_bytes;
1648
+ factx.col_vec_bytes = L.col_vec_bytes;
1649
+ factx.d_tile_bytes = L.d_tile_bytes;
1650
+ factx.vtcm_slopes = VTCM_LAYOUT_PTR(__fp16, base, L.off_slopes);
1651
+
1652
+ const size_t m_line_bytes = L.m_line_bytes; // used by the mask DMAs in the KV loop
1653
+
1654
+ dma_cache_init(&factx.m_cache, (uint8_t *) factx.vtcm_mask_buf, L.m_buf_slot_bytes, HMX_FA_DMA_CACHE_SIZE);
1655
+
1656
+ // ======== Initialize HMX output scales ========
1657
+ hmx_init_column_scales(factx.vtcm_hmx_scales_id, Q6_V_vsplat_R(0x3c00)); // 1.0
1658
+ hmx_init_column_scales(factx.vtcm_hmx_scales_qk, hvx_vec_splat_f16(factx.scale));
1659
+
1660
+ // ======== Skip compute if profiling ========
1661
+ if (octx->flags & HTP_OPFLAGS_SKIP_COMPUTE) {
1662
+ return HTP_STATUS_OK;
1663
+ }
1664
+
1665
+ // ======== DMA setup ========
1666
+ dma_queue * const dma = ctx->dma[0];
1667
+
1668
+ const size_t n_row_tiles_g_br = g_br / HMX_FP16_TILE_N_ROWS;
1669
+ const size_t n_tiles_per_bc = Bc / HMX_FP16_TILE_N_COLS;
1670
+
1671
+ const size_t qo_element_size = factx.is_q_fp32 ? sizeof(float) : sizeof(__fp16);
1672
+
1673
+ // ======== Reusable job descriptors for pipeline ========
1674
+ hmx_fa_qk_job_t qk_job;
1675
+ hmx_fa_o_update_job_t ou_job;
1676
+ hmx_fa_o_norm_job_t on_job;
1677
+
1678
+ // ======== Main loop ========
1679
+ for (uint32_t ib3 = 0; ib3 < neq3; ++ib3) {
1680
+ const uint32_t im3 = mask ? fastmodulo(ib3, mask->ne[3], &factx.src3_div3) : 0;
1681
+ for (uint32_t q_start = 0; q_start < neq1; q_start += Br) {
1682
+ const uint32_t n_rows_q = hex_smin(Br, neq1 - q_start);
1683
+ const size_t n_rows_g = n_rows_q * G;
1684
+ const size_t g_br_actual = hex_align_up(n_rows_g, HMX_FP16_TILE_N_ROWS);
1685
+ const size_t n_row_tiles = g_br_actual / HMX_FP16_TILE_N_ROWS;
1686
+
1687
+ for (uint32_t kv_head = 0; kv_head < n_kv_heads; ++kv_head) {
1688
+ const uint32_t ik2 = kv_head;
1689
+ const uint32_t ik3 = fastdiv(ib3, &kparams->broadcast_rk3);
1690
+ const uint32_t iv2 = kv_head;
1691
+ const uint32_t iv3 = fastdiv(ib3, &kparams->broadcast_rv3);
1692
+
1693
+ // 1. Push Q DMA (if Q DMA is used)
1694
+ const size_t o_tile_bytes = factx.o_tile_bytes;
1695
+ const bool use_q_dma = (2 * o_tile_bytes >= factx.g_br * factx.DK * (factx.is_q_fp32 ? 4 : 2));
1696
+ if (use_q_dma) {
1697
+ const bool q_transposed = q->nb[1] < q->nb[2];
1698
+ const uint8_t * q_ptr = (const uint8_t *) q->data + q_start * q->nb[1] + (kv_head * factx.G) * q->nb[2] + ib3 * q->nb[3];
1699
+ const size_t el_size = factx.is_q_fp32 ? sizeof(float) : sizeof(__fp16);
1700
+ const size_t q_row_bytes = q_transposed ? n_rows_q * factx.DK * el_size : factx.G * factx.DK * el_size;
1701
+ const size_t src_stride = q_transposed ? q->nb[2] : q->nb[1];
1702
+ const size_t n_rows = q_transposed ? factx.G : n_rows_q;
1703
+ dma_queue_push(dma, dma_make_ptr(factx.vtcm_o_tiles[0], q_ptr), q_row_bytes, hex_smax(src_stride, q_row_bytes), q_row_bytes, n_rows);
1704
+ }
1705
+
1706
+ // 2. Prefetch first KV block
1707
+ if (factx.n_kv_blocks > 0) {
1708
+ const uint32_t kv_rows0 = hex_smin(Bc, nek1);
1709
+
1710
+ const uint8_t * k_src = (const uint8_t *) k->data + ik2 * k->nb[2] + ik3 * k->nb[3];
1711
+ dma_queue_push(dma, dma_make_ptr(factx.vtcm_k_fp16[0], k_src), size_k_row_padded, k->nb[1], size_k_row, kv_rows0);
1712
+
1713
+ const uint8_t * v_src = (const uint8_t *) v->data + iv2 * v->nb[2] + iv3 * v->nb[3];
1714
+ dma_queue_push(dma, dma_make_ptr(factx.vtcm_v_fp16[0], v_src), size_v_row_padded, v->nb[1], size_v_row, kv_rows0);
1715
+ }
1716
+
1717
+ // 3. Pop Q DMA (blocks until Q is loaded)
1718
+ if (use_q_dma) {
1719
+ dma_queue_pop(dma);
1720
+ }
1721
+
1722
+ // ---- Load Q block & Initialize per-block state ----
1723
+ fa_phase_q_load(&factx, q, q_start, kv_head, ib3, n_rows_g);
1724
+
1725
+ __fp16 * o_tile_prev = factx.vtcm_o_tiles[0];
1726
+ __fp16 * o_tile_curr = factx.vtcm_o_tiles[1];
1727
+
1728
+ // ---- KV block loop with DMA double-buffering ----
1729
+ size_t buf_idx = 0;
1730
+
1731
+ htp_trace_event_start(tr_hvx, HTP_TRACE_EVT_HVX_A_PREP, (uint16_t) q_start);
1732
+ fa_compute_slopes(&factx, kv_head, n_rows_g);
1733
+ htp_trace_event_stop(tr_hvx, HTP_TRACE_EVT_HVX_A_PREP, (uint16_t) q_start);
1734
+
1735
+ const size_t k_src_stride = size_k_row_padded / sizeof(__fp16);
1736
+ const size_t v_src_stride = size_v_row_padded / sizeof(__fp16);
1737
+
1738
+ struct hmx_queue * hmx_q = ctx->hmx_queue;
1739
+
1740
+ if (factx.pipeline) {
1741
+ // Pipeline path
1742
+ for (uint32_t kv_blk = 0; kv_blk < factx.n_kv_blocks; ++kv_blk) {
1743
+ const uint32_t kv_start = kv_blk * Bc;
1744
+ const uint32_t kv_rows = hex_smin(Bc, nek1 - kv_start);
1745
+ const size_t n_col_tiles = hmx_ceil_div(kv_rows, HMX_FP16_TILE_N_COLS);
1746
+
1747
+ // Push mask DMA
1748
+ if (mask) {
1749
+ if (__builtin_expect(factx.mask_broadcast, true)) {
1750
+ const uint8_t * ms_src = (const uint8_t *) mask->data + q_start * mask->nb[1] + im3 * mask->nb[3] + kv_start * sizeof(__fp16);
1751
+ dma_cache_push(dma, &factx.m_cache, ms_src, m_line_bytes, mask->nb[1], kv_rows * sizeof(__fp16), n_rows_q);
1752
+ } else {
1753
+ fa_push_mask_dma_gqa(dma, mask, q_start, im3, kv_start, kv_head, G, m_line_bytes, kv_rows, n_rows_q, &factx);
1754
+ }
1755
+ }
1756
+
1757
+ // Prefetch next KV block early
1758
+ if (kv_blk + 1 < factx.n_kv_blocks) {
1759
+ const uint32_t prefetch_start = (kv_blk + 1) * Bc;
1760
+ const uint32_t prefetch_rows = hex_smin(Bc, nek1 - prefetch_start);
1761
+ const size_t prefetch_buf = 1 - buf_idx;
1762
+ const uint8_t * k_prefetch_src = (const uint8_t *) k->data + prefetch_start * k->nb[1] + ik2 * k->nb[2] + ik3 * k->nb[3];
1763
+ dma_queue_push(dma, dma_make_ptr(factx.vtcm_k_fp16[prefetch_buf], k_prefetch_src), size_k_row_padded, k->nb[1], size_k_row, prefetch_rows);
1764
+ const uint8_t * v_prefetch_src = (const uint8_t *) v->data + prefetch_start * v->nb[1] + iv2 * v->nb[2] + iv3 * v->nb[3];
1765
+ dma_queue_push(dma, dma_make_ptr(factx.vtcm_v_fp16[prefetch_buf], v_prefetch_src), size_v_row_padded, v->nb[1], size_v_row, prefetch_rows);
1766
+ }
1767
+
1768
+ // ---- Phase 1: K_int ----
1769
+ if (kv_blk > 0) {
1770
+ ou_job.o_curr = o_tile_curr;
1771
+ ou_job.o_prev = o_tile_prev;
1772
+ ou_job.p_tiles = factx.vtcm_p_tiles;
1773
+ ou_job.v_tiles = factx.vtcm_v_tiles[1 - buf_idx];
1774
+ ou_job.d_tiles = factx.vtcm_d_tiles;
1775
+ ou_job.hmx_scales = factx.vtcm_hmx_scales_id;
1776
+ ou_job.n_row_tiles = n_row_tiles;
1777
+ ou_job.n_col_tiles = hmx_ceil_div(hex_smin(Bc, nek1 - (kv_blk - 1) * Bc), HMX_FP16_TILE_N_COLS);
1778
+ ou_job.n_row_tiles_g_br = n_row_tiles_g_br;
1779
+ ou_job.n_tiles_per_bc = n_tiles_per_bc;
1780
+ ou_job.DV = DV;
1781
+ hmx_queue_push(hmx_q, hmx_queue_make_desc(hmx_fa_o_update_worker, &ou_job));
1782
+ }
1783
+
1784
+ // Wait for current K DMA and interleave
1785
+ void * curr_k = dma_queue_pop(dma).dst;
1786
+ fa_phase_k_interleave(&factx, kv_rows, k_src_stride, curr_k, kv_start);
1787
+
1788
+ // ---- Phase 2: qk_dot ----
1789
+ qk_job.q_tiles = factx.vtcm_q_tiles;
1790
+ qk_job.k_tiles = factx.vtcm_k_tiles;
1791
+ qk_job.s_tiles = factx.vtcm_s_tiles;
1792
+ qk_job.n_row_tiles = n_row_tiles;
1793
+ qk_job.n_col_tiles = n_col_tiles;
1794
+ qk_job.n_dot_tiles = DK / 32;
1795
+ qk_job.n_tiles_per_bc = n_tiles_per_bc;
1796
+ qk_job.hmx_scales = factx.vtcm_hmx_scales_qk;
1797
+ hmx_queue_push(hmx_q, hmx_queue_make_desc(hmx_fa_qk_dot_worker, &qk_job));
1798
+
1799
+ // Wait for current V DMA and interleave
1800
+ void * curr_v = dma_queue_pop(dma).dst;
1801
+ fa_phase_v_interleave(&factx, kv_rows, v_src_stride, curr_v, factx.vtcm_v_tiles[buf_idx], n_tiles_per_bc, kv_start);
1802
+
1803
+ if (kv_blk > 0) {
1804
+ hmx_queue_pop(hmx_q);
1805
+ hex_swap_ptr((void **) &o_tile_curr, (void **) &o_tile_prev);
1806
+ }
1807
+
1808
+ hmx_queue_pop(hmx_q);
1809
+
1810
+ // ---- Phase 3: softmax + build_D ----
1811
+ __fp16 * current_mask_vtcm = NULL;
1812
+ if (mask) {
1813
+ if (__builtin_expect(factx.mask_broadcast, true)) {
1814
+ current_mask_vtcm = (__fp16 *) dma_queue_pop(dma).dst;
1815
+ } else {
1816
+ fa_pop_mask_dma_gqa(dma, G);
1817
+ current_mask_vtcm = factx.vtcm_mask_buf;
1818
+ }
1819
+ }
1820
+
1821
+ fa_softmax_args_t sargs;
1822
+ memset(&sargs, 0, sizeof(sargs));
1823
+ sargs.factx = &factx;
1824
+ sargs.kv_rows = kv_rows;
1825
+ sargs.n_rows_g = n_rows_g;
1826
+ sargs.n_col_tiles = n_col_tiles;
1827
+ sargs.n_tiles_per_bc = n_tiles_per_bc;
1828
+ sargs.n_row_tiles = n_row_tiles;
1829
+ sargs.n_row_tiles_g_br = n_row_tiles_g_br;
1830
+ sargs.Bc = Bc;
1831
+ sargs.G = G;
1832
+ sargs.kv_head = kv_head;
1833
+ sargs.kv_start = kv_start;
1834
+ sargs.q_start = q_start;
1835
+ sargs.ib3 = ib3;
1836
+ sargs.has_alibi = (factx.max_bias != 0.0f);
1837
+ sargs.mask = mask;
1838
+ sargs.mask_vtcm = current_mask_vtcm;
1839
+ sargs.mask_vtcm_row_stride = factx.mask_buf_row_stride;
1840
+ sargs.slopes = factx.vtcm_slopes;
1841
+ fa_phase_softmax_and_build_d(&factx, &sargs, n_row_tiles, n_row_tiles_g_br);
1842
+
1843
+ buf_idx = 1 - buf_idx;
1844
+ }
1845
+
1846
+ // Epilogue
1847
+ if (factx.n_kv_blocks > 0) {
1848
+ const uint32_t last_blk = factx.n_kv_blocks - 1;
1849
+ const size_t last_cols = hmx_ceil_div(hex_smin(Bc, nek1 - last_blk * Bc), HMX_FP16_TILE_N_COLS);
1850
+ ou_job.o_curr = o_tile_curr;
1851
+ ou_job.o_prev = o_tile_prev;
1852
+ ou_job.p_tiles = factx.vtcm_p_tiles;
1853
+ ou_job.v_tiles = factx.vtcm_v_tiles[1 - buf_idx];
1854
+ ou_job.d_tiles = factx.vtcm_d_tiles;
1855
+ ou_job.hmx_scales = factx.vtcm_hmx_scales_id;
1856
+ ou_job.n_row_tiles = n_row_tiles;
1857
+ ou_job.n_col_tiles = last_cols;
1858
+ ou_job.n_row_tiles_g_br = n_row_tiles_g_br;
1859
+ ou_job.n_tiles_per_bc = n_tiles_per_bc;
1860
+ ou_job.DV = DV;
1861
+ hmx_queue_push(hmx_q, hmx_queue_make_desc(hmx_fa_o_update_worker, &ou_job));
1862
+ hmx_queue_pop(hmx_q);
1863
+
1864
+ hex_swap_ptr((void **) &o_tile_curr, (void **) &o_tile_prev);
1865
+ }
1866
+
1867
+ } else {
1868
+ // Fallback path
1869
+ for (uint32_t kv_blk = 0; kv_blk < factx.n_kv_blocks; ++kv_blk) {
1870
+ const uint32_t kv_start = kv_blk * Bc;
1871
+ const uint32_t kv_rows = hex_smin(Bc, nek1 - kv_start);
1872
+ const size_t n_col_tiles = hmx_ceil_div(kv_rows, HMX_FP16_TILE_N_COLS);
1873
+
1874
+ if (mask) {
1875
+ if (__builtin_expect(factx.mask_broadcast, true)) {
1876
+ const uint8_t * ms_src = (const uint8_t *) mask->data + q_start * mask->nb[1] + im3 * mask->nb[3] + kv_start * sizeof(__fp16);
1877
+ dma_cache_push(dma, &factx.m_cache, ms_src, m_line_bytes, mask->nb[1], kv_rows * sizeof(__fp16), n_rows_q);
1878
+ } else {
1879
+ fa_push_mask_dma_gqa(dma, mask, q_start, im3, kv_start, kv_head, G, m_line_bytes, kv_rows, n_rows_q, &factx);
1880
+ }
1881
+ }
1882
+
1883
+ if (kv_blk + 1 < factx.n_kv_blocks) {
1884
+ const uint32_t prefetch_start = (kv_blk + 1) * Bc;
1885
+ const uint32_t prefetch_rows = hex_smin(Bc, nek1 - prefetch_start);
1886
+ const size_t prefetch_buf = 1 - buf_idx;
1887
+ const uint8_t * k_prefetch_src = (const uint8_t *) k->data + prefetch_start * k->nb[1] + ik2 * k->nb[2] + ik3 * k->nb[3];
1888
+ dma_queue_push(dma, dma_make_ptr(factx.vtcm_k_fp16[prefetch_buf], k_prefetch_src), size_k_row_padded, k->nb[1], size_k_row, prefetch_rows);
1889
+ const uint8_t * v_prefetch_src = (const uint8_t *) v->data + prefetch_start * v->nb[1] + iv2 * v->nb[2] + iv3 * v->nb[3];
1890
+ dma_queue_push(dma, dma_make_ptr(factx.vtcm_v_fp16[prefetch_buf], v_prefetch_src), size_v_row_padded, v->nb[1], size_v_row, prefetch_rows);
1891
+ }
1892
+
1893
+ // Wait for current K DMA and interleave
1894
+ void * curr_k = dma_queue_pop(dma).dst;
1895
+ fa_phase_k_interleave(&factx, kv_rows, k_src_stride, curr_k, kv_start);
1896
+
1897
+ {
1898
+ qk_job.q_tiles = factx.vtcm_q_tiles;
1899
+ qk_job.k_tiles = factx.vtcm_k_tiles;
1900
+ qk_job.s_tiles = factx.vtcm_s_tiles;
1901
+ qk_job.n_row_tiles = n_row_tiles;
1902
+ qk_job.n_col_tiles = n_col_tiles;
1903
+ qk_job.n_dot_tiles = (size_t) (DK / 32);
1904
+ qk_job.n_tiles_per_bc = n_tiles_per_bc;
1905
+ qk_job.hmx_scales = factx.vtcm_hmx_scales_qk;
1906
+
1907
+ hmx_queue_push(ctx->hmx_queue, hmx_queue_make_desc(hmx_fa_qk_dot_worker, &qk_job));
1908
+ hmx_queue_pop(ctx->hmx_queue);
1909
+ }
1910
+
1911
+ // Wait for current V DMA and interleave
1912
+ void * curr_v = dma_queue_pop(dma).dst;
1913
+ fa_phase_v_interleave(&factx, kv_rows, v_src_stride, curr_v, factx.vtcm_v_tiles[0], n_tiles_per_bc, kv_start);
1914
+
1915
+ // ---- Phase 3: softmax + build_D ----
1916
+ __fp16 * current_mask_vtcm = NULL;
1917
+ if (mask) {
1918
+ if (__builtin_expect(factx.mask_broadcast, true)) {
1919
+ current_mask_vtcm = (__fp16 *) dma_queue_pop(dma).dst;
1920
+ } else {
1921
+ fa_pop_mask_dma_gqa(dma, G);
1922
+ current_mask_vtcm = factx.vtcm_mask_buf;
1923
+ }
1924
+ }
1925
+
1926
+ fa_softmax_args_t sargs;
1927
+ memset(&sargs, 0, sizeof(sargs));
1928
+ sargs.factx = &factx;
1929
+ sargs.kv_rows = kv_rows;
1930
+ sargs.n_rows_g = n_rows_g;
1931
+ sargs.n_col_tiles = n_col_tiles;
1932
+ sargs.n_tiles_per_bc = n_tiles_per_bc;
1933
+ sargs.n_row_tiles = n_row_tiles;
1934
+ sargs.n_row_tiles_g_br = n_row_tiles_g_br;
1935
+ sargs.Bc = Bc;
1936
+ sargs.G = G;
1937
+ sargs.kv_head = kv_head;
1938
+ sargs.kv_start = kv_start;
1939
+ sargs.q_start = q_start;
1940
+ sargs.ib3 = ib3;
1941
+ sargs.has_alibi = (factx.max_bias != 0.0f);
1942
+ sargs.mask = mask;
1943
+ sargs.mask_vtcm = current_mask_vtcm;
1944
+ sargs.mask_vtcm_row_stride = factx.mask_buf_row_stride;
1945
+ sargs.slopes = factx.vtcm_slopes;
1946
+ fa_phase_softmax_and_build_d(&factx, &sargs, n_row_tiles, n_row_tiles_g_br);
1947
+
1948
+ {
1949
+ ou_job.o_curr = o_tile_curr;
1950
+ ou_job.o_prev = o_tile_prev;
1951
+ ou_job.p_tiles = factx.vtcm_p_tiles;
1952
+ ou_job.v_tiles = factx.vtcm_v_tiles[0];
1953
+ ou_job.d_tiles = factx.vtcm_d_tiles;
1954
+ ou_job.hmx_scales = factx.vtcm_hmx_scales_id;
1955
+ ou_job.n_row_tiles = n_row_tiles;
1956
+ ou_job.n_col_tiles = n_col_tiles;
1957
+ ou_job.n_row_tiles_g_br = n_row_tiles_g_br;
1958
+ ou_job.n_tiles_per_bc = n_tiles_per_bc;
1959
+ ou_job.DV = DV;
1960
+
1961
+ hmx_queue_push(ctx->hmx_queue, hmx_queue_make_desc(hmx_fa_o_update_worker, &ou_job));
1962
+ hmx_queue_pop(ctx->hmx_queue);
1963
+
1964
+ hex_swap_ptr((void **) &o_tile_curr, (void **) &o_tile_prev);
1965
+ }
1966
+
1967
+ buf_idx = 1 - buf_idx;
1968
+ }
1969
+ }
1970
+
1971
+ // ---- Final normalization ----
1972
+ {
1973
+ htp_trace_event_start(tr_hvx, HTP_TRACE_EVT_HVX_O_PROC, (uint16_t) q_start);
1974
+ fa_build_d_diag_inv_l(&factx, n_row_tiles, n_row_tiles_g_br);
1975
+ htp_trace_event_stop(tr_hvx, HTP_TRACE_EVT_HVX_O_PROC, (uint16_t) q_start);
1976
+
1977
+ on_job.o_curr = o_tile_curr;
1978
+ on_job.o_prev = o_tile_prev;
1979
+ on_job.d_tiles = factx.vtcm_d_tiles;
1980
+ on_job.hmx_scales = factx.vtcm_hmx_scales_id;
1981
+ on_job.n_row_tiles = n_row_tiles;
1982
+ on_job.n_row_tiles_g_br = n_row_tiles_g_br;
1983
+ on_job.DV = DV;
1984
+ hmx_queue_push(ctx->hmx_queue, hmx_queue_make_desc(hmx_fa_o_norm_worker, &on_job));
1985
+ hmx_queue_pop(ctx->hmx_queue);
1986
+ }
1987
+
1988
+ // ---- Store O block ----
1989
+ fa_phase_o_store(&factx, dst, o_tile_curr, q_start, kv_head, ib3, n_rows_g);
1990
+ }
1991
+ }
1992
+ }
1993
+
1994
+ return HTP_STATUS_OK;
1995
+ }
1996
+
610
1997
  int op_flash_attn_ext(struct htp_ops_context * octx) {
611
- const struct htp_tensor * q = &octx->src0;
612
- const struct htp_tensor * k = &octx->src1;
613
- const struct htp_tensor * v = &octx->src2;
614
- const struct htp_tensor * mask = (octx->src3.data) ? &octx->src3 : NULL;
615
- const struct htp_tensor * dst = &octx->dst;
1998
+ const struct htp_tensor * q = octx->src[0];
1999
+ const struct htp_tensor * k = octx->src[1];
2000
+ const struct htp_tensor * v = octx->src[2];
2001
+ const struct htp_tensor * mask = octx->src[3];
2002
+ const struct htp_tensor * dst = octx->dst;
616
2003
 
617
2004
  // Check support
618
2005
  if ((q->type != HTP_TYPE_F16 && q->type != HTP_TYPE_F32) || k->type != HTP_TYPE_F16 || v->type != HTP_TYPE_F16) {
619
2006
  return HTP_STATUS_NO_SUPPORT;
620
2007
  }
621
2008
 
2009
+ const struct htp_fa_kernel_params * kparams = (const struct htp_fa_kernel_params *) octx->kernel_params;
2010
+
2011
+ if (kparams->kernel_type == HTP_FA_KERNEL_UNSUPPORTED) {
2012
+ return HTP_STATUS_NO_SUPPORT;
2013
+ }
2014
+
2015
+ if (kparams->kernel_type == HTP_FA_KERNEL_HMX) {
2016
+ return hmx_flash_attn_ext(octx);
2017
+ }
2018
+
622
2019
  struct htp_fa_context factx;
623
2020
  factx.octx = octx;
624
2021
 
625
2022
  factx.t_start = HAP_perf_get_qtimer_count();
626
2023
 
627
- factx.src0_div21 = init_fastdiv_values(q->ne[2] * q->ne[1]);
628
- factx.src0_div1 = init_fastdiv_values(q->ne[1]);
2024
+ factx.src0_div21 = kparams->u.hvx.src0_div21;
2025
+ factx.src0_div1 = kparams->u.hvx.src0_div1;
629
2026
 
630
- factx.broadcast_rk2 = init_fastdiv_values(q->ne[2]/k->ne[2]);
631
- factx.broadcast_rk3 = init_fastdiv_values(q->ne[3]/k->ne[3]);
632
- factx.broadcast_rv2 = init_fastdiv_values(q->ne[2]/v->ne[2]);
633
- factx.broadcast_rv3 = init_fastdiv_values(q->ne[3]/v->ne[3]);
2027
+ factx.broadcast_rk2 = kparams->broadcast_rk2;
2028
+ factx.broadcast_rk3 = kparams->broadcast_rk3;
2029
+ factx.broadcast_rv2 = kparams->broadcast_rv2;
2030
+ factx.broadcast_rv3 = kparams->broadcast_rv3;
634
2031
 
635
2032
  if (mask) {
636
- factx.src3_div2 = init_fastdiv_values(mask->ne[2]);
637
- factx.src3_div3 = init_fastdiv_values(mask->ne[3]);
2033
+ factx.src3_div2 = kparams->src3_div2;
2034
+ factx.src3_div3 = kparams->src3_div3;
638
2035
  }
639
2036
 
640
- factx.is_q_fp32 = (q->type == HTP_TYPE_F32);
641
- factx.size_q_row_padded = hex_round_up(q->ne[0] * (factx.is_q_fp32 ? 4 : 2), 128);
642
- factx.size_k_row_padded = hex_round_up(k->ne[0] * sizeof(__fp16), 128);
643
- factx.size_v_row_padded = hex_round_up(v->ne[0] * sizeof(__fp16), 128);
2037
+ factx.is_q_fp32 = (kparams->is_q_fp32 != 0);
2038
+ factx.size_q_row_padded = kparams->u.hvx.size_q_row_padded;
2039
+ factx.size_k_row_padded = kparams->u.hvx.size_k_row_padded;
2040
+ factx.size_v_row_padded = kparams->u.hvx.size_v_row_padded;
644
2041
 
645
2042
  size_t size_q_block = factx.size_q_row_padded * 1; // single row for now
646
2043
  factx.size_k_block = factx.size_k_row_padded * FLASH_ATTN_BLOCK_SIZE;
647
2044
  factx.size_v_block = factx.size_v_row_padded * FLASH_ATTN_BLOCK_SIZE;
648
2045
  factx.size_m_block = hex_round_up(FLASH_ATTN_BLOCK_SIZE * sizeof(__fp16), 128);
649
2046
 
650
- factx.n_blocks = (k->ne[1] + FLASH_ATTN_BLOCK_SIZE - 1) / FLASH_ATTN_BLOCK_SIZE;
2047
+ factx.n_blocks = kparams->n_kv_blocks;
651
2048
 
652
- float scale = 1.0f;
653
- float max_bias = 0.0f;
654
- float logit_softcap = 0.0f;
2049
+ factx.scale = kparams->scale;
2050
+ factx.max_bias = kparams->max_bias;
2051
+ factx.logit_softcap = (__fp16) kparams->logit_softcap;
655
2052
 
656
- memcpy(&scale, (float *) octx->op_params + 0, sizeof(float));
657
- memcpy(&max_bias, (float *) octx->op_params + 1, sizeof(float));
658
- memcpy(&logit_softcap, (float *) octx->op_params + 2, sizeof(float));
2053
+ factx.n_head_log2 = kparams->n_head_log2;
2054
+ factx.m0 = kparams->m0;
2055
+ factx.m1 = kparams->m1;
659
2056
 
660
- if (logit_softcap != 0.0f) {
661
- scale /= logit_softcap;
2057
+ const uint32_t n_head = q->ne[2];
2058
+ if (n_head > 512) {
2059
+ return HTP_STATUS_NO_SUPPORT;
2060
+ }
2061
+ for (uint32_t h = 0; h < n_head; ++h) {
2062
+ factx.slopes[h] = (__fp16) ((kparams->max_bias > 0.0f) ? alibi_slope(h, factx.n_head_log2, factx.m0, factx.m1) : 1.0f);
662
2063
  }
663
-
664
- factx.scale = scale;
665
- factx.max_bias = max_bias;
666
- factx.logit_softcap = logit_softcap;
667
-
668
- uint32_t n_head = q->ne[2];
669
- factx.n_head_log2 = 1u << (uint32_t) floor(log2(n_head));
670
- factx.m0 = powf(2.0f, -(max_bias ) / factx.n_head_log2);
671
- factx.m1 = powf(2.0f, -(max_bias / 2.0f) / factx.n_head_log2);
672
2064
 
673
2065
  // total rows in q
674
- const uint32_t neq0 = q->ne[0];
675
- const uint32_t neq1 = q->ne[1];
676
- const uint32_t neq2 = q->ne[2];
677
- const uint32_t neq3 = q->ne[3];
678
-
679
- factx.qrows = neq1*neq2*neq3;
680
- factx.qrows_per_thread = (factx.qrows + octx->n_threads - 1) / octx->n_threads;
2066
+ factx.qrows = kparams->qrows;
2067
+ factx.qrows_per_thread = kparams->qrows_per_thread;
681
2068
 
682
2069
  size_t size_vkq_acc = hex_round_up(v->ne[0] * sizeof(float), 128); // VKQ32
683
2070
 
684
- octx->src0_spad.size_per_thread = size_q_block * 1;
685
- octx->src1_spad.size_per_thread = factx.size_k_block * 2;
686
- octx->src2_spad.size_per_thread = factx.size_v_block * 2;
687
- octx->src3_spad.size_per_thread = mask ? factx.size_m_block * 2 : 0;
688
- octx->dst_spad.size_per_thread = size_vkq_acc;
2071
+ factx.size_q_block = size_q_block;
2072
+ factx.size_vkq_acc = size_vkq_acc;
689
2073
 
690
- octx->src0_spad.size = octx->src0_spad.size_per_thread * octx->n_threads;
691
- octx->src1_spad.size = octx->src1_spad.size_per_thread * octx->n_threads;
692
- octx->src2_spad.size = octx->src2_spad.size_per_thread * octx->n_threads;
693
- octx->src3_spad.size = octx->src3_spad.size_per_thread * octx->n_threads;
694
- octx->dst_spad.size = octx->dst_spad.size_per_thread * octx->n_threads;
2074
+ uint8_t * vtcm_cur = octx->ctx->vtcm_base;
695
2075
 
696
- size_t total_spad = octx->src0_spad.size + octx->src1_spad.size + octx->src2_spad.size + octx->src3_spad.size + octx->dst_spad.size;
2076
+ factx.spad_q = vtcm_seq_alloc(&vtcm_cur, size_q_block * octx->n_threads);
2077
+ factx.spad_k = vtcm_seq_alloc(&vtcm_cur, factx.size_k_block * 2 * octx->n_threads);
2078
+ factx.spad_v = vtcm_seq_alloc(&vtcm_cur, factx.size_v_block * 2 * octx->n_threads);
2079
+ factx.spad_m = vtcm_seq_alloc(&vtcm_cur, (mask ? factx.size_m_block * HVX_FA_DMA_CACHE_SIZE : 0) * octx->n_threads);
2080
+ factx.spad_a = vtcm_seq_alloc(&vtcm_cur, size_vkq_acc * octx->n_threads);
697
2081
 
698
- if (octx->ctx->vtcm_size < total_spad) {
2082
+ if ((size_t) (vtcm_cur - octx->ctx->vtcm_base) > octx->ctx->vtcm_size) {
699
2083
  return HTP_STATUS_VTCM_TOO_SMALL;
700
2084
  }
701
2085
 
702
- octx->src0_spad.data = octx->ctx->vtcm_base;
703
- octx->src1_spad.data = octx->src0_spad.data + octx->src0_spad.size;
704
- octx->src2_spad.data = octx->src1_spad.data + octx->src1_spad.size;
705
- octx->src3_spad.data = octx->src2_spad.data + octx->src2_spad.size;
706
- octx->dst_spad.data = octx->src3_spad.data + octx->src3_spad.size;
707
-
708
2086
  if (!(octx->flags & HTP_OPFLAGS_SKIP_COMPUTE)) {
709
2087
  worker_pool_run_func(octx->ctx->worker_pool, flash_attn_ext_f16_thread, &factx, octx->n_threads);
710
2088
  }