char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
eafe15a5e
char/aliceai-t5-moe
1#pragma clang diagnostic ignored "-Wunused-variable" 2#pragma clang diagnostic ignored "-Wunused-function" 3#pragma clang diagnostic ignored "-Wunused-but-set-variable" 4 5#include <HAP_farf.h> 6#include <HAP_perf.h> 7 8#include <math.h> 9#include <string.h> 10 11#include "hex-dma.h" 12#include "hex-fastdiv.h" 13#include "hvx-exp.h" 14#include "hvx-sigmoid.h" 15#include "hvx-utils.h" 16#include "unary-ops.h" 17 18#define GGML_COMMON_DECL_C 19#include "ggml-common.h" 20#include "htp-ctx.h" 21#include "htp-ops.h" 22#include "htp-tensor.h" 23#include "htp-vtcm.h" 24#include "hex-profile.h" 25 26struct htp_unary_context { 27struct htp_ops_context * octx ; 28const struct htp_unary_kernel_params * kparams ; 29 30const uint8_t * data_src0 ; 31const uint8_t * data_src1 ;// weight/scale tensor for RMS_NORM_MUL 32uint8_t * data_dst ; 33 34size_t src0_data_row_size ;// actual data bytes per row 35size_t src1_data_row_size ; 36size_t dst_data_row_size ;// actual data bytes per row 37 38size_t src0_row_size_aligned ; 39size_t src1_row_size_aligned ; 40size_t dst_row_size_aligned ; 41 42size_t src0_vtcm_half_size ; 43size_t src1_vtcm_half_size ; 44size_t dst_vtcm_half_size ; 45 46uint32_t block ; 47uint32_t src0_nrows ; 48uint32_t src0_nrows_per_thread ; 49uint32_t row_start ; 50uint32_t nc ; 51uint32_t col_tile ;// tiled mode 52bool broadcast_weight ; 53 54uint8_t * vtcm_src0 ; 55uint8_t * vtcm_src1 ; 56uint8_t * vtcm_dst ; 57 58size_t vtcm_src0_size_per_thread ; 59size_t vtcm_src1_size_per_thread ; 60size_t vtcm_dst_size_per_thread ; 61}; 62 63// Convert flat row index to DDR byte offset using the tensor's actual strides. 64// ir = i1 + ne1*(i2 + ne2*i3) => offset = i1*nb1 + i2*nb2 + i3*nb3 65static inline size_t unary_row_offset (uint32_t ir , 66uint32_t ne1 ,uint32_t ne2 , 67const struct fastdiv_values * div_ne1 , 68const struct fastdiv_values * div_ne2 , 69const struct fastdiv_values * div_ne12 , 70size_t nb1 ,size_t nb2 ,size_t nb3 ) { 71const uint32_t i1 = fastmodulo (ir ,ne1 ,div_ne1 ); 72const uint32_t ir_div_ne1 = fastdiv (ir ,div_ne1 ); 73const uint32_t i2 = fastmodulo (ir_div_ne1 ,ne2 ,div_ne2 ); 74const uint32_t i3 = fastdiv (ir ,div_ne12 ); 75return i1 * nb1 + i2 * nb2 + i3 * nb3 ; 76} 77 78// Safe DMA block size from row `ir`: clamp to the tighter dim-1 slice 79// boundary of src and dst so the nb1 stride stays valid for all rows. 80static inline uint32_t unary_block_size (uint32_t ir , 81uint32_t end_row , 82uint32_t block , 83bool src_contig , 84bool dst_contig , 85uint32_t ne1 , 86const struct fastdiv_values * div_ne1 ) { 87uint32_t limit = MIN (block ,end_row - ir ); 88 89if (!src_contig || !dst_contig ) { 90const uint32_t slice_end = (fastdiv (ir ,div_ne1 )+ 1 )* ne1 ; 91limit = MIN (limit ,slice_end - ir ); 92 } 93 94return limit ; 95} 96 97#define htp_unary_preamble \ 98 const uint32_t ne00 = src->ne[0]; \ 99 const uint32_t ne01 = src->ne[1]; \ 100 const uint32_t ne02 = src->ne[2]; \ 101 const uint32_t ne03 = src->ne[3]; \ 102 \ 103 const uint32_t ne0 = dst->ne[0]; \ 104 const uint32_t ne1 = dst->ne[1]; \ 105 const uint32_t ne2 = dst->ne[2]; \ 106 const uint32_t ne3 = dst->ne[3]; \ 107 \ 108 const uint32_t nb00 = src->nb[0]; \ 109 const uint32_t nb01 = src->nb[1]; \ 110 const uint32_t nb02 = src->nb[2]; \ 111 const uint32_t nb03 = src->nb[3]; \ 112 \ 113 const uint32_t nb0 = dst->nb[0]; \ 114 const uint32_t nb1 = dst->nb[1]; \ 115 const uint32_t nb2 = dst->nb[2]; \ 116 const uint32_t nb3 = dst->nb[3]; 117 118#define htp_unary_op_preamble \ 119 int32_t * op_params = uctx->octx->op_params; \ 120 const uint32_t ne0 = uctx->nc; \ 121 const size_t src0_row_size_aligned = uctx->src0_row_size_aligned; \ 122 const size_t dst_row_size_aligned = uctx->dst_row_size_aligned; 123 124static void scale_f32 (const float * restrictsrc , 125float * restrictdst , 126const uint32_t num_rows , 127const struct htp_unary_context * uctx ) { 128htp_unary_op_preamble ; 129float scale = 0.f ; 130float bias = 0.f ; 131memcpy (& scale ,& op_params [0 ],sizeof (float )); 132memcpy (& bias ,& op_params [1 ],sizeof (float )); 133 134for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 135const uint8_t * restrictsrc_local = (const uint8_t * )src + (ir * src0_row_size_aligned ); 136uint8_t * restrictdst_local = (uint8_t * )dst + (ir * dst_row_size_aligned ); 137 138hvx_scale_offset_f32_aa ((uint8_t * )dst_local , (const uint8_t * )src_local ,ne0 ,scale ,bias ); 139 } 140} 141 142static void clamp_f32 (const float * restrictsrc , 143float * restrictdst , 144const uint32_t num_rows , 145const struct htp_unary_context * uctx ) { 146htp_unary_op_preamble ; 147float min = 0.f ; 148float max = 0.f ; 149memcpy (& min ,& op_params [0 ],sizeof (float )); 150memcpy (& max ,& op_params [1 ],sizeof (float )); 151 152for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 153const uint8_t * restrictsrc_local = (const uint8_t * )src + (ir * src0_row_size_aligned ); 154uint8_t * restrictdst_local = (uint8_t * )dst + (ir * dst_row_size_aligned ); 155 156hvx_clamp_scalar_f32 (dst_local ,src_local ,min ,max ,ne0 ); 157 } 158} 159 160static void leaky_relu_f32 (const float * restrictsrc , 161float * restrictdst , 162const uint32_t num_rows , 163const struct htp_unary_context * uctx ) { 164htp_unary_op_preamble ; 165float negative_slope = 0.f ; 166memcpy (& negative_slope ,& op_params [0 ],sizeof (float )); 167 168for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 169const uint8_t * restrictsrc_local = (const uint8_t * )src + (ir * src0_row_size_aligned ); 170uint8_t * restrictdst_local = (uint8_t * )dst + (ir * dst_row_size_aligned ); 171 172hvx_leaky_relu_scalar_f32 (dst_local ,src_local ,negative_slope ,ne0 ); 173 } 174} 175 176static void rms_norm_f32 (const float * restrictsrc , 177float * restrictdst , 178const uint32_t num_rows , 179const struct htp_unary_context * uctx ) { 180htp_unary_op_preamble ; 181float epsilon = 0.f ; 182memcpy (& epsilon ,op_params ,sizeof (float )); 183 184for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 185const uint8_t * restrictsrc_local = (const uint8_t * )src + (ir * src0_row_size_aligned ); 186uint8_t * restrictdst_local = (uint8_t * )dst + (ir * dst_row_size_aligned ); 187 188hvx_fast_rms_norm_f32 ((const uint8_t * )src_local , (uint8_t * )dst_local ,ne0 ,epsilon ); 189 } 190} 191 192static void rms_norm_mul_f32 (const float * restrictsrc , 193const float * restrictweight , 194float * restrictdst , 195const uint32_t num_rows , 196const struct htp_unary_context * uctx ) { 197htp_unary_op_preamble ; 198float epsilon = 0.f ; 199memcpy (& epsilon ,op_params ,sizeof (float )); 200 201for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 202const uint8_t * restrictsrc_local = (const uint8_t * )src + (ir * src0_row_size_aligned ); 203const uint8_t * restrictw_local = (const uint8_t * )weight + (uctx -> broadcast_weight ?0 :ir * uctx -> src1_row_size_aligned ); 204uint8_t * restrictdst_local = (uint8_t * )dst + (ir * dst_row_size_aligned ); 205 206hvx_fast_rms_norm_mul_f32 (src_local ,w_local ,dst_local ,ne0 ,epsilon ); 207 } 208} 209 210static void norm_f32 (const float * restrictsrc , 211float * restrictdst , 212const uint32_t num_rows , 213const struct htp_unary_context * uctx ) { 214htp_unary_op_preamble ; 215float epsilon = 0.f ; 216memcpy (& epsilon ,op_params ,sizeof (float )); 217 218for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 219const uint8_t * restrictsrc_local = (const uint8_t * )src + (ir * src0_row_size_aligned ); 220uint8_t * restrictdst_local = (uint8_t * )dst + (ir * dst_row_size_aligned ); 221 222hvx_fast_norm_f32 ((const uint8_t * )src_local , (uint8_t * )dst_local ,ne0 ,epsilon ); 223 } 224} 225 226static void sqr_f32 (const float * restrictsrc , 227float * restrictdst , 228const uint32_t num_rows , 229const struct htp_unary_context * uctx ) { 230htp_unary_op_preamble ; 231 232for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 233const uint8_t * restrictsrc_local = (const uint8_t * )src + (ir * src0_row_size_aligned ); 234uint8_t * restrictdst_local = (uint8_t * )dst + (ir * dst_row_size_aligned ); 235 236hvx_sqr_f32_aa ((uint8_t * )dst_local , (const uint8_t * )src_local ,ne0 ); 237 } 238} 239 240static void sqrt_f32 (const float * restrictsrc , 241float * restrictdst , 242const uint32_t num_rows , 243const struct htp_unary_context * uctx ) { 244htp_unary_op_preamble ; 245 246for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 247const uint8_t * restrictsrc_local = (const uint8_t * )src + (ir * src0_row_size_aligned ); 248uint8_t * restrictdst_local = (uint8_t * )dst + (ir * dst_row_size_aligned ); 249 250hvx_sqrt_f32_aa ((uint8_t * )dst_local , (const uint8_t * )src_local ,ne0 ); 251 } 252} 253 254static void scale_f16 (const _Float16 * restrictsrc , 255_Float16 * restrictdst , 256const uint32_t num_rows , 257const struct htp_unary_context * uctx ) { 258htp_unary_op_preamble ; 259float scale = 0.f ; 260float bias = 0.f ; 261memcpy (& scale ,& op_params [0 ],sizeof (float )); 262memcpy (& bias ,& op_params [1 ],sizeof (float )); 263 264for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 265const uint8_t * restrictsrc_local = (const uint8_t * )src + (ir * src0_row_size_aligned ); 266uint8_t * restrictdst_local = (uint8_t * )dst + (ir * dst_row_size_aligned ); 267 268hvx_scale_offset_f16_aa ((uint8_t * )dst_local , (const uint8_t * )src_local ,ne0 ,scale ,bias ); 269 } 270} 271 272static void clamp_f16 (const _Float16 * restrictsrc , 273_Float16 * restrictdst , 274const uint32_t num_rows , 275const struct htp_unary_context * uctx ) { 276htp_unary_op_preamble ; 277float min = 0.f ; 278float max = 0.f ; 279memcpy (& min ,& op_params [0 ],sizeof (float )); 280memcpy (& max ,& op_params [1 ],sizeof (float )); 281 282for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 283const uint8_t * restrictsrc_local = (const uint8_t * )src + (ir * src0_row_size_aligned ); 284uint8_t * restrictdst_local = (uint8_t * )dst + (ir * dst_row_size_aligned ); 285 286hvx_clamp_scalar_f16 (dst_local ,src_local , (_Float16 )min , (_Float16 )max ,ne0 ); 287 } 288} 289 290static void rms_norm_f16 (const _Float16 * restrictsrc , 291_Float16 * restrictdst , 292const uint32_t num_rows , 293const struct htp_unary_context * uctx ) { 294htp_unary_op_preamble ; 295float epsilon = 0.f ; 296memcpy (& epsilon ,op_params ,sizeof (float )); 297 298for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 299const uint8_t * restrictsrc_local = (const uint8_t * )src + (ir * src0_row_size_aligned ); 300uint8_t * restrictdst_local = (uint8_t * )dst + (ir * dst_row_size_aligned ); 301 302hvx_fast_rms_norm_f16 ((const uint8_t * )src_local , (uint8_t * )dst_local ,ne0 ,epsilon ); 303 } 304} 305 306static void norm_f16 (const _Float16 * restrictsrc , 307_Float16 * restrictdst , 308const uint32_t num_rows , 309const struct htp_unary_context * uctx ) { 310htp_unary_op_preamble ; 311float epsilon = 0.f ; 312memcpy (& epsilon ,op_params ,sizeof (float )); 313 314for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 315const uint8_t * restrictsrc_local = (const uint8_t * )src + (ir * src0_row_size_aligned ); 316uint8_t * restrictdst_local = (uint8_t * )dst + (ir * dst_row_size_aligned ); 317 318hvx_fast_norm_f16 ((const uint8_t * )src_local , (uint8_t * )dst_local ,ne0 ,epsilon ); 319 } 320} 321 322static void sqr_f16 (const _Float16 * restrictsrc , 323_Float16 * restrictdst , 324const uint32_t num_rows , 325const struct htp_unary_context * uctx ) { 326htp_unary_op_preamble ; 327 328for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 329const uint8_t * restrictsrc_local = (const uint8_t * )src + (ir * src0_row_size_aligned ); 330uint8_t * restrictdst_local = (uint8_t * )dst + (ir * dst_row_size_aligned ); 331 332hvx_sqr_f16_aa ((uint8_t * )dst_local , (const uint8_t * )src_local ,ne0 ); 333 } 334} 335 336static void sqrt_f16 (const _Float16 * restrictsrc , 337_Float16 * restrictdst , 338const uint32_t num_rows , 339const struct htp_unary_context * uctx ) { 340htp_unary_op_preamble ; 341 342for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 343const uint8_t * restrictsrc_local = (const uint8_t * )src + (ir * src0_row_size_aligned ); 344uint8_t * restrictdst_local = (uint8_t * )dst + (ir * dst_row_size_aligned ); 345 346hvx_sqrt_f16_aa ((uint8_t * )dst_local , (const uint8_t * )src_local ,ne0 ); 347 } 348} 349 350static void abs_f16 (const _Float16 * restrictsrc , 351_Float16 * restrictdst , 352const uint32_t num_rows , 353const struct htp_unary_context * uctx ) { 354htp_unary_op_preamble ; 355 356for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 357const uint8_t * restrictsrc_local = (const uint8_t * )src + (ir * src0_row_size_aligned ); 358uint8_t * restrictdst_local = (uint8_t * )dst + (ir * dst_row_size_aligned ); 359 360hvx_abs_f16_aa ((uint8_t * )dst_local , (const uint8_t * )src_local ,ne0 ); 361 } 362} 363 364static void log_f16 (const _Float16 * restrictsrc , 365_Float16 * restrictdst , 366const uint32_t num_rows , 367const struct htp_unary_context * uctx ) { 368htp_unary_op_preamble ; 369 370for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 371const uint8_t * restrictsrc_local = (const uint8_t * )src + (ir * src0_row_size_aligned ); 372uint8_t * restrictdst_local = (uint8_t * )dst + (ir * dst_row_size_aligned ); 373 374hvx_log_f16_aa ((uint8_t * )dst_local , (const uint8_t * )src_local ,ne0 ); 375 } 376} 377 378static void l2_norm_f16 (const _Float16 * restrictsrc , 379_Float16 * restrictdst , 380const uint32_t num_rows , 381const struct htp_unary_context * uctx ) { 382htp_unary_op_preamble ; 383float epsilon = 0.f ; 384memcpy (& epsilon ,op_params ,sizeof (float )); 385 386for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 387const uint8_t * restrictsrc_f = (const uint8_t * )src + (ir * src0_row_size_aligned ); 388uint8_t * restrictdst_f = (uint8_t * )dst + (ir * dst_row_size_aligned ); 389 390hvx_fast_l2_norm_f16 ((const uint8_t * )src_f , (uint8_t * )dst_f ,ne0 ,epsilon ); 391 } 392} 393 394static void neg_f32 (const float * restrictsrc , 395float * restrictdst , 396const uint32_t num_rows , 397const struct htp_unary_context * uctx ) { 398htp_unary_op_preamble ; 399 400for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 401const uint8_t * restrictsrc_local = (const uint8_t * )src + (ir * src0_row_size_aligned ); 402uint8_t * restrictdst_local = (uint8_t * )dst + (ir * dst_row_size_aligned ); 403 404hvx_scale_f32_aa (dst_local ,src_local ,ne0 ,-1.0f ); 405 } 406} 407 408static void exp_f32 (const float * restrictsrc , 409float * restrictdst , 410const uint32_t num_rows , 411const struct htp_unary_context * uctx ) { 412htp_unary_op_preamble ; 413 414for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 415const uint8_t * restrictsrc_local = (const uint8_t * )src + (ir * src0_row_size_aligned ); 416uint8_t * restrictdst_local = (uint8_t * )dst + (ir * dst_row_size_aligned ); 417 418hvx_exp_f32 (dst_local ,src_local ,ne0 , false); 419 } 420} 421 422static void sigmoid_f32 (const float * restrictsrc , 423float * restrictdst , 424const uint32_t num_rows , 425const struct htp_unary_context * uctx ) { 426htp_unary_op_preamble ; 427 428for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 429const uint8_t * restrictsrc_local = (const uint8_t * )src + (ir * src0_row_size_aligned ); 430uint8_t * restrictdst_local = (uint8_t * )dst + (ir * dst_row_size_aligned ); 431 432hvx_sigmoid_f32_aa (dst_local ,src_local ,ne0 ); 433 } 434} 435 436// silu(x) = x * sigmoid(x) 437static void silu_f32 (const float * restrictsrc , 438float * restrictdst , 439const uint32_t num_rows , 440const struct htp_unary_context * uctx ) { 441htp_unary_op_preamble ; 442 443for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 444const uint8_t * restrictsrc_local = (const uint8_t * )src + (ir * src0_row_size_aligned ); 445uint8_t * restrictdst_local = (uint8_t * )dst + (ir * dst_row_size_aligned ); 446 447hvx_sigmoid_f32_aa (dst_local ,src_local ,ne0 ); 448hvx_mul_f32_aaa (dst_local ,src_local ,dst_local ,ne0 ); 449 } 450} 451 452// gelu(x) = x * sigmoid(1.702 * x) (quick/sigmoid approximation, matches CPU GELU_QUICK reference) 453static void gelu_f32 (const float * restrictsrc , 454float * restrictdst , 455const uint32_t num_rows , 456const struct htp_unary_context * uctx ) { 457htp_unary_op_preamble ; 458 459for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 460const uint8_t * restrictsrc_local = (const uint8_t * )src + (ir * src0_row_size_aligned ); 461uint8_t * restrictdst_local = (uint8_t * )dst + (ir * dst_row_size_aligned ); 462 463hvx_mul_scalar_f32 (dst_local ,src_local ,1.702f ,ne0 ); 464hvx_sigmoid_f32_aa (dst_local ,dst_local ,ne0 ); 465hvx_mul_f32_aaa (dst_local ,src_local ,dst_local ,ne0 ); 466 } 467} 468 469static void tri_f32 (const float * restrictsrc , 470float * restrictdst , 471const uint32_t num_rows , 472const uint32_t ir , 473const struct htp_unary_context * uctx ) { 474htp_unary_op_preamble ; 475const int32_t ttype = op_params [0 ]; 476const HVX_Vector zero = hvx_vec_splat_f32 (0.0f ); 477const uint32_t nvec = ne0 /VLEN_FP32 ; 478const uint32_t nloe = ne0 %VLEN_FP32 ; 479 480const uint32_t ne01 = uctx -> octx -> src [0 ]-> ne [1 ]; 481 482for (uint32_t b = 0 ;b < num_rows ;b ++ ) { 483const uint32_t abs_row = ir + b ; 484const uint32_t i01 = abs_row %ne01 ; 485 486const HVX_Vector * restrictv_src = (const HVX_Vector * ) ((const uint8_t * )src + b * src0_row_size_aligned ); 487HVX_Vector * restrictv_dst = (HVX_Vector * ) ((uint8_t * )dst + b * dst_row_size_aligned ); 488 489uint32_t boundary ; 490int keep_left ; 491switch (ttype ) { 492case 0 :boundary = i01 ;keep_left = 0 ;break ;// keep col >= row 493case 1 :boundary = i01 + 1 ;keep_left = 0 ;break ;// keep col > row 494case 2 :boundary = i01 + 1 ;keep_left = 1 ;break ;// keep col <= row 495case 3 :boundary = i01 ;keep_left = 1 ;break ;// keep col < row 496default :boundary = 0 ;keep_left = 0 ;break ; 497 } 498if (boundary > ne0 )boundary = ne0 ; 499 500// Full HVX vectors - each starts at a 128-byte aligned offset 501for (uint32_t i = 0 ;i < nvec ;i ++ ) { 502const uint32_t vec_start = i * VLEN_FP32 ; 503const uint32_t vec_end = vec_start + VLEN_FP32 ; 504if (keep_left ) { 505if (vec_end <=boundary ) { 506v_dst [i ]= v_src [i ]; 507 }else if (vec_start >=boundary ) { 508v_dst [i ]= zero ; 509 }else { 510HVX_VectorPred mask = Q6_Q_vsetq_R ((boundary - vec_start )* sizeof (float )); 511v_dst [i ]= Q6_V_vmux_QVV (mask ,v_src [i ],zero ); 512 } 513 }else { 514if (vec_end <=boundary ) { 515v_dst [i ]= zero ; 516 }else if (vec_start >=boundary ) { 517v_dst [i ]= v_src [i ]; 518 }else { 519HVX_VectorPred mask = Q6_Q_vsetq_R ((boundary - vec_start )* sizeof (float )); 520v_dst [i ]= Q6_V_vmux_QVV (mask ,zero ,v_src [i ]); 521 } 522 } 523 } 524 525// Tail elements (row_elems not a multiple of VLEN_FP32) 526if (nloe > 0 ) { 527const uint32_t abs_start = nvec * VLEN_FP32 ; 528const uint32_t abs_end = abs_start + nloe ; 529HVX_Vector tail_val ; 530if (keep_left ) { 531if (abs_end <=boundary ) { 532tail_val = v_src [nvec ]; 533 }else if (abs_start >=boundary ) { 534tail_val = zero ; 535 }else { 536HVX_VectorPred mask = Q6_Q_vsetq_R ((boundary - abs_start )* sizeof (float )); 537tail_val = Q6_V_vmux_QVV (mask ,v_src [nvec ],zero ); 538 } 539 }else { 540if (abs_end <=boundary ) { 541tail_val = zero ; 542 }else if (abs_start >=boundary ) { 543tail_val = v_src [nvec ]; 544 }else { 545HVX_VectorPred mask = Q6_Q_vsetq_R ((boundary - abs_start )* sizeof (float )); 546tail_val = Q6_V_vmux_QVV (mask ,zero ,v_src [nvec ]); 547 } 548 } 549hvx_vec_store_a (& v_dst [nvec ],nloe * sizeof (float ),tail_val ); 550 } 551 } 552} 553 554static void softplus_f32 (const float * restrictsrc , 555float * restrictdst , 556const uint32_t num_rows , 557const struct htp_unary_context * uctx ) { 558htp_unary_op_preamble ; 559// softplus(x) = log(1 + exp(x)) 560// Match CPU reference: ggml_compute_softplus_f32() in ggml-impl.h 561for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 562const float * restrictsrc_f = (const float * )((const uint8_t * )src + (ir * src0_row_size_aligned )); 563float * restrictdst_f = (float * )((uint8_t * )dst + (ir * dst_row_size_aligned )); 564 565for (uint32_t i = 0 ;i < ne0 ;i ++ ) { 566float x = src_f [i ]; 567// For x > 20: softplus(x) ~ x (avoids exp overflow) 568dst_f [i ]= (x > 20.0f ) ?x :logf (1.0f + expf (x )); 569 } 570 } 571} 572 573static void l2_norm_f32 (const float * restrictsrc , 574float * restrictdst , 575const uint32_t num_rows , 576const struct htp_unary_context * uctx ) { 577htp_unary_op_preamble ; 578float epsilon = 0.f ; 579memcpy (& epsilon ,op_params ,sizeof (float )); 580 581for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 582const float * restrictsrc_f = (const float * )((const uint8_t * )src + (ir * src0_row_size_aligned )); 583float * restrictdst_f = (float * )((uint8_t * )dst + (ir * dst_row_size_aligned )); 584 585hvx_fast_l2_norm_f32 ((const uint8_t * )src_f , (uint8_t * )dst_f ,ne0 ,epsilon ); 586 } 587} 588 589static void tanh_f32 (const float * restrictsrc , 590float * restrictdst , 591const uint32_t num_rows , 592const struct htp_unary_context * uctx ) { 593htp_unary_op_preamble ; 594 595for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 596const uint8_t * restrictsrc_local = (const uint8_t * )src + (ir * src0_row_size_aligned ); 597uint8_t * restrictdst_local = (uint8_t * )dst + (ir * dst_row_size_aligned ); 598 599hvx_tanh_f32_aa (dst_local ,src_local ,ne0 ); 600 } 601} 602 603static void abs_f32 (const float * restrictsrc , 604float * restrictdst , 605const uint32_t num_rows , 606const struct htp_unary_context * uctx ) { 607htp_unary_op_preamble ; 608 609for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 610const uint8_t * restrictsrc_local = (const uint8_t * )src + (ir * src0_row_size_aligned ); 611uint8_t * restrictdst_local = (uint8_t * )dst + (ir * dst_row_size_aligned ); 612 613hvx_abs_f32_aa (dst_local ,src_local ,ne0 ); 614 } 615} 616 617static void relu_f32 (const float * restrictsrc , 618float * restrictdst , 619const uint32_t num_rows , 620const struct htp_unary_context * uctx ) { 621htp_unary_op_preamble ; 622 623for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 624const uint8_t * restrictsrc_local = (const uint8_t * )src + (ir * src0_row_size_aligned ); 625uint8_t * restrictdst_local = (uint8_t * )dst + (ir * dst_row_size_aligned ); 626 627hvx_max_scalar_f32 (dst_local ,src_local ,0.0f ,ne0 ); 628 } 629} 630 631static void log_f32 (const float * restrictsrc , 632float * restrictdst , 633const uint32_t num_rows , 634const struct htp_unary_context * uctx ) { 635htp_unary_op_preamble ; 636 637for (uint32_t ir = 0 ;ir < num_rows ;ir ++ ) { 638const uint8_t * restrictsrc_local = (const uint8_t * )src + (ir * src0_row_size_aligned ); 639uint8_t * restrictdst_local = (uint8_t * )dst + (ir * dst_row_size_aligned ); 640 641hvx_log_f32_aa (dst_local ,src_local ,ne0 ); 642 } 643} 644 645#define DEFINE_UNARY_TASK_IMPL (NAME ,TYPE ,SUFFIX ,IS_RMS_NORM_MUL ,IS_TRI ,CORE_EXPR ) \ 646static void unary_task_##SUFFIX##_##NAME(unsigned int nth, unsigned int ith, void * data) { \ 647 const struct htp_unary_context * uctx = (const struct htp_unary_context *) data; \ 648 struct htp_ops_context * octx = uctx->octx; \ 649 const struct htp_tensor * src = octx->src[0]; \ 650 const struct htp_tensor * dst = octx->dst; \ 651 struct htp_thread_trace * tr = &octx->ctx->trace[ith]; \ 652 \ 653 htp_unary_preamble; \ 654 \ 655 int32_t * op_params = octx->op_params; \ 656 uint32_t src0_nrows_per_thread = uctx->src0_nrows_per_thread; \ 657 \ 658 const size_t src0_data_row_size = uctx->src0_data_row_size; \ 659 const size_t dst_data_row_size = uctx->dst_data_row_size; \ 660 \ 661 const size_t src0_row_size_aligned = uctx->src0_row_size_aligned; \ 662 const size_t dst_row_size_aligned = uctx->dst_row_size_aligned; \ 663 \ 664 const uint32_t src0_nrows = uctx->src0_nrows; \ 665 const uint32_t src0_start_row = uctx->row_start + src0_nrows_per_thread * ith; \ 666 const uint32_t src0_end_row = MIN(src0_start_row + src0_nrows_per_thread, uctx->row_start + src0_nrows); \ 667 \ 668 if (src0_start_row >= src0_end_row) { \ 669 return; \ 670 } \ 671 \ 672 const uint8_t * restrict data_src = uctx->data_src0; \ 673 const uint8_t * restrict data_src1 = uctx->data_src1; \ 674 uint8_t * restrict data_dst = uctx->data_dst; \ 675 \ 676 const struct htp_tensor * src1 = (IS_RMS_NORM_MUL) ? octx->src[1] : NULL; \ 677 const uint32_t nb11 = src1 ? src1->nb[1] : 0; \ 678 const uint32_t nb12 = src1 ? src1->nb[2] : 0; \ 679 const uint32_t nb13 = src1 ? src1->nb[3] : 0; \ 680 const uint32_t nb11_bc = (src1 && src1->ne[1] > 1) ? nb11 : 0; \ 681 const uint32_t nb12_bc = (src1 && src1->ne[2] > 1) ? nb12 : 0; \ 682 const uint32_t nb13_bc = (src1 && src1->ne[3] > 1) ? nb13 : 0; \ 683 const bool src1_contig = src1 ? ((nb12 == (size_t)ne01 * nb11) && (nb13 == (size_t)ne02 * nb12)) : false; \ 684 \ 685 uint8_t * src0_vtcm_data = uctx->vtcm_src0 + (ith * uctx->vtcm_src0_size_per_thread); \ 686 uint8_t * src1_vtcm_data = uctx->vtcm_src1 ? (uctx->vtcm_src1 + (ith * uctx->vtcm_src1_size_per_thread)) : NULL;\ 687 uint8_t * dst_vtcm_data = uctx->vtcm_dst + (ith * uctx->vtcm_dst_size_per_thread); \ 688 \ 689 size_t src0_vtcm_half_size = uctx->src0_vtcm_half_size; \ 690 size_t src1_vtcm_half_size = uctx->src1_vtcm_half_size; \ 691 size_t dst_vtcm_half_size = uctx->dst_vtcm_half_size; \ 692 \ 693 const bool src0_contig = (nb02 == (size_t)ne01 * nb01) && \ 694 (nb03 == (size_t)ne02 * nb02); \ 695 const bool dst_contig = (nb2 == (size_t)ne1 * nb1) && \ 696 (nb3 == (size_t)ne2 * nb2); \ 697 \ 698 const struct fastdiv_values * div_ne01 = &uctx->kparams->div_ne01; \ 699 const struct fastdiv_values * div_ne02 = &uctx->kparams->div_ne02; \ 700 const struct fastdiv_values * div_ne012 = &uctx->kparams->div_ne012; \ 701 \ 702 const bool src1_needs_row_clip = (IS_RMS_NORM_MUL) && !uctx->broadcast_weight && !src1_contig; \ 703 const bool block_src0_contig = src0_contig && !src1_needs_row_clip; \ 704 const bool block_dst_contig = dst_contig && !src1_needs_row_clip; \ 705 \ 706 const uint32_t src0_max_block = block_src0_contig ? uctx->block : MIN((uint32_t)uctx->block, ne01); \ 707 const uint32_t dst_max_block = block_dst_contig ? uctx->block : MIN((uint32_t)uctx->block, ne1); \ 708 const uint32_t BLOCK = MIN(src0_max_block, dst_max_block); \ 709 if (BLOCK == 0) { \ 710 FARF(ERROR, "unary-" #SUFFIX " : current VTCM reservation %zu is too small, needed at least %zu\n", \ 711 uctx->vtcm_src0_size_per_thread, src0_row_size_aligned); \ 712 return; \ 713 } \ 714 \ 715 dma_queue * dma_queue = octx->ctx->dma[ith]; \ 716 \ 717 if ((IS_RMS_NORM_MUL) && uctx->broadcast_weight) { \ 718 dma_queue_push(dma_queue, dma_make_ptr(src1_vtcm_data, data_src1), \ 719 uctx->src1_row_size_aligned, 0, uctx->src1_data_row_size, 1); \ 720 dma_queue_flush(dma_queue); \ 721 } \ 722 \ 723 for (uint32_t ir = src0_start_row, vtcm_idx = 0; ir < src0_end_row && vtcm_idx < 2; vtcm_idx++) { \ 724 const uint32_t block_size = unary_block_size(ir, src0_end_row, BLOCK, block_src0_contig, block_dst_contig, \ 725 ne01, div_ne01); \ 726 \ 727 dma_queue_push(dma_queue, \ 728 dma_make_ptr(data_dst, dst_vtcm_data + (vtcm_idx * dst_vtcm_half_size)), \ 729 nb1, dst_row_size_aligned, dst_data_row_size, 0); \ 730 \ 731 const size_t src0_off = src0_contig ? (ir * nb01) : \ 732 unary_row_offset(ir, ne01, ne02, div_ne01, div_ne02, div_ne012, nb01, nb02, nb03); \ 733 dma_queue_push(dma_queue, \ 734 dma_make_ptr(src0_vtcm_data + (vtcm_idx * src0_vtcm_half_size), data_src + src0_off), \ 735 src0_row_size_aligned, nb01, src0_data_row_size, block_size); \ 736 \ 737 if ((IS_RMS_NORM_MUL) && !uctx->broadcast_weight) { \ 738 const size_t src1_off = src1_contig ? (ir * nb11) : \ 739 unary_row_offset(ir, ne01, ne02, div_ne01, div_ne02, div_ne012, nb11_bc, nb12_bc, nb13_bc); \ 740 dma_queue_push(dma_queue, \ 741 dma_make_ptr(src1_vtcm_data + (vtcm_idx * src1_vtcm_half_size), data_src1 + src1_off), \ 742 uctx->src1_row_size_aligned, nb11, uctx->src1_data_row_size, block_size); \ 743 } \ 744 \ 745 ir += block_size; \ 746 } \ 747 \ 748 for (uint32_t ir = src0_start_row; ir < src0_end_row; ) { \ 749 const uint32_t block_size = unary_block_size(ir, src0_end_row, BLOCK, block_src0_contig, block_dst_contig, \ 750 ne01, div_ne01); \ 751 \ 752 TYPE * dst_vtcm = (TYPE *) dma_queue_pop(dma_queue).src; \ 753 TYPE * src0_vtcm = (TYPE *) dma_queue_pop(dma_queue).dst; \ 754 TYPE * src1_vtcm = NULL; \ 755 if ((IS_RMS_NORM_MUL) && !uctx->broadcast_weight) { \ 756 src1_vtcm = (TYPE *) dma_queue_pop(dma_queue).dst; \ 757 } \ 758 \ 759 htp_trace_event_start(tr, HTP_TRACE_EVT_HVX_COMP, ir); \ 760 CORE_EXPR; \ 761 htp_trace_event_stop(tr, HTP_TRACE_EVT_HVX_COMP, ir); \ 762 \ 763 const size_t dst_off = dst_contig ? (ir * nb1) : \ 764 unary_row_offset(ir, ne1, ne2, div_ne01, div_ne02, div_ne012, nb1, nb2, nb3); \ 765 dma_queue_push(dma_queue, \ 766 dma_make_ptr(data_dst + dst_off, dst_vtcm), \ 767 nb1, dst_row_size_aligned, dst_data_row_size, block_size); \ 768 \ 769 const uint32_t next_ir = ir + block_size; \ 770 if (next_ir < src0_end_row) { \ 771 const uint32_t next_block_size = unary_block_size(next_ir, src0_end_row, BLOCK, block_src0_contig, \ 772 block_dst_contig, ne01, div_ne01); \ 773 const uint32_t pref_ir = next_ir + next_block_size; \ 774 if (pref_ir < src0_end_row) { \ 775 const uint32_t pref_block_size = unary_block_size(pref_ir, src0_end_row, BLOCK, block_src0_contig, \ 776 block_dst_contig, ne01, div_ne01); \ 777 const size_t src0_pref_off = src0_contig ? (pref_ir * nb01) : \ 778 unary_row_offset(pref_ir, ne01, ne02, div_ne01, div_ne02, div_ne012, nb01, nb02, nb03); \ 779 dma_queue_push(dma_queue, \ 780 dma_make_ptr(src0_vtcm, data_src + src0_pref_off), \ 781 src0_row_size_aligned, nb01, src0_data_row_size, pref_block_size); \ 782 \ 783 if ((IS_RMS_NORM_MUL) && !uctx->broadcast_weight) { \ 784 const size_t src1_pref_off = src1_contig ? (pref_ir * nb11) : \ 785 unary_row_offset(pref_ir, ne01, ne02, div_ne01, div_ne02, div_ne012, nb11_bc, nb12_bc, \ 786 nb13_bc); \ 787 dma_queue_push(dma_queue, \ 788 dma_make_ptr(src1_vtcm, data_src1 + src1_pref_off), \ 789 uctx->src1_row_size_aligned, nb11, uctx->src1_data_row_size, pref_block_size); \ 790 } \ 791 } \ 792 } \ 793 ir += block_size; \ 794 } \ 795 \ 796 dma_queue_flush(dma_queue); \ 797} 798 799// F32 unary task: row-block DMA/VTCM plumbing, float-typed VTCM buffers. 800#define DEFINE_UNARY_TASK (NAME ,IS_RMS_NORM_MUL ,IS_TRI ,CORE_EXPR ) \ 801 DEFINE_UNARY_TASK_IMPL(NAME, float, f32, IS_RMS_NORM_MUL, IS_TRI, CORE_EXPR) 802 803DEFINE_UNARY_TASK (norm , false, false,norm_f32 (src0_vtcm ,dst_vtcm ,block_size ,uctx )) 804DEFINE_UNARY_TASK (rms_norm , false, false,rms_norm_f32 (src0_vtcm ,dst_vtcm ,block_size ,uctx )) 805DEFINE_UNARY_TASK (rms_norm_mul , true, false,rms_norm_mul_f32 (src0_vtcm ,uctx -> broadcast_weight ? (const float * )src1_vtcm_data :src1_vtcm ,dst_vtcm ,block_size ,uctx )) 806DEFINE_UNARY_TASK (scale , false, false,scale_f32 (src0_vtcm ,dst_vtcm ,block_size ,uctx )) 807DEFINE_UNARY_TASK (clamp , false, false,clamp_f32 (src0_vtcm ,dst_vtcm ,block_size ,uctx )) 808DEFINE_UNARY_TASK (leaky_relu , false, false,leaky_relu_f32 (src0_vtcm ,dst_vtcm ,block_size ,uctx )) 809DEFINE_UNARY_TASK (sqr , false, false,sqr_f32 (src0_vtcm ,dst_vtcm ,block_size ,uctx )) 810DEFINE_UNARY_TASK (sqrt , false, false,sqrt_f32 (src0_vtcm ,dst_vtcm ,block_size ,uctx )) 811DEFINE_UNARY_TASK (unary_neg , false, false,neg_f32 (src0_vtcm ,dst_vtcm ,block_size ,uctx )) 812DEFINE_UNARY_TASK (unary_exp , false, false,exp_f32 (src0_vtcm ,dst_vtcm ,block_size ,uctx )) 813DEFINE_UNARY_TASK (unary_sigmoid , false, false,sigmoid_f32 (src0_vtcm ,dst_vtcm ,block_size ,uctx )) 814DEFINE_UNARY_TASK (unary_silu , false, false,silu_f32 (src0_vtcm ,dst_vtcm ,block_size ,uctx )) 815DEFINE_UNARY_TASK (unary_gelu , false, false,gelu_f32 (src0_vtcm ,dst_vtcm ,block_size ,uctx )) 816DEFINE_UNARY_TASK (unary_softplus , false, false,softplus_f32 (src0_vtcm ,dst_vtcm ,block_size ,uctx )) 817DEFINE_UNARY_TASK (unary_tanh , false, false,tanh_f32 (src0_vtcm ,dst_vtcm ,block_size ,uctx )) 818DEFINE_UNARY_TASK (unary_abs , false, false,abs_f32 (src0_vtcm ,dst_vtcm ,block_size ,uctx )) 819DEFINE_UNARY_TASK (unary_log , false, false,log_f32 (src0_vtcm ,dst_vtcm ,block_size ,uctx )) 820DEFINE_UNARY_TASK (unary_relu , false, false,relu_f32 (src0_vtcm ,dst_vtcm ,block_size ,uctx )) 821DEFINE_UNARY_TASK (l2_norm , false, false,l2_norm_f32 (src0_vtcm ,dst_vtcm ,block_size ,uctx )) 822DEFINE_UNARY_TASK (tri , false, true,tri_f32 (src0_vtcm ,dst_vtcm ,block_size ,ir ,uctx )) 823 824// F16 unary tasks: same DMA/VTCM plumbing as DEFINE_UNARY_TASK, but VTCM buffers are 825// _Float16-typed. None of the current F16 ops need RMS_NORM_MUL or TRI support. 826DEFINE_UNARY_TASK_IMPL (norm ,_Float16 ,f16 , false, false,norm_f16 (src0_vtcm ,dst_vtcm ,block_size ,uctx )) 827DEFINE_UNARY_TASK_IMPL (rms_norm ,_Float16 ,f16 , false, false,rms_norm_f16 (src0_vtcm ,dst_vtcm ,block_size ,uctx )) 828DEFINE_UNARY_TASK_IMPL (scale ,_Float16 ,f16 , false, false,scale_f16 (src0_vtcm ,dst_vtcm ,block_size ,uctx )) 829DEFINE_UNARY_TASK_IMPL (clamp ,_Float16 ,f16 , false, false,clamp_f16 (src0_vtcm ,dst_vtcm ,block_size ,uctx )) 830DEFINE_UNARY_TASK_IMPL (sqr ,_Float16 ,f16 , false, false,sqr_f16 (src0_vtcm ,dst_vtcm ,block_size ,uctx )) 831DEFINE_UNARY_TASK_IMPL (sqrt ,_Float16 ,f16 , false, false,sqrt_f16 (src0_vtcm ,dst_vtcm ,block_size ,uctx )) 832DEFINE_UNARY_TASK_IMPL (l2_norm ,_Float16 ,f16 , false, false,l2_norm_f16 (src0_vtcm ,dst_vtcm ,block_size ,uctx )) 833DEFINE_UNARY_TASK_IMPL (unary_abs ,_Float16 ,f16 , false, false,abs_f16 (src0_vtcm ,dst_vtcm ,block_size ,uctx )) 834DEFINE_UNARY_TASK_IMPL (unary_log ,_Float16 ,f16 , false, false,log_f16 (src0_vtcm ,dst_vtcm ,block_size ,uctx )) 835 836// Apply a pointwise unary op to one column tile that is already in VTCM. 837#define DEFINE_UNARY_TILED_TASK (NAME ,IS_TRI ,CORE_TILE_EXPR ) \ 838static void unary_task_f32_tiled_##NAME(unsigned int nth, unsigned int ith, void * data) { \ 839 const struct htp_unary_context * uctx = (const struct htp_unary_context *) data; \ 840 struct htp_ops_context * octx = uctx->octx; \ 841 const struct htp_tensor * src = octx->src[0]; \ 842 const struct htp_tensor * dst = octx->dst; \ 843 struct htp_thread_trace * tr = &octx->ctx->trace[ith]; \ 844 \ 845 htp_unary_preamble; \ 846 \ 847 uint32_t src0_nrows_per_thread = uctx->src0_nrows_per_thread; \ 848 \ 849 int32_t * op_params = octx->op_params; \ 850 const uint32_t col_tile = uctx->col_tile; \ 851 \ 852 const uint32_t src0_nrows = uctx->src0_nrows; \ 853 const uint32_t src0_start_row = uctx->row_start + src0_nrows_per_thread * ith; \ 854 const uint32_t src0_end_row = MIN(src0_start_row + src0_nrows_per_thread, uctx->row_start + src0_nrows); \ 855 \ 856 if (src0_start_row >= src0_end_row) { \ 857 return; \ 858 } \ 859 \ 860 const uint8_t * restrict data_src = uctx->data_src0; \ 861 uint8_t * restrict data_dst = uctx->data_dst; \ 862 \ 863 uint8_t * src0_vtcm_data = uctx->vtcm_src0 + (ith * uctx->vtcm_src0_size_per_thread); \ 864 uint8_t * dst_vtcm_data = uctx->vtcm_dst + (ith * uctx->vtcm_dst_size_per_thread); \ 865 \ 866 const size_t src0_half = uctx->src0_vtcm_half_size; \ 867 const size_t dst_half = uctx->dst_vtcm_half_size; \ 868 \ 869 dma_queue * dmaq = octx->ctx->dma[ith]; \ 870 \ 871 const struct fastdiv_values * div_ne01 = &uctx->kparams->div_ne01; \ 872 const struct fastdiv_values * div_ne02 = &uctx->kparams->div_ne02; \ 873 const struct fastdiv_values * div_ne012 = &uctx->kparams->div_ne012; \ 874 const struct fastdiv_values * div_tpr = &uctx->kparams->div_tpr; \ 875 \ 876 const uint32_t tiles_per_row = (ne0 + col_tile - 1) / col_tile; \ 877 const int32_t tri_ttype = (IS_TRI) ? op_params[0] : 0; \ 878 \ 879 const bool src0_contig = (nb02 == (size_t)ne01 * nb01) && \ 880 (nb03 == (size_t)ne02 * nb02); \ 881 const bool dst_contig = (nb2 == (size_t)ne1 * nb1) && \ 882 (nb3 == (size_t)ne2 * nb2); \ 883 \ 884 const uint32_t total_tiles = (src0_end_row - src0_start_row) * tiles_per_row; \ 885 \ 886 for (uint32_t t = 0, vtcm_idx = 0; t < total_tiles && vtcm_idx < 2; t++, vtcm_idx++) { \ 887 const uint32_t row = src0_start_row + t / tiles_per_row; \ 888 const uint32_t col = (t % tiles_per_row) * col_tile; \ 889 const uint32_t tw = MIN(col_tile, ne0 - col); \ 890 const size_t tb = (size_t) tw * sizeof(float); \ 891 const size_t soff = (src0_contig ? (row * nb01) : \ 892 unary_row_offset(row, ne01, ne02, div_ne01, div_ne02, div_ne012, nb01, nb02, nb03)) + \ 893 (size_t) col * sizeof(float); \ 894 \ 895 dma_queue_push(dmaq, dma_make_ptr(data_dst, dst_vtcm_data + (vtcm_idx * dst_half)), 0, 0, 0, 0); \ 896 dma_queue_push(dmaq, dma_make_ptr(src0_vtcm_data + (vtcm_idx * src0_half), data_src + soff), tb, tb, tb, 1); \ 897 } \ 898 \ 899 uint32_t row = src0_start_row; \ 900 uint32_t col = 0; \ 901 uint32_t tile_in_row = 0; \ 902 uint32_t i01 = fastmodulo(row, ne01, div_ne01); \ 903 \ 904 uint32_t prow = src0_start_row + fastdiv(2, div_tpr); \ 905 uint32_t pcol = fastmodulo(2, tiles_per_row, div_tpr) * col_tile; \ 906 uint32_t ptile_in_row = fastmodulo(2, tiles_per_row, div_tpr); \ 907 \ 908 for (uint32_t t = 0; t < total_tiles; t++) { \ 909 uint8_t * dst_vtcm = (uint8_t *) dma_queue_pop(dmaq).src; \ 910 uint8_t * src_vtcm = (uint8_t *) dma_queue_pop(dmaq).dst; \ 911 \ 912 const uint32_t tw = MIN(col_tile, ne0 - col); \ 913 \ 914 htp_trace_event_start(tr, HTP_TRACE_EVT_HVX_COMP, t); \ 915 CORE_TILE_EXPR; \ 916 htp_trace_event_stop(tr, HTP_TRACE_EVT_HVX_COMP, t); \ 917 \ 918 const size_t doff = (dst_contig ? (row * nb1) : \ 919 unary_row_offset(row, ne1, ne2, div_ne01, div_ne02, div_ne012, nb1, nb2, nb3)) + \ 920 (size_t) col * sizeof(float); \ 921 const size_t tb = (size_t) tw * sizeof(float); \ 922 dma_queue_push(dmaq, dma_make_ptr(data_dst + doff, dst_vtcm), tb, tb, tb, 1); \ 923 \ 924 const uint32_t pt = t + 2; \ 925 if (pt < total_tiles) { \ 926 const uint32_t ptw = MIN(col_tile, ne0 - pcol); \ 927 const size_t ptb = (size_t) ptw * sizeof(float); \ 928 const size_t psoff = (src0_contig ? (prow * nb01) : \ 929 unary_row_offset(prow, ne01, ne02, div_ne01, div_ne02, div_ne012, nb01, nb02, \ 930 nb03)) + \ 931 (size_t) pcol * sizeof(float); \ 932 dma_queue_push(dmaq, dma_make_ptr(src_vtcm, data_src + psoff), ptb, ptb, ptb, 1); \ 933 } \ 934 \ 935 tile_in_row++; \ 936 col += col_tile; \ 937 if (tile_in_row == tiles_per_row) { \ 938 tile_in_row = 0; \ 939 col = 0; \ 940 row++; \ 941 i01++; \ 942 if (i01 == ne01) { \ 943 i01 = 0; \ 944 } \ 945 } \ 946 \ 947 ptile_in_row++; \ 948 pcol += col_tile; \ 949 if (ptile_in_row == tiles_per_row) { \ 950 ptile_in_row = 0; \ 951 pcol = 0; \ 952 prow++; \ 953 } \ 954 } \ 955 \ 956 dma_queue_flush(dmaq); \ 957} 958 959static inline void tile_scale_f32 (uint8_t * dst_vtcm ,const uint8_t * src_vtcm ,uint32_t tw ,const int32_t * op_params ) { 960float scale = 0.f ; 961float bias = 0.f ; 962memcpy (& scale ,& op_params [0 ],sizeof (float )); 963memcpy (& bias ,& op_params [1 ],sizeof (float )); 964hvx_scale_offset_f32_aa (dst_vtcm ,src_vtcm ,tw ,scale ,bias ); 965} 966 967static inline void tile_clamp_f32 (uint8_t * dst_vtcm ,const uint8_t * src_vtcm ,uint32_t tw ,const int32_t * op_params ) { 968float min = 0.f ; 969float max = 0.f ; 970memcpy (& min ,& op_params [0 ],sizeof (float )); 971memcpy (& max ,& op_params [1 ],sizeof (float )); 972hvx_clamp_scalar_f32 (dst_vtcm ,src_vtcm ,min ,max ,tw ); 973} 974 975static inline void tile_leaky_relu_f32 (uint8_t * dst_vtcm ,const uint8_t * src_vtcm ,uint32_t tw ,const int32_t * op_params ) { 976float negative_slope = 0.f ; 977memcpy (& negative_slope ,& op_params [0 ],sizeof (float )); 978hvx_leaky_relu_scalar_f32 (dst_vtcm ,src_vtcm ,negative_slope ,tw ); 979} 980 981static inline void tile_unary_softplus_f32 (uint8_t * dst_vtcm ,const uint8_t * src_vtcm ,uint32_t tw ) { 982const float * restrictsf = (const float * )src_vtcm ; 983float * restrictdf = (float * )dst_vtcm ; 984for (uint32_t i = 0 ;i < tw ;i ++ ) { 985float x = sf [i ]; 986df [i ]= (x > 20.0f ) ?x :logf (1.0f + expf (x )); 987 } 988} 989 990// silu(x) = x * sigmoid(x) 991static inline void tile_silu_f32 (uint8_t * dst_vtcm ,const uint8_t * src_vtcm ,uint32_t tw ) { 992hvx_sigmoid_f32_aa (dst_vtcm ,src_vtcm ,tw ); 993hvx_mul_f32_aaa (dst_vtcm ,src_vtcm ,dst_vtcm ,tw ); 994} 995 996// gelu(x) = x * sigmoid(1.702 * x) (quick/sigmoid approximation, matches CPU GELU_QUICK reference) 997static inline void tile_gelu_f32 (uint8_t * dst_vtcm ,const uint8_t * src_vtcm ,uint32_t tw ) { 998hvx_mul_scalar_f32 (dst_vtcm ,src_vtcm ,1.702f ,tw ); 999hvx_sigmoid_f32_aa (dst_vtcm ,dst_vtcm ,tw ); 1000hvx_mul_f32_aaa (dst_vtcm ,src_vtcm ,dst_vtcm ,tw ); 1001} 1002 1003// Triangular mask applied to one column tile. Boundary is an absolute column index, so 1004// each vector compares against its absolute column position (col_start + i*VLEN_FP32). 1005static inline void tri_apply_tile_f32 (const uint8_t * restrictsrc ,uint8_t * restrictdst , 1006uint32_t tile_elems ,uint32_t col_start ,uint32_t i01 , 1007uint32_t ne0 ,int32_t ttype ) { 1008const HVX_Vector * restrictv_src = (const HVX_Vector * )src ; 1009HVX_Vector * restrictv_dst = (HVX_Vector * )dst ; 1010const HVX_Vector zero = hvx_vec_splat_f32 (0.0f ); 1011 1012uint32_t boundary ; 1013int keep_left ; 1014switch (ttype ) { 1015case 0 :boundary = i01 ;keep_left = 0 ;break ; 1016case 1 :boundary = i01 + 1 ;keep_left = 0 ;break ; 1017case 2 :boundary = i01 + 1 ;keep_left = 1 ;break ; 1018case 3 :boundary = i01 ;keep_left = 1 ;break ; 1019default :boundary = 0 ;keep_left = 0 ;break ; 1020 } 1021if (boundary > ne0 )boundary = ne0 ; 1022 1023const uint32_t nvec = tile_elems /VLEN_FP32 ; 1024const uint32_t nloe = tile_elems %VLEN_FP32 ; 1025 1026for (uint32_t i = 0 ;i < nvec ;i ++ ) { 1027const uint32_t abs_start = col_start + i * VLEN_FP32 ; 1028const uint32_t abs_end = abs_start + VLEN_FP32 ; 1029if (keep_left ) { 1030if (abs_end <=boundary ) { 1031v_dst [i ]= v_src [i ]; 1032 }else if (abs_start >=boundary ) { 1033v_dst [i ]= zero ; 1034 }else { 1035HVX_VectorPred mask = Q6_Q_vsetq_R ((boundary - abs_start )* sizeof (float )); 1036v_dst [i ]= Q6_V_vmux_QVV (mask ,v_src [i ],zero ); 1037 } 1038 }else { 1039if (abs_end <=boundary ) { 1040v_dst [i ]= zero ; 1041 }else if (abs_start >=boundary ) { 1042v_dst [i ]= v_src [i ]; 1043 }else { 1044HVX_VectorPred mask = Q6_Q_vsetq_R ((boundary - abs_start )* sizeof (float )); 1045v_dst [i ]= Q6_V_vmux_QVV (mask ,zero ,v_src [i ]); 1046 } 1047 } 1048 } 1049 1050if (nloe > 0 ) { 1051const uint32_t abs_start = col_start + nvec * VLEN_FP32 ; 1052const uint32_t abs_end = abs_start + nloe ; 1053HVX_Vector tail_val ; 1054if (keep_left ) { 1055if (abs_end <=boundary ) { 1056tail_val = v_src [nvec ]; 1057 }else if (abs_start >=boundary ) { 1058tail_val = zero ; 1059 }else { 1060HVX_VectorPred mask = Q6_Q_vsetq_R ((boundary - abs_start )* sizeof (float )); 1061tail_val = Q6_V_vmux_QVV (mask ,v_src [nvec ],zero ); 1062 } 1063 }else { 1064if (abs_end <=boundary ) { 1065tail_val = zero ; 1066 }else if (abs_start >=boundary ) { 1067tail_val = v_src [nvec ]; 1068 }else { 1069HVX_VectorPred mask = Q6_Q_vsetq_R ((boundary - abs_start )* sizeof (float )); 1070tail_val = Q6_V_vmux_QVV (mask ,zero ,v_src [nvec ]); 1071 } 1072 } 1073hvx_vec_store_a (& v_dst [nvec ],nloe * sizeof (float ),tail_val ); 1074 } 1075} 1076 1077DEFINE_UNARY_TILED_TASK (scale , false,tile_scale_f32 (dst_vtcm ,src_vtcm ,tw ,op_params )) 1078DEFINE_UNARY_TILED_TASK (clamp , false,tile_clamp_f32 (dst_vtcm ,src_vtcm ,tw ,op_params )) 1079DEFINE_UNARY_TILED_TASK (leaky_relu , false,tile_leaky_relu_f32 (dst_vtcm ,src_vtcm ,tw ,op_params )) 1080DEFINE_UNARY_TILED_TASK (sqr , false,hvx_sqr_f32_aa (dst_vtcm ,src_vtcm ,tw )) 1081DEFINE_UNARY_TILED_TASK (sqrt , false,hvx_sqrt_f32_aa (dst_vtcm ,src_vtcm ,tw )) 1082DEFINE_UNARY_TILED_TASK (unary_neg , false,hvx_scale_f32_aa (dst_vtcm ,src_vtcm ,tw ,-1.0f )) 1083DEFINE_UNARY_TILED_TASK (unary_exp , false,hvx_exp_f32 (dst_vtcm ,src_vtcm ,tw , false)) 1084DEFINE_UNARY_TILED_TASK (unary_sigmoid , false,hvx_sigmoid_f32_aa (dst_vtcm ,src_vtcm ,tw )) 1085DEFINE_UNARY_TILED_TASK (unary_silu , false,tile_silu_f32 (dst_vtcm ,src_vtcm ,tw )) 1086DEFINE_UNARY_TILED_TASK (unary_gelu , false,tile_gelu_f32 (dst_vtcm ,src_vtcm ,tw )) 1087DEFINE_UNARY_TILED_TASK (unary_softplus , false,tile_unary_softplus_f32 (dst_vtcm ,src_vtcm ,tw )) 1088DEFINE_UNARY_TILED_TASK (unary_tanh , false,hvx_tanh_f32_aa (dst_vtcm ,src_vtcm ,tw )) 1089DEFINE_UNARY_TILED_TASK (unary_abs , false,hvx_abs_f32_aa (dst_vtcm ,src_vtcm ,tw )) 1090DEFINE_UNARY_TILED_TASK (unary_log , false,hvx_log_f32_aa (dst_vtcm ,src_vtcm ,tw )) 1091DEFINE_UNARY_TILED_TASK (unary_relu , false,hvx_max_scalar_f32 (dst_vtcm ,src_vtcm ,0.0f ,tw )) 1092DEFINE_UNARY_TILED_TASK (tri , true,tri_apply_tile_f32 (src_vtcm ,dst_vtcm ,tw ,col ,i01 ,ne0 ,tri_ttype )) 1093 1094static int execute_op_unary (struct htp_ops_context * octx ) { 1095int err = HTP_STATUS_OK ; 1096 1097const struct htp_tensor * src0 = octx -> src [0 ]; 1098const struct htp_tensor * dst = octx -> dst ; 1099 1100const bool is_f16 = (src0 -> type == HTP_TYPE_F16 ); 1101 1102const char * op_type = NULL ; 1103 1104switch (octx -> op ) { 1105case HTP_OP_NORM :op_type = is_f16 ?"norm-f16" :"norm-f32" ;break ; 1106case HTP_OP_RMS_NORM :op_type = is_f16 ?"rmsnorm-f16" :"rmsnorm-f32" ;break ; 1107case HTP_OP_RMS_NORM_MUL :op_type = "rmsnorm-mul-f32" ;break ; 1108case HTP_OP_SCALE :op_type = is_f16 ?"scale-f16" :"scale-f32" ;break ; 1109case HTP_OP_CLAMP :op_type = is_f16 ?"clamp-f16" :"clamp-f32" ;break ; 1110case HTP_OP_LEAKY_RELU :op_type = "leaky-relu-f32" ;break ; 1111case HTP_OP_SQR :op_type = is_f16 ?"sqr-f16" :"sqr-f32" ;break ; 1112case HTP_OP_SQRT :op_type = is_f16 ?"sqrt-f16" :"sqrt-f32" ;break ; 1113case HTP_OP_UNARY_NEG :op_type = "neg-f32" ;break ; 1114case HTP_OP_UNARY_EXP :op_type = "exp-f32" ;break ; 1115case HTP_OP_UNARY_SIGMOID :op_type = "sigmoid-f32" ;break ; 1116case HTP_OP_UNARY_SILU :op_type = "silu-f32" ;break ; 1117case HTP_OP_UNARY_GELU :op_type = "gelu-f32" ;break ; 1118case HTP_OP_UNARY_SOFTPLUS :op_type = "softplus-f32" ;break ; 1119case HTP_OP_UNARY_TANH :op_type = "tanh-f32" ;break ; 1120case HTP_OP_UNARY_ABS :op_type = is_f16 ?"abs-f16" :"abs-f32" ;break ; 1121case HTP_OP_UNARY_LOG :op_type = is_f16 ?"log-f16" :"log-f32" ;break ; 1122case HTP_OP_UNARY_RELU :op_type = "relu-f32" ;break ; 1123case HTP_OP_L2_NORM :op_type = is_f16 ?"l2norm-f16" :"l2norm-f32" ;break ; 1124case HTP_OP_TRI :op_type = "tri-f32" ;break ; 1125default : 1126FARF (ERROR ,"Unsupported unary Op %u\n" ,octx -> op ); 1127return HTP_STATUS_NO_SUPPORT ; 1128 } 1129 1130// F16 only has row-block kernels for this subset of ops (see the dispatch switch 1131// below) - reject everything else up front, before touching kparams/VTCM. 1132if (is_f16 ) { 1133switch (octx -> op ) { 1134case HTP_OP_NORM : 1135case HTP_OP_RMS_NORM : 1136case HTP_OP_SCALE : 1137case HTP_OP_CLAMP : 1138case HTP_OP_SQR : 1139case HTP_OP_SQRT : 1140case HTP_OP_L2_NORM : 1141case HTP_OP_UNARY_ABS : 1142case HTP_OP_UNARY_LOG : 1143break ; 1144default : 1145FARF (ERROR ,"unary-%s: not supported for F16\n" ,op_type ); 1146return HTP_STATUS_NO_SUPPORT ; 1147 } 1148 } 1149 1150const struct htp_unary_kernel_params * kparams = (const struct htp_unary_kernel_params * )octx -> kernel_params ; 1151 1152if (!htp_ops_context_set_n_threads (octx ,kparams -> n_threads )) { 1153return HTP_STATUS_INVAL_PARAMS ; 1154 } 1155 1156const uint32_t src0_nrows = src0 -> ne [1 ]* src0 -> ne [2 ]* src0 -> ne [3 ]; 1157const size_t elem_size = is_f16 ?sizeof (_Float16 ) :sizeof (float ); 1158const size_t src0_data_row_size = src0 -> ne [0 ]* elem_size ; 1159const size_t dst_data_row_size = dst -> ne [0 ]* elem_size ; 1160 1161uint32_t row_start = 0 ; 1162uint32_t nrows = src0_nrows ; 1163 1164if (octx -> ctx -> mdev .count > 1 ) { 1165uint32_t rows_per_chunk = 0 ; 1166htp_tensor_mdev_rows_per_chunk (dst , (uint32_t )elem_size , (uint32_t )dst_data_row_size ,& rows_per_chunk ); 1167const struct htp_tensor_mdev_range range = htp_tensor_mdev_partition (src0_nrows ,rows_per_chunk ,octx -> ctx -> mdev .idx ,octx -> ctx -> mdev .count ,& octx -> ctx -> mdev .count_div ); 1168row_start = range .start ; 1169nrows = range .count ; 1170 } 1171 1172if (nrows == 0 ) { 1173return HTP_STATUS_OK ; 1174 } 1175 1176const uint32_t n_threads = octx -> n_threads ; 1177 1178const size_t src0_row_size_aligned = kparams -> src0_row_size_aligned ; 1179const size_t dst_row_size_aligned = kparams -> dst_row_size_aligned ; 1180 1181// Always 0 for F16 - htp_unary_vtcm_layout_build() keeps F16 on the row-block path, 1182// since only F32 has unary_task_f32_tiled_* kernels. 1183const uint32_t col_tile = kparams -> col_tile ; 1184 1185size_t src1_data_row_size = 0 ; 1186size_t src1_row_size_aligned = kparams -> src1_row_size_aligned ; 1187bool broadcast_weight = kparams -> broadcast_weight ; 1188const struct htp_tensor * src1 = NULL ; 1189 1190// RMS_NORM_MUL fusion is F32-only (its weight tensor is always F32; see 1191// try_fuse_node()'s type guard), so this never triggers when is_f16 is true. 1192if (octx -> op == HTP_OP_RMS_NORM_MUL ) { 1193src1 = octx -> src [1 ]; 1194src1_data_row_size = src1 -> ne [0 ]* sizeof (float ); 1195 } 1196 1197if (octx -> ctx -> vtcm_size < (size_t )kparams -> vtcm_size ) { 1198FARF (ERROR ,"unary-%s : current VTCM reservation %zu is too small, needed %zu\n" ,op_type ,octx -> ctx -> vtcm_size , (size_t )kparams -> vtcm_size ); 1199return HTP_STATUS_VTCM_TOO_SMALL ; 1200 } 1201 1202octx -> src0_spad .src = NULL ; 1203octx -> src1_spad .src = NULL ; 1204octx -> dst_spad .src = NULL ; 1205 1206FARF (HIGH ,"%s: (%ux%ux%ux%u) -> (%ux%ux%ux%u) : src0-vtcm-size %u src1-vtcm-size %u dst-vtcm-size %u\n" ,op_type , 1207src0 -> ne [0 ],src0 -> ne [1 ],src0 -> ne [2 ],src0 -> ne [3 ],dst -> ne [0 ],dst -> ne [1 ],dst -> ne [2 ],dst -> ne [3 ], 1208kparams -> vtcm_src0_size ,kparams -> vtcm_src1_size ,kparams -> vtcm_dst_size ); 1209 1210if (!(octx -> flags & HTP_OPFLAGS_SKIP_COMPUTE )) { 1211uint8_t * const base = (uint8_t * )octx -> ctx -> vtcm_base ; 1212struct htp_unary_context uctx = { 1213 .octx = octx , 1214 .kparams = kparams , 1215 .src0_nrows_per_thread = fastdiv (nrows + n_threads - 1 ,& octx -> n_threads_div ), 1216 .src0_nrows = nrows , 1217 .row_start = row_start , 1218 1219 .data_src0 = (const uint8_t * )src0 -> data , 1220 .data_src1 = (octx -> op == HTP_OP_RMS_NORM_MUL ) ? (const uint8_t * )src1 -> data :NULL , 1221 .data_dst = (uint8_t * )dst -> data , 1222 1223 .src0_data_row_size = src0_data_row_size , 1224 .src1_data_row_size = src1_data_row_size , 1225 .dst_data_row_size = dst_data_row_size , 1226 1227 .src0_row_size_aligned = src0_row_size_aligned , 1228 .src1_row_size_aligned = src1_row_size_aligned , 1229 .dst_row_size_aligned = dst_row_size_aligned , 1230 1231 .src0_vtcm_half_size = kparams -> vtcm_src0_size_per_thread /2 , 1232 .src1_vtcm_half_size = (octx -> op == HTP_OP_RMS_NORM_MUL ) ? (kparams -> vtcm_src1_size_per_thread / (broadcast_weight ?1 :2 )) :0 , 1233 .dst_vtcm_half_size = kparams -> vtcm_dst_size_per_thread /2 , 1234 1235 .block = kparams -> block , 1236 .nc = src0 -> ne [0 ], 1237 .col_tile = col_tile , 1238 .broadcast_weight = broadcast_weight , 1239 1240 .vtcm_src0 = VTCM_LAYOUT_PTR (uint8_t ,base ,0 ), 1241 .vtcm_src1 = VTCM_LAYOUT_PTR_OPTIONAL (uint8_t ,base ,kparams -> vtcm_src0_size ,kparams -> vtcm_src1_size > 0 ), 1242 .vtcm_dst = VTCM_LAYOUT_PTR (uint8_t ,base ,kparams -> vtcm_src0_size + kparams -> vtcm_src1_size ), 1243 1244 .vtcm_src0_size_per_thread = kparams -> vtcm_src0_size_per_thread , 1245 .vtcm_src1_size_per_thread = kparams -> vtcm_src1_size_per_thread , 1246 .vtcm_dst_size_per_thread = kparams -> vtcm_dst_size_per_thread , 1247 }; 1248 1249FARF (HIGH ,"%s: %s mode (col_tile %u)\n" ,op_type ,col_tile ?"tiled" :"row-block" ,col_tile ); 1250 1251worker_callback_t task_func = NULL ; 1252if (col_tile ) { 1253switch (octx -> op ) { 1254case HTP_OP_SCALE :task_func = unary_task_f32_tiled_scale ;break ; 1255case HTP_OP_CLAMP :task_func = unary_task_f32_tiled_clamp ;break ; 1256case HTP_OP_LEAKY_RELU :task_func = unary_task_f32_tiled_leaky_relu ;break ; 1257case HTP_OP_SQR :task_func = unary_task_f32_tiled_sqr ;break ; 1258case HTP_OP_SQRT :task_func = unary_task_f32_tiled_sqrt ;break ; 1259case HTP_OP_UNARY_NEG :task_func = unary_task_f32_tiled_unary_neg ;break ; 1260case HTP_OP_UNARY_EXP :task_func = unary_task_f32_tiled_unary_exp ;break ; 1261case HTP_OP_UNARY_SIGMOID :task_func = unary_task_f32_tiled_unary_sigmoid ;break ; 1262case HTP_OP_UNARY_SILU :task_func = unary_task_f32_tiled_unary_silu ;break ; 1263case HTP_OP_UNARY_GELU :task_func = unary_task_f32_tiled_unary_gelu ;break ; 1264case HTP_OP_UNARY_SOFTPLUS :task_func = unary_task_f32_tiled_unary_softplus ;break ; 1265case HTP_OP_UNARY_TANH :task_func = unary_task_f32_tiled_unary_tanh ;break ; 1266case HTP_OP_UNARY_ABS :task_func = unary_task_f32_tiled_unary_abs ;break ; 1267case HTP_OP_UNARY_LOG :task_func = unary_task_f32_tiled_unary_log ;break ; 1268case HTP_OP_UNARY_RELU :task_func = unary_task_f32_tiled_unary_relu ;break ; 1269case HTP_OP_TRI :task_func = unary_task_f32_tiled_tri ;break ; 1270default :break ; 1271 } 1272 }else if (is_f16 ) { 1273switch (octx -> op ) { 1274case HTP_OP_NORM :task_func = unary_task_f16_norm ;break ; 1275case HTP_OP_RMS_NORM :task_func = unary_task_f16_rms_norm ;break ; 1276case HTP_OP_SCALE :task_func = unary_task_f16_scale ;break ; 1277case HTP_OP_CLAMP :task_func = unary_task_f16_clamp ;break ; 1278case HTP_OP_SQR :task_func = unary_task_f16_sqr ;break ; 1279case HTP_OP_SQRT :task_func = unary_task_f16_sqrt ;break ; 1280case HTP_OP_L2_NORM :task_func = unary_task_f16_l2_norm ;break ; 1281case HTP_OP_UNARY_ABS :task_func = unary_task_f16_unary_abs ;break ; 1282case HTP_OP_UNARY_LOG :task_func = unary_task_f16_unary_log ;break ; 1283default :break ; 1284 } 1285 }else { 1286switch (octx -> op ) { 1287case HTP_OP_NORM :task_func = unary_task_f32_norm ;break ; 1288case HTP_OP_RMS_NORM :task_func = unary_task_f32_rms_norm ;break ; 1289case HTP_OP_RMS_NORM_MUL :task_func = unary_task_f32_rms_norm_mul ;break ; 1290case HTP_OP_SCALE :task_func = unary_task_f32_scale ;break ; 1291case HTP_OP_CLAMP :task_func = unary_task_f32_clamp ;break ; 1292case HTP_OP_LEAKY_RELU :task_func = unary_task_f32_leaky_relu ;break ; 1293case HTP_OP_SQR :task_func = unary_task_f32_sqr ;break ; 1294case HTP_OP_SQRT :task_func = unary_task_f32_sqrt ;break ; 1295case HTP_OP_UNARY_NEG :task_func = unary_task_f32_unary_neg ;break ; 1296case HTP_OP_UNARY_EXP :task_func = unary_task_f32_unary_exp ;break ; 1297case HTP_OP_UNARY_SIGMOID :task_func = unary_task_f32_unary_sigmoid ;break ; 1298case HTP_OP_UNARY_SILU :task_func = unary_task_f32_unary_silu ;break ; 1299case HTP_OP_UNARY_GELU :task_func = unary_task_f32_unary_gelu ;break ; 1300case HTP_OP_UNARY_SOFTPLUS :task_func = unary_task_f32_unary_softplus ;break ; 1301case HTP_OP_UNARY_TANH :task_func = unary_task_f32_unary_tanh ;break ; 1302case HTP_OP_UNARY_ABS :task_func = unary_task_f32_unary_abs ;break ; 1303case HTP_OP_UNARY_LOG :task_func = unary_task_f32_unary_log ;break ; 1304case HTP_OP_UNARY_RELU :task_func = unary_task_f32_unary_relu ;break ; 1305case HTP_OP_L2_NORM :task_func = unary_task_f32_l2_norm ;break ; 1306case HTP_OP_TRI :task_func = unary_task_f32_tri ;break ; 1307default :break ; 1308 } 1309 } 1310 1311if (task_func ) { 1312work_queue_run (octx -> ctx -> work_queue ,task_func ,& uctx ,n_threads ); 1313 }else { 1314FARF (ERROR ,"execute_op_unary: task function is NULL for op %d\n" ,octx -> op ); 1315err = HTP_STATUS_NO_SUPPORT ; 1316 } 1317 } 1318 1319return err ; 1320} 1321 1322int op_unary (struct htp_ops_context * octx ) { 1323switch (octx -> src [0 ]-> type ) { 1324case HTP_TYPE_F32 : 1325case HTP_TYPE_F16 : 1326return execute_op_unary (octx ); 1327 1328default : 1329return HTP_STATUS_NO_SUPPORT ; 1330 } 1331}