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 "hvx-utils.h" 13 14#define GGML_COMMON_DECL_C 15#include "ggml-common.h" 16#include "hex-common.h" 17#include "hex-profile.h" 18#include "htp-ctx.h" 19#include "htp-ops.h" 20#include "htp-tensor.h" 21 22#ifndef MIN 23#define MIN (a ,b ) ((a) < (b) ? (a) : (b)) 24#endif 25 26// Context for binary operations 27struct htp_binary_context { 28struct htp_ops_context * octx ; 29 30struct fastdiv_values src0_dim1_div ;// ne01 31struct fastdiv_values src0_dim2_div ;// ne02 32struct fastdiv_values src0_dim12_div ;// ne03 33 34struct fastdiv_values src1_dim1_div ;// ne11 35struct fastdiv_values src1_dim2_div ;// ne12 36struct fastdiv_values src1_dim3_div ;// ne13 37 38uint32_t block_max ; 39uint32_t nrows_per_thread ; 40uint32_t total_rows ; 41uint32_t row_start ; 42size_t src0_row_size_aligned ; 43size_t src1_row_size_aligned ; 44size_t dst_row_size_aligned ; 45 46bool split_at_ne01 ; 47bool split_at_ne02 ; 48}; 49 50#define htp_binary_preamble \ 51 const struct htp_tensor * src0 = octx->src[0]; \ 52 const struct htp_tensor * src1 = octx->src[1]; \ 53 const struct htp_tensor * dst = octx->dst; \ 54 \ 55 const uint32_t ne00 = src0->ne[0]; \ 56 const uint32_t ne01 = src0->ne[1]; \ 57 const uint32_t ne02 = src0->ne[2]; \ 58 const uint32_t ne03 = src0->ne[3]; \ 59 \ 60 const uint32_t ne10 = src1->ne[0]; \ 61 const uint32_t ne11 = src1->ne[1]; \ 62 const uint32_t ne12 = src1->ne[2]; \ 63 const uint32_t ne13 = src1->ne[3]; \ 64 \ 65 const uint32_t nb01 = src0->nb[1]; \ 66 const uint32_t nb02 = src0->nb[2]; \ 67 const uint32_t nb03 = src0->nb[3]; \ 68 \ 69 const uint32_t nb11 = src1->nb[1]; \ 70 const uint32_t nb12 = src1->nb[2]; \ 71 const uint32_t nb13 = src1->nb[3]; \ 72 \ 73 const uint32_t nb1 = dst->nb[1]; \ 74 const uint32_t nb2 = dst->nb[2]; \ 75 const uint32_t nb3 = dst->nb[3]; 76 77static inline uint32_t calc_block_size (struct htp_binary_context * bctx ,uint32_t ir ,uint32_t end_row ,uint32_t ne01 ,uint32_t ne02 ) { 78uint32_t i03 ,i02 ,i01 ,rem ; 79i03 = fastdiv (ir ,& bctx -> src0_dim12_div ); 80rem = ir - i03 * (ne02 * ne01 ); 81i02 = fastdiv (rem ,& bctx -> src0_dim1_div ); 82i01 = rem - i02 * ne01 ; 83 84uint32_t rows_left = end_row - ir ; 85uint32_t block_limit = rows_left ; 86 87if (bctx -> split_at_ne01 ) { 88block_limit = MIN (block_limit ,ne01 - i01 ); 89 } 90if (bctx -> split_at_ne02 ) { 91uint32_t rows_in_plane = (ne02 * ne01 )- rem ; 92block_limit = MIN (block_limit ,rows_in_plane ); 93 } 94 95return MIN (bctx -> block_max ,block_limit ); 96} 97 98// Macro for scalar op switch 99#define COMPUTE_SCALAR_OP (DST ,SRC ,VAL ,TYPE ,N ) \ 100 if(TYPE == HTP_TYPE_F32) { \ 101 switch (octx->op) { \ 102 case HTP_OP_ADD: hvx_add_scalar_f32_aa(DST, SRC, *(float *)VAL, N); break; \ 103 case HTP_OP_SUB: hvx_sub_scalar_f32_aa(DST, SRC, *(float *)VAL, N); break; \ 104 case HTP_OP_MUL: hvx_mul_scalar_f32_aa(DST, SRC, *(float *)VAL, N); break; \ 105 case HTP_OP_DIV: hvx_mul_scalar_f32_aa(DST, SRC, 1.0f / (*(float *)VAL), N); break; \ 106 default: break; \ 107 } \ 108 } \ 109 else { \ 110 switch (octx->op) { \ 111 case HTP_OP_ADD: hvx_add_scalar_f16_aa(DST, SRC, *(_Float16 *)VAL, N); break; \ 112 case HTP_OP_SUB: hvx_sub_scalar_f16_aa(DST, SRC, *(_Float16 *)VAL, N); break; \ 113 case HTP_OP_MUL: hvx_mul_scalar_f16_aa(DST, SRC, *(_Float16 *)VAL, N); break; \ 114 case HTP_OP_DIV: hvx_div_scalar_f16_aa(DST, SRC, *(_Float16 *)VAL, N); break; \ 115 default: break; \ 116 } \ 117 } 118 119// Macro for vector op switch (All Aligned) 120#define COMPUTE_VECTOR_OP_AAA (DST ,SRC0 ,SRC1 ,TYPE ,N ) \ 121 if(TYPE == HTP_TYPE_F32) { \ 122 switch (octx->op) { \ 123 case HTP_OP_ADD: hvx_add_f32_aaa(DST, SRC0, SRC1, N); break; \ 124 case HTP_OP_SUB: hvx_sub_f32_aaa(DST, SRC0, SRC1, N); break; \ 125 case HTP_OP_MUL: hvx_mul_f32_aaa(DST, SRC0, SRC1, N); break; \ 126 case HTP_OP_DIV: hvx_div_f32_aaa(DST, SRC0, SRC1, N); break; \ 127 default: break; \ 128 } \ 129 } \ 130 else { \ 131 switch (octx->op) { \ 132 case HTP_OP_ADD: hvx_add_f16_aaa(DST, SRC0, SRC1, N); break; \ 133 case HTP_OP_SUB: hvx_sub_f16_aaa(DST, SRC0, SRC1, N); break; \ 134 case HTP_OP_MUL: hvx_mul_f16_aaa(DST, SRC0, SRC1, N); break; \ 135 case HTP_OP_DIV: hvx_div_f16_aaa(DST, SRC0, SRC1, N); break; \ 136 default: break; \ 137 } \ 138 } 139 140// Macro for vector op switch (Dst Aligned, Src0 Aligned, Src1 Unaligned) 141#define COMPUTE_VECTOR_OP_AAU (DST ,SRC0 ,SRC1 ,TYPE ,N ) \ 142 if(TYPE == HTP_TYPE_F32) { \ 143 switch (octx->op) { \ 144 case HTP_OP_ADD: hvx_add_f32_aau(DST, SRC0, SRC1, N); break; \ 145 case HTP_OP_SUB: hvx_sub_f32_aau(DST, SRC0, SRC1, N); break; \ 146 case HTP_OP_MUL: hvx_mul_f32_aau(DST, SRC0, SRC1, N); break; \ 147 case HTP_OP_DIV: hvx_div_f32_aau(DST, SRC0, SRC1, N); break; \ 148 default: break; \ 149 } \ 150 } \ 151 else { \ 152 switch (octx->op) { \ 153 case HTP_OP_ADD: hvx_add_f16_aau(DST, SRC0, SRC1, N); break; \ 154 case HTP_OP_SUB: hvx_sub_f16_aau(DST, SRC0, SRC1, N); break; \ 155 case HTP_OP_MUL: hvx_mul_f16_aau(DST, SRC0, SRC1, N); break; \ 156 case HTP_OP_DIV: hvx_div_f16_aau(DST, SRC0, SRC1, N); break; \ 157 default: break; \ 158 } \ 159 } 160 161// Macro for vector op switch (All Unaligned - generic loop used in element repeat) 162#define COMPUTE_VECTOR_OP_UUU (DST ,SRC0 ,SRC1 ,TYPE ,N ) \ 163 if(TYPE == HTP_TYPE_F32) { \ 164 switch (octx->op) { \ 165 case HTP_OP_ADD: hvx_add_f32_uuu(DST, SRC0, SRC1, N); break; \ 166 case HTP_OP_SUB: hvx_sub_f32_uuu(DST, SRC0, SRC1, N); break; \ 167 case HTP_OP_MUL: hvx_mul_f32_uuu(DST, SRC0, SRC1, N); break; \ 168 case HTP_OP_DIV: hvx_div_f32_uuu(DST, SRC0, SRC1, N); break; \ 169 default: break; \ 170 } \ 171 } \ 172 else { \ 173 switch (octx->op) { \ 174 case HTP_OP_ADD: hvx_add_f16_uuu(DST, SRC0, SRC1, N); break; \ 175 case HTP_OP_SUB: hvx_sub_f16_uuu(DST, SRC0, SRC1, N); break; \ 176 case HTP_OP_MUL: hvx_mul_f16_uuu(DST, SRC0, SRC1, N); break; \ 177 case HTP_OP_DIV: hvx_div_f16_uuu(DST, SRC0, SRC1, N); break; \ 178 default: break; \ 179 } \ 180 } 181 182// 1. Scalar src1 (ne10 == 1) 183static void binary_job_scalar (unsigned int nth ,unsigned int ith ,void * data ) { 184struct htp_binary_context * bctx = (struct htp_binary_context * )data ; 185struct htp_ops_context * octx = bctx -> octx ; 186htp_binary_preamble ; 187 188const uint32_t src0_type = octx -> src [0 ]-> type ; 189const uint32_t row_size_bytes = (src0_type == HTP_TYPE_F32 ) ?ne00 * sizeof (float ) :ne00 * sizeof (_Float16 ); 190const uint32_t start_row = bctx -> row_start + bctx -> nrows_per_thread * ith ; 191const uint32_t end_row = MIN (start_row + bctx -> nrows_per_thread ,bctx -> row_start + bctx -> total_rows ); 192if (start_row >=end_row )return ; 193 194FARF (HIGH ,"binary-scalar: %d/%d (%u:%u) row-size %u (%u)" ,ith ,nth ,start_row ,end_row ,nb01 ,bctx -> dst_row_size_aligned ); 195 196uint8_t * src0_spad_base = octx -> src0_spad .data + (ith * octx -> src0_spad .size_per_thread ); 197uint8_t * dst_spad_base = octx -> dst_spad .data + (ith * octx -> dst_spad .size_per_thread ); 198size_t src0_spad_half = octx -> src0_spad .size_per_thread /2 ; 199size_t dst_spad_half = octx -> dst_spad .size_per_thread /2 ; 200 201dma_queue * q = octx -> ctx -> dma [ith ]; 202uint32_t ir_prefetch = start_row ; 203int spad_idx = 0 ; 204 205// Preamble 206for (int k = 0 ;k < 2 && ir_prefetch < end_row ;k ++ ) { 207uint32_t current_block_size = calc_block_size (bctx ,ir_prefetch ,end_row ,ne01 ,ne02 ); 208uint32_t i03 ,i02 ,i01 ,rem ; 209i03 = fastdiv (ir_prefetch ,& bctx -> src0_dim12_div ); 210rem = ir_prefetch - i03 * (ne02 * ne01 ); 211i02 = fastdiv (rem ,& bctx -> src0_dim1_div ); 212i01 = rem - i02 * ne01 ; 213 214uint8_t * src0_curr = (uint8_t * )src0 -> data + i03 * nb03 + i02 * nb02 + i01 * nb01 ; 215uint8_t * dst_curr = (uint8_t * )dst -> data + i03 * nb3 + i02 * nb2 + i01 * nb1 ; 216 217uint8_t * s0_spad = src0_spad_base + spad_idx * src0_spad_half ; 218uint8_t * d_spad = dst_spad_base + spad_idx * dst_spad_half ; 219 220dma_queue_push (q ,dma_make_ptr (dst_curr ,d_spad ),nb1 ,bctx -> dst_row_size_aligned ,row_size_bytes ,0 ); 221dma_queue_push (q ,dma_make_ptr (s0_spad ,src0_curr ),bctx -> src0_row_size_aligned ,nb01 ,row_size_bytes ,current_block_size ); 222ir_prefetch += current_block_size ; 223spad_idx ^=1 ; 224 } 225 226// Main loop 227struct htp_thread_trace * tr = & octx -> ctx -> trace [ith ]; 228 229for (uint32_t ir = start_row ;ir < end_row ; ) { 230uint32_t current_block_size = calc_block_size (bctx ,ir ,end_row ,ne01 ,ne02 ); 231 232uint8_t * d_spad = (uint8_t * )dma_queue_pop (q ).src ; 233uint8_t * s0_spad = (uint8_t * )dma_queue_pop (q ).dst ; 234 235uint32_t i03 ,i02 ,i01 ,rem ; 236i03 = fastdiv (ir ,& bctx -> src0_dim12_div ); 237rem = ir - i03 * (ne02 * ne01 ); 238i02 = fastdiv (rem ,& bctx -> src0_dim1_div ); 239i01 = rem - i02 * ne01 ; 240 241// src1 indices (broadcast/repeat) 242uint32_t i13 = fastmodulo (i03 ,ne13 ,& bctx -> src1_dim3_div ); 243uint32_t i12 = fastmodulo (i02 ,ne12 ,& bctx -> src1_dim2_div ); 244uint32_t i11 = fastmodulo (i01 ,ne11 ,& bctx -> src1_dim1_div ); 245 246uint8_t * src1_ptr = (uint8_t * )src1 -> data + i13 * nb13 + i12 * nb12 + i11 * nb11 ; 247uint32_t s1_stride = (ne11 == 1 ) ?0 :nb11 ; 248 249htp_trace_event_start (tr ,HTP_TRACE_EVT_HVX_COMP , (uint16_t )ir ); 250for (uint32_t r = 0 ;r < current_block_size ;r ++ ) { 251uint8_t * r_src0 = s0_spad + r * bctx -> src0_row_size_aligned ; 252uint8_t * r_dst = d_spad + r * bctx -> dst_row_size_aligned ; 253COMPUTE_SCALAR_OP (r_dst ,r_src0 ,src1_ptr ,src0_type ,ne00 ); 254src1_ptr += s1_stride ; 255 } 256htp_trace_event_stop (tr ,HTP_TRACE_EVT_HVX_COMP , (uint16_t )ir ); 257 258uint8_t * dst_curr = (uint8_t * )dst -> data + i03 * nb3 + i02 * nb2 + i01 * nb1 ; 259dma_queue_push (q ,dma_make_ptr (dst_curr ,d_spad ),nb1 ,bctx -> dst_row_size_aligned ,row_size_bytes ,current_block_size ); 260 261if (ir_prefetch < end_row ) { 262uint32_t next_block_size = calc_block_size (bctx ,ir_prefetch ,end_row ,ne01 ,ne02 ); 263uint32_t p03 ,p02 ,p01 ,prem ; 264p03 = fastdiv (ir_prefetch ,& bctx -> src0_dim12_div ); 265prem = ir_prefetch - p03 * (ne02 * ne01 ); 266p02 = fastdiv (prem ,& bctx -> src0_dim1_div ); 267p01 = prem - p02 * ne01 ; 268uint8_t * s0_next = (uint8_t * )src0 -> data + p03 * nb03 + p02 * nb02 + p01 * nb01 ; 269 270dma_queue_push (q ,dma_make_ptr (s0_spad ,s0_next ),bctx -> src0_row_size_aligned ,nb01 ,row_size_bytes ,next_block_size ); 271ir_prefetch += next_block_size ; 272 } 273ir += current_block_size ; 274 } 275 276dma_queue_flush (q ); 277} 278 279// 2. Vector Same Shape (ne1x == ne0x) or Simple Broadcast 280static void binary_job_vector_same_shape (unsigned int nth ,unsigned int ith ,void * data ) { 281struct htp_binary_context * bctx = (struct htp_binary_context * )data ; 282struct htp_ops_context * octx = bctx -> octx ; 283htp_binary_preamble ; 284 285const uint32_t src0_type = octx -> src [0 ]-> type ; 286const uint32_t row_size_bytes = (src0_type == HTP_TYPE_F32 ) ?ne00 * sizeof (float ) :ne00 * sizeof (_Float16 ); 287const uint32_t start_row = bctx -> row_start + bctx -> nrows_per_thread * ith ; 288const uint32_t end_row = MIN (start_row + bctx -> nrows_per_thread ,bctx -> row_start + bctx -> total_rows ); 289if (start_row >=end_row )return ; 290 291FARF (HIGH ,"binary-same-shape: %d/%d (%u:%u) row-size %u (%u)" ,ith ,nth ,start_row ,end_row ,nb01 ,bctx -> dst_row_size_aligned ); 292 293uint8_t * src0_spad_base = octx -> src0_spad .data + (ith * octx -> src0_spad .size_per_thread ); 294uint8_t * src1_spad_base = octx -> src1_spad .data + (ith * octx -> src1_spad .size_per_thread ); 295uint8_t * dst_spad_base = octx -> dst_spad .data + (ith * octx -> dst_spad .size_per_thread ); 296 297size_t src0_spad_half = octx -> src0_spad .size_per_thread /2 ; 298size_t src1_spad_half = octx -> src1_spad .size_per_thread /2 ; 299size_t dst_spad_half = octx -> dst_spad .size_per_thread /2 ; 300 301dma_queue * q = octx -> ctx -> dma [ith ]; 302uint32_t ir_prefetch = start_row ; 303int spad_idx = 0 ; 304 305for (int k = 0 ;k < 2 && ir_prefetch < end_row ;k ++ ) { 306uint32_t current_block_size = calc_block_size (bctx ,ir_prefetch ,end_row ,ne01 ,ne02 ); 307uint32_t i03 ,i02 ,i01 ,rem ; 308i03 = fastdiv (ir_prefetch ,& bctx -> src0_dim12_div ); 309rem = ir_prefetch - i03 * (ne02 * ne01 ); 310i02 = fastdiv (rem ,& bctx -> src0_dim1_div ); 311i01 = rem - i02 * ne01 ; 312 313uint32_t i13 = (ne13 == 1 ) ?0 :i03 ; 314uint32_t i12 = (ne12 == 1 ) ?0 :i02 ; 315uint32_t i11 = (ne11 == 1 ) ?0 :i01 ; 316 317uint8_t * src0_curr = (uint8_t * )src0 -> data + i03 * nb03 + i02 * nb02 + i01 * nb01 ; 318uint8_t * src1_curr = (uint8_t * )src1 -> data + i13 * nb13 + i12 * nb12 + i11 * nb11 ; 319uint8_t * dst_curr = (uint8_t * )dst -> data + i03 * nb3 + i02 * nb2 + i01 * nb1 ; 320 321uint8_t * s0_spad = src0_spad_base + spad_idx * src0_spad_half ; 322uint8_t * s1_spad = src1_spad_base + spad_idx * src1_spad_half ; 323uint8_t * d_spad = dst_spad_base + spad_idx * dst_spad_half ; 324 325dma_queue_push (q ,dma_make_ptr (dst_curr ,d_spad ),nb1 ,bctx -> dst_row_size_aligned ,row_size_bytes ,0 ); 326dma_queue_push (q ,dma_make_ptr (s0_spad ,src0_curr ),bctx -> src0_row_size_aligned ,nb01 ,row_size_bytes ,current_block_size ); 327dma_queue_push (q ,dma_make_ptr (s1_spad ,src1_curr ),bctx -> src1_row_size_aligned ,nb11 ,row_size_bytes ,current_block_size ); 328ir_prefetch += current_block_size ; 329spad_idx ^=1 ; 330 } 331 332struct htp_thread_trace * tr = & octx -> ctx -> trace [ith ]; 333 334for (uint32_t ir = start_row ;ir < end_row ; ) { 335uint32_t current_block_size = calc_block_size (bctx ,ir ,end_row ,ne01 ,ne02 ); 336uint8_t * d_spad = (uint8_t * )dma_queue_pop (q ).src ; 337uint8_t * s0_spad = (uint8_t * )dma_queue_pop (q ).dst ; 338uint8_t * s1_spad = (uint8_t * )dma_queue_pop (q ).dst ; 339 340htp_trace_event_start (tr ,HTP_TRACE_EVT_HVX_COMP , (uint16_t )ir ); 341for (uint32_t r = 0 ;r < current_block_size ;r ++ ) { 342uint8_t * r_src0 = s0_spad + r * bctx -> src0_row_size_aligned ; 343uint8_t * r_src1 = s1_spad + r * bctx -> src1_row_size_aligned ; 344uint8_t * r_dst = d_spad + r * bctx -> dst_row_size_aligned ; 345COMPUTE_VECTOR_OP_AAA (r_dst ,r_src0 ,r_src1 ,src0_type ,ne00 ); 346 } 347htp_trace_event_stop (tr ,HTP_TRACE_EVT_HVX_COMP , (uint16_t )ir ); 348 349uint32_t i03 ,i02 ,i01 ,rem ; 350i03 = fastdiv (ir ,& bctx -> src0_dim12_div ); 351rem = ir - i03 * (ne02 * ne01 ); 352i02 = fastdiv (rem ,& bctx -> src0_dim1_div ); 353i01 = rem - i02 * ne01 ; 354uint8_t * dst_curr = (uint8_t * )dst -> data + i03 * nb3 + i02 * nb2 + i01 * nb1 ; 355dma_queue_push (q ,dma_make_ptr (dst_curr ,d_spad ),nb1 ,bctx -> dst_row_size_aligned ,row_size_bytes ,current_block_size ); 356 357if (ir_prefetch < end_row ) { 358uint32_t next_block_size = calc_block_size (bctx ,ir_prefetch ,end_row ,ne01 ,ne02 ); 359uint32_t p03 ,p02 ,p01 ,prem ; 360p03 = fastdiv (ir_prefetch ,& bctx -> src0_dim12_div ); 361prem = ir_prefetch - p03 * (ne02 * ne01 ); 362p02 = fastdiv (prem ,& bctx -> src0_dim1_div ); 363p01 = prem - p02 * ne01 ; 364 365uint32_t p13 = (ne13 == 1 ) ?0 :p03 ; 366uint32_t p12 = (ne12 == 1 ) ?0 :p02 ; 367uint32_t p11 = (ne11 == 1 ) ?0 :p01 ; 368 369uint8_t * s0_next = (uint8_t * )src0 -> data + p03 * nb03 + p02 * nb02 + p01 * nb01 ; 370uint8_t * s1_next = (uint8_t * )src1 -> data + p13 * nb13 + p12 * nb12 + p11 * nb11 ; 371 372dma_queue_push (q ,dma_make_ptr (s0_spad ,s0_next ),bctx -> src0_row_size_aligned ,nb01 ,row_size_bytes ,next_block_size ); 373dma_queue_push (q ,dma_make_ptr (s1_spad ,s1_next ),bctx -> src1_row_size_aligned ,nb11 ,row_size_bytes ,next_block_size ); 374 375ir_prefetch += next_block_size ; 376 } 377ir += current_block_size ; 378 } 379 380dma_queue_flush (q ); 381} 382 383// 3. Row Broadcast (ne11 == 1, ne12 == 1, single row src1) 384static void binary_job_vector_row_broadcast (unsigned int nth ,unsigned int ith ,void * data ) { 385struct htp_binary_context * bctx = (struct htp_binary_context * )data ; 386struct htp_ops_context * octx = bctx -> octx ; 387htp_binary_preamble ; 388 389const uint32_t src0_type = octx -> src [0 ]-> type ; 390const uint32_t row_size_bytes = (src0_type == HTP_TYPE_F32 ) ?ne00 * sizeof (float ) :ne00 * sizeof (_Float16 ); 391const uint32_t start_row = bctx -> row_start + bctx -> nrows_per_thread * ith ; 392const uint32_t end_row = MIN (start_row + bctx -> nrows_per_thread ,bctx -> row_start + bctx -> total_rows ); 393if (start_row >=end_row )return ; 394 395FARF (HIGH ,"binary-row-bcast: %d/%d (%u:%u) row-size %u (%u)" ,ith ,nth ,start_row ,end_row ,nb01 ,bctx -> dst_row_size_aligned ); 396 397uint8_t * src0_spad_base = octx -> src0_spad .data + (ith * octx -> src0_spad .size_per_thread ); 398uint8_t * src1_spad_base = octx -> src1_spad .data + (ith * octx -> src1_spad .size_per_thread ); 399uint8_t * dst_spad_base = octx -> dst_spad .data + (ith * octx -> dst_spad .size_per_thread ); 400 401size_t src0_spad_half = octx -> src0_spad .size_per_thread /2 ; 402size_t dst_spad_half = octx -> dst_spad .size_per_thread /2 ; 403 404dma_queue * q = octx -> ctx -> dma [ith ]; 405uint32_t ir_prefetch = start_row ; 406int spad_idx = 0 ; 407 408void * s1_ptr = (void * )src1_spad_base ; 409 410for (int k = 0 ;k < 2 && ir_prefetch < end_row ;k ++ ) { 411uint32_t current_block_size = calc_block_size (bctx ,ir_prefetch ,end_row ,ne01 ,ne02 ); 412uint32_t i03 = fastdiv (ir_prefetch ,& bctx -> src0_dim12_div ); 413uint32_t rem = ir_prefetch - i03 * (ne02 * ne01 ); 414uint32_t i02 = fastdiv (rem ,& bctx -> src0_dim1_div ); 415uint32_t i01 = rem - i02 * ne01 ; 416 417uint8_t * src0_curr = (uint8_t * )src0 -> data + i03 * nb03 + i02 * nb02 + i01 * nb01 ; 418uint8_t * dst_curr = (uint8_t * )dst -> data + i03 * nb3 + i02 * nb2 + i01 * nb1 ; 419 420uint8_t * s0_spad = src0_spad_base + spad_idx * src0_spad_half ; 421uint8_t * d_spad = dst_spad_base + spad_idx * dst_spad_half ; 422 423dma_queue_push (q ,dma_make_ptr (dst_curr ,d_spad ),nb1 ,bctx -> dst_row_size_aligned ,row_size_bytes ,0 ); 424dma_queue_push (q ,dma_make_ptr (s0_spad ,src0_curr ),bctx -> src0_row_size_aligned ,nb01 ,row_size_bytes ,current_block_size ); 425ir_prefetch += current_block_size ; 426spad_idx ^=1 ; 427 } 428 429struct htp_thread_trace * tr = & octx -> ctx -> trace [ith ]; 430 431for (uint32_t ir = start_row ;ir < end_row ; ) { 432uint32_t current_block_size = calc_block_size (bctx ,ir ,end_row ,ne01 ,ne02 ); 433uint8_t * d_spad = (uint8_t * )dma_queue_pop (q ).src ; 434uint8_t * s0_spad = (uint8_t * )dma_queue_pop (q ).dst ; 435 436htp_trace_event_start (tr ,HTP_TRACE_EVT_HVX_COMP , (uint16_t )ir ); 437for (uint32_t r = 0 ;r < current_block_size ;r ++ ) { 438uint8_t * r_src0 = s0_spad + r * bctx -> src0_row_size_aligned ; 439uint8_t * r_src1 = (uint8_t * )s1_ptr ;// Constant 440uint8_t * r_dst = d_spad + r * bctx -> dst_row_size_aligned ; 441COMPUTE_VECTOR_OP_AAA (r_dst ,r_src0 ,r_src1 ,src0_type ,ne00 ); 442 } 443htp_trace_event_stop (tr ,HTP_TRACE_EVT_HVX_COMP , (uint16_t )ir ); 444 445uint32_t i03 = fastdiv (ir ,& bctx -> src0_dim12_div ); 446uint32_t rem = ir - i03 * (ne02 * ne01 ); 447uint32_t i02 = fastdiv (rem ,& bctx -> src0_dim1_div ); 448uint32_t i01 = rem - i02 * ne01 ; 449uint8_t * dst_curr = (uint8_t * )dst -> data + i03 * nb3 + i02 * nb2 + i01 * nb1 ; 450dma_queue_push (q ,dma_make_ptr (dst_curr ,d_spad ),nb1 ,bctx -> dst_row_size_aligned ,row_size_bytes ,current_block_size ); 451 452if (ir_prefetch < end_row ) { 453uint32_t next_block_size = calc_block_size (bctx ,ir_prefetch ,end_row ,ne01 ,ne02 ); 454uint32_t p03 = fastdiv (ir_prefetch ,& bctx -> src0_dim12_div ); 455uint32_t prem = ir_prefetch - p03 * (ne02 * ne01 ); 456uint32_t p02 = fastdiv (prem ,& bctx -> src0_dim1_div ); 457uint32_t p01 = prem - p02 * ne01 ; 458uint8_t * s0_next = (uint8_t * )src0 -> data + p03 * nb03 + p02 * nb02 + p01 * nb01 ; 459dma_queue_push (q ,dma_make_ptr (s0_spad ,s0_next ),bctx -> src0_row_size_aligned ,nb01 ,row_size_bytes ,next_block_size ); 460ir_prefetch += next_block_size ; 461 } 462ir += current_block_size ; 463 } 464 465dma_queue_flush (q ); 466} 467 468// 4. Vector Complex (ne10 == ne00, complex broadcast) 469static void binary_job_vector_complex (unsigned int nth ,unsigned int ith ,void * data ) { 470struct htp_binary_context * bctx = (struct htp_binary_context * )data ; 471struct htp_ops_context * octx = bctx -> octx ; 472htp_binary_preamble ; 473 474const uint32_t src0_type = octx -> src [0 ]-> type ; 475const uint32_t row_size_bytes = (src0_type == HTP_TYPE_F32 ) ?ne00 * sizeof (float ) :ne00 * sizeof (_Float16 ); 476const uint32_t start_row = bctx -> row_start + bctx -> nrows_per_thread * ith ; 477const uint32_t end_row = MIN (start_row + bctx -> nrows_per_thread ,bctx -> row_start + bctx -> total_rows ); 478if (start_row >=end_row )return ; 479 480FARF (HIGH ,"binary-complex: %d/%d (%u:%u) row-size %u (%u)" ,ith ,nth ,start_row ,end_row ,nb01 ,bctx -> dst_row_size_aligned ); 481 482uint8_t * src0_spad_base = octx -> src0_spad .data + (ith * octx -> src0_spad .size_per_thread ); 483uint8_t * dst_spad_base = octx -> dst_spad .data + (ith * octx -> dst_spad .size_per_thread ); 484size_t src0_spad_half = octx -> src0_spad .size_per_thread /2 ; 485size_t dst_spad_half = octx -> dst_spad .size_per_thread /2 ; 486 487dma_queue * q = octx -> ctx -> dma [ith ]; 488uint32_t ir_prefetch = start_row ; 489int spad_idx = 0 ; 490 491for (int k = 0 ;k < 2 && ir_prefetch < end_row ;k ++ ) { 492uint32_t current_block_size = calc_block_size (bctx ,ir_prefetch ,end_row ,ne01 ,ne02 ); 493uint32_t i03 = fastdiv (ir_prefetch ,& bctx -> src0_dim12_div ); 494uint32_t rem = ir_prefetch - i03 * (ne02 * ne01 ); 495uint32_t i02 = fastdiv (rem ,& bctx -> src0_dim1_div ); 496uint32_t i01 = rem - i02 * ne01 ; 497 498uint8_t * src0_curr = (uint8_t * )src0 -> data + i03 * nb03 + i02 * nb02 + i01 * nb01 ; 499uint8_t * dst_curr = (uint8_t * )dst -> data + i03 * nb3 + i02 * nb2 + i01 * nb1 ; 500 501uint8_t * s0_spad = src0_spad_base + spad_idx * src0_spad_half ; 502uint8_t * d_spad = dst_spad_base + spad_idx * dst_spad_half ; 503 504dma_queue_push (q ,dma_make_ptr (dst_curr ,d_spad ),nb1 ,bctx -> dst_row_size_aligned ,row_size_bytes ,0 ); 505dma_queue_push (q ,dma_make_ptr (s0_spad ,src0_curr ),bctx -> src0_row_size_aligned ,nb01 ,row_size_bytes ,current_block_size ); 506ir_prefetch += current_block_size ; 507spad_idx ^=1 ; 508 } 509 510struct htp_thread_trace * tr = & octx -> ctx -> trace [ith ]; 511 512for (uint32_t ir = start_row ;ir < end_row ; ) { 513uint32_t current_block_size = calc_block_size (bctx ,ir ,end_row ,ne01 ,ne02 ); 514uint8_t * d_spad = (uint8_t * )dma_queue_pop (q ).src ; 515uint8_t * s0_spad = (uint8_t * )dma_queue_pop (q ).dst ; 516 517uint32_t i03 = fastdiv (ir ,& bctx -> src0_dim12_div ); 518uint32_t rem = ir - i03 * (ne02 * ne01 ); 519uint32_t i02 = fastdiv (rem ,& bctx -> src0_dim1_div ); 520uint32_t i01 = rem - i02 * ne01 ; 521 522htp_trace_event_start (tr ,HTP_TRACE_EVT_HVX_COMP , (uint16_t )ir ); 523for (uint32_t r = 0 ;r < current_block_size ;r ++ ) { 524uint32_t r_i01 = i01 + r ; 525uint32_t i13 = fastmodulo (i03 ,ne13 ,& bctx -> src1_dim3_div ); 526uint32_t i12 = fastmodulo (i02 ,ne12 ,& bctx -> src1_dim2_div ); 527uint32_t i11 = fastmodulo (r_i01 ,ne11 ,& bctx -> src1_dim1_div ); 528 529uint8_t * r_src0 = s0_spad + r * bctx -> src0_row_size_aligned ; 530uint8_t * r_src1 = (uint8_t * )src1 -> data + i13 * nb13 + i12 * nb12 + i11 * nb11 ; 531uint8_t * r_dst = d_spad + r * bctx -> dst_row_size_aligned ; 532 533// Read src1 from DDR (unaligned) 534COMPUTE_VECTOR_OP_AAU (r_dst ,r_src0 ,r_src1 ,src0_type ,ne00 ); 535 } 536htp_trace_event_stop (tr ,HTP_TRACE_EVT_HVX_COMP , (uint16_t )ir ); 537 538uint8_t * dst_curr = (uint8_t * )dst -> data + i03 * nb3 + i02 * nb2 + i01 * nb1 ; 539dma_queue_push (q ,dma_make_ptr (dst_curr ,d_spad ),nb1 ,bctx -> dst_row_size_aligned ,row_size_bytes ,current_block_size ); 540 541if (ir_prefetch < end_row ) { 542uint32_t next_block_size = calc_block_size (bctx ,ir_prefetch ,end_row ,ne01 ,ne02 ); 543uint32_t p03 = fastdiv (ir_prefetch ,& bctx -> src0_dim12_div ); 544uint32_t prem = ir_prefetch - p03 * (ne02 * ne01 ); 545uint32_t p02 = fastdiv (prem ,& bctx -> src0_dim1_div ); 546uint32_t p01 = prem - p02 * ne01 ; 547uint8_t * s0_next = (uint8_t * )src0 -> data + p03 * nb03 + p02 * nb02 + p01 * nb01 ; 548dma_queue_push (q ,dma_make_ptr (s0_spad ,s0_next ),bctx -> src0_row_size_aligned ,nb01 ,row_size_bytes ,next_block_size ); 549ir_prefetch += next_block_size ; 550 } 551ir += current_block_size ; 552 } 553 554dma_queue_flush (q ); 555} 556 557// 5. Element Repeat (ne10 != ne00) 558static void binary_job_element_repeat (unsigned int nth ,unsigned int ith ,void * data ) { 559struct htp_binary_context * bctx = (struct htp_binary_context * )data ; 560struct htp_ops_context * octx = bctx -> octx ; 561htp_binary_preamble ; 562 563const uint32_t src0_type = octx -> src [0 ]-> type ; 564const uint32_t elem_size_bytes = (src0_type == HTP_TYPE_F32 ) ?sizeof (float ) :sizeof (_Float16 ); 565const uint32_t row_size_bytes = ne00 * elem_size_bytes ;; 566const uint32_t start_row = bctx -> row_start + bctx -> nrows_per_thread * ith ; 567const uint32_t end_row = MIN (start_row + bctx -> nrows_per_thread ,bctx -> row_start + bctx -> total_rows ); 568if (start_row >=end_row )return ; 569 570uint8_t * src0_spad_base = octx -> src0_spad .data + (ith * octx -> src0_spad .size_per_thread ); 571uint8_t * dst_spad_base = octx -> dst_spad .data + (ith * octx -> dst_spad .size_per_thread ); 572size_t src0_spad_half = octx -> src0_spad .size_per_thread /2 ; 573size_t dst_spad_half = octx -> dst_spad .size_per_thread /2 ; 574 575FARF (HIGH ,"binary-repeat: %d/%d (%u:%u) row-size %u (%u)" ,ith ,nth ,start_row ,end_row ,nb01 ,bctx -> dst_row_size_aligned ); 576 577dma_queue * q = octx -> ctx -> dma [ith ]; 578uint32_t ir_prefetch = start_row ; 579int spad_idx = 0 ; 580 581for (int k = 0 ;k < 2 && ir_prefetch < end_row ;k ++ ) { 582uint32_t current_block_size = calc_block_size (bctx ,ir_prefetch ,end_row ,ne01 ,ne02 ); 583uint32_t i03 = fastdiv (ir_prefetch ,& bctx -> src0_dim12_div ); 584uint32_t rem = ir_prefetch - i03 * (ne02 * ne01 ); 585uint32_t i02 = fastdiv (rem ,& bctx -> src0_dim1_div ); 586uint32_t i01 = rem - i02 * ne01 ; 587 588uint8_t * src0_curr = (uint8_t * )src0 -> data + i03 * nb03 + i02 * nb02 + i01 * nb01 ; 589uint8_t * dst_curr = (uint8_t * )dst -> data + i03 * nb3 + i02 * nb2 + i01 * nb1 ; 590 591uint8_t * s0_spad = src0_spad_base + spad_idx * src0_spad_half ; 592uint8_t * d_spad = dst_spad_base + spad_idx * dst_spad_half ; 593 594dma_queue_push (q ,dma_make_ptr (dst_curr ,d_spad ),nb1 ,bctx -> dst_row_size_aligned ,row_size_bytes ,0 ); 595dma_queue_push (q ,dma_make_ptr (s0_spad ,src0_curr ),bctx -> src0_row_size_aligned ,nb01 ,row_size_bytes ,current_block_size ); 596ir_prefetch += current_block_size ; 597spad_idx ^=1 ; 598 } 599 600struct htp_thread_trace * tr = & octx -> ctx -> trace [ith ]; 601 602for (uint32_t ir = start_row ;ir < end_row ; ) { 603uint32_t current_block_size = calc_block_size (bctx ,ir ,end_row ,ne01 ,ne02 ); 604uint8_t * d_spad = (uint8_t * )dma_queue_pop (q ).src ; 605uint8_t * s0_spad = (uint8_t * )dma_queue_pop (q ).dst ; 606 607uint32_t i03 = fastdiv (ir ,& bctx -> src0_dim12_div ); 608uint32_t rem = ir - i03 * (ne02 * ne01 ); 609uint32_t i02 = fastdiv (rem ,& bctx -> src0_dim1_div ); 610uint32_t i01 = rem - i02 * ne01 ; 611 612htp_trace_event_start (tr ,HTP_TRACE_EVT_HVX_COMP , (uint16_t )ir ); 613for (uint32_t r = 0 ;r < current_block_size ;r ++ ) { 614uint32_t r_i01 = i01 + r ; 615uint32_t i13 = fastmodulo (i03 ,ne13 ,& bctx -> src1_dim3_div ); 616uint32_t i12 = fastmodulo (i02 ,ne12 ,& bctx -> src1_dim2_div ); 617uint32_t i11 = fastmodulo (r_i01 ,ne11 ,& bctx -> src1_dim1_div ); 618 619uint8_t * r_src0 = s0_spad + r * bctx -> src0_row_size_aligned ; 620uint8_t * r_src1_row = (uint8_t * )src1 -> data + i13 * nb13 + i12 * nb12 + i11 * nb11 ; 621uint8_t * r_dst = d_spad + r * bctx -> dst_row_size_aligned ; 622 623// Repeat src1 row 624for (uint32_t c = 0 ;c < ne00 ;c += ne10 ) { 625uint32_t len = MIN (ne10 ,ne00 - c ); 626// Use UUU for speed and simplicity 627COMPUTE_VECTOR_OP_UUU (r_dst + c * elem_size_bytes ,r_src0 + c * elem_size_bytes ,r_src1_row ,src0_type ,len ); 628 } 629 } 630htp_trace_event_stop (tr ,HTP_TRACE_EVT_HVX_COMP , (uint16_t )ir ); 631 632uint8_t * dst_curr = (uint8_t * )dst -> data + i03 * nb3 + i02 * nb2 + i01 * nb1 ; 633dma_queue_push (q ,dma_make_ptr (dst_curr ,d_spad ),nb1 ,bctx -> dst_row_size_aligned ,row_size_bytes ,current_block_size ); 634 635if (ir_prefetch < end_row ) { 636uint32_t next_block_size = calc_block_size (bctx ,ir_prefetch ,end_row ,ne01 ,ne02 ); 637uint32_t p03 = fastdiv (ir_prefetch ,& bctx -> src0_dim12_div ); 638uint32_t prem = ir_prefetch - p03 * (ne02 * ne01 ); 639uint32_t p02 = fastdiv (prem ,& bctx -> src0_dim1_div ); 640uint32_t p01 = prem - p02 * ne01 ; 641uint8_t * s0_next = (uint8_t * )src0 -> data + p03 * nb03 + p02 * nb02 + p01 * nb01 ; 642dma_queue_push (q ,dma_make_ptr (s0_spad ,s0_next ),bctx -> src0_row_size_aligned ,nb01 ,row_size_bytes ,next_block_size ); 643ir_prefetch += next_block_size ; 644 } 645ir += current_block_size ; 646 } 647 648dma_queue_flush (q ); 649} 650 651// 6. ADD_ID (src1 gathered via src2 indices) 652static void binary_job_add_id (unsigned int nth ,unsigned int ith ,void * data ) { 653struct htp_binary_context * bctx = (struct htp_binary_context * )data ; 654struct htp_ops_context * octx = bctx -> octx ; 655 656const struct htp_tensor * src0 = octx -> src [0 ]; 657const struct htp_tensor * src1 = octx -> src [1 ]; 658const struct htp_tensor * src2 = octx -> src [2 ]; 659const struct htp_tensor * dst = octx -> dst ; 660 661const uint32_t ne00 = src0 -> ne [0 ]; 662const uint32_t ne01 = src0 -> ne [1 ]; 663const uint32_t ne02 = src0 -> ne [2 ]; 664const uint32_t ne03 = src0 -> ne [3 ]; 665const uint32_t ne11 = src1 -> ne [1 ];// for bounds check 666 667const uint32_t nb01 = src0 -> nb [1 ]; 668const uint32_t nb02 = src0 -> nb [2 ]; 669const uint32_t nb03 = src0 -> nb [3 ]; 670const uint32_t nb11 = src1 -> nb [1 ];// src1 row stride 671 672const uint32_t nb1 = dst -> nb [1 ]; 673const uint32_t nb2 = dst -> nb [2 ]; 674const uint32_t nb3 = dst -> nb [3 ]; 675 676const uint32_t start_row = bctx -> row_start + bctx -> nrows_per_thread * ith ; 677const uint32_t end_row = MIN (start_row + bctx -> nrows_per_thread ,bctx -> row_start + bctx -> total_rows ); 678if (start_row >=end_row )return ; 679 680uint8_t * src0_spad_base = octx -> src0_spad .data + (ith * octx -> src0_spad .size_per_thread ); 681uint8_t * dst_spad_base = octx -> dst_spad .data + (ith * octx -> dst_spad .size_per_thread ); 682size_t src0_spad_half = octx -> src0_spad .size_per_thread /2 ; 683size_t dst_spad_half = octx -> dst_spad .size_per_thread /2 ; 684 685dma_queue * q = octx -> ctx -> dma [ith ]; 686uint32_t ir_prefetch = start_row ; 687int spad_idx = 0 ; 688 689for (int k = 0 ;k < 2 && ir_prefetch < end_row ;k ++ ) { 690uint32_t current_block_size = calc_block_size (bctx ,ir_prefetch ,end_row ,ne01 ,ne02 ); 691uint32_t i03 = fastdiv (ir_prefetch ,& bctx -> src0_dim12_div ); 692uint32_t rem = ir_prefetch - i03 * (ne02 * ne01 ); 693uint32_t i02 = fastdiv (rem ,& bctx -> src0_dim1_div ); 694uint32_t i01 = rem - i02 * ne01 ; 695 696uint8_t * src0_curr = (uint8_t * )src0 -> data + i03 * nb03 + i02 * nb02 + i01 * nb01 ; 697uint8_t * dst_curr = (uint8_t * )dst -> data + i03 * nb3 + i02 * nb2 + i01 * nb1 ; 698 699uint8_t * s0_spad = src0_spad_base + spad_idx * src0_spad_half ; 700uint8_t * d_spad = dst_spad_base + spad_idx * dst_spad_half ; 701 702dma_queue_push (q ,dma_make_ptr (dst_curr ,d_spad ),nb1 ,bctx -> dst_row_size_aligned ,ne00 * sizeof (float ),0 ); 703dma_queue_push (q ,dma_make_ptr (s0_spad ,src0_curr ),bctx -> src0_row_size_aligned ,nb01 ,ne00 * sizeof (float ),current_block_size ); 704ir_prefetch += current_block_size ; 705spad_idx ^=1 ; 706 } 707 708struct htp_thread_trace * tr = & octx -> ctx -> trace [ith ]; 709 710for (uint32_t ir = start_row ;ir < end_row ; ) { 711uint32_t current_block_size = calc_block_size (bctx ,ir ,end_row ,ne01 ,ne02 ); 712uint8_t * d_spad = (uint8_t * )dma_queue_pop (q ).src ; 713uint8_t * s0_spad = (uint8_t * )dma_queue_pop (q ).dst ; 714 715uint32_t i03 = fastdiv (ir ,& bctx -> src0_dim12_div ); 716uint32_t rem = ir - i03 * (ne02 * ne01 ); 717uint32_t i02 = fastdiv (rem ,& bctx -> src0_dim1_div ); 718uint32_t i01 = rem - i02 * ne01 ; 719 720htp_trace_event_start (tr ,HTP_TRACE_EVT_HVX_COMP , (uint16_t )ir ); 721for (uint32_t r = 0 ;r < current_block_size ;r ++ ) { 722uint32_t r_i01 = i01 + r ;// linear within block since we split at ne01 723 724const int32_t idx = * (int32_t * )((char * )src2 -> data + r_i01 * src2 -> nb [0 ]+ i02 * src2 -> nb [1 ]); 725 726uint8_t * r_src1 = (uint8_t * )src1 -> data + idx * nb11 ; 727uint8_t * r_src0 = s0_spad + r * bctx -> src0_row_size_aligned ; 728uint8_t * r_dst = d_spad + r * bctx -> dst_row_size_aligned ; 729 730hvx_add_f32_aau (r_dst ,r_src0 ,r_src1 ,ne00 ); 731 } 732htp_trace_event_stop (tr ,HTP_TRACE_EVT_HVX_COMP , (uint16_t )ir ); 733 734uint8_t * dst_curr = (uint8_t * )dst -> data + i03 * nb3 + i02 * nb2 + i01 * nb1 ; 735dma_queue_push (q ,dma_make_ptr (dst_curr ,d_spad ),nb1 ,bctx -> dst_row_size_aligned ,ne00 * sizeof (float ),current_block_size ); 736 737if (ir_prefetch < end_row ) { 738uint32_t next_block_size = calc_block_size (bctx ,ir_prefetch ,end_row ,ne01 ,ne02 ); 739uint32_t p03 = fastdiv (ir_prefetch ,& bctx -> src0_dim12_div ); 740uint32_t prem = ir_prefetch - p03 * (ne02 * ne01 ); 741uint32_t p02 = fastdiv (prem ,& bctx -> src0_dim1_div ); 742uint32_t p01 = prem - p02 * ne01 ; 743uint8_t * s0_next = (uint8_t * )src0 -> data + p03 * nb03 + p02 * nb02 + p01 * nb01 ; 744dma_queue_push (q ,dma_make_ptr (s0_spad ,s0_next ),bctx -> src0_row_size_aligned ,nb01 ,ne00 * sizeof (float ),next_block_size ); 745ir_prefetch += next_block_size ; 746 } 747ir += current_block_size ; 748 } 749 750dma_queue_flush (q ); 751} 752 753static int execute_op_binary (struct htp_ops_context * octx ) { 754const struct htp_tensor * src0 = octx -> src [0 ]; 755const struct htp_tensor * src1 = octx -> src [1 ]; 756const struct htp_tensor * dst = octx -> dst ; 757 758const uint32_t src0_nrows = src0 -> ne [1 ]* src0 -> ne [2 ]* src0 -> ne [3 ]; 759 760// Use packed row sizes for VTCM allocation and alignment 761const uint32_t src0_type = octx -> src [0 ]-> type ; 762const size_t elem_size = (src0_type == HTP_TYPE_F32 ) ?sizeof (float ) :sizeof (_Float16 ); 763const size_t src0_row_size = src0 -> ne [0 ]* elem_size ; 764const size_t src1_row_size = src1 -> ne [0 ]* elem_size ; 765const size_t dst_row_size = dst -> ne [0 ]* elem_size ; 766 767uint32_t row_start = 0 ; 768uint32_t nrows = src0_nrows ; 769 770if (octx -> ctx -> mdev .count > 1 ) { 771uint32_t rows_per_chunk = 0 ; 772htp_tensor_mdev_rows_per_chunk (dst , (uint32_t )elem_size , (uint32_t )dst_row_size ,& rows_per_chunk ); 773const 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 ); 774row_start = range .start ; 775nrows = range .count ; 776 } 777 778if (nrows == 0 ) { 779return HTP_STATUS_OK ; 780 } 781 782const uint32_t n_threads = octx -> n_threads ; 783 784size_t src0_row_size_aligned = hex_round_up (src0_row_size ,VLEN ); 785size_t src1_row_size_aligned = hex_round_up (src1_row_size ,VLEN ); 786size_t dst_row_size_aligned = hex_round_up (dst_row_size ,VLEN ); 787 788bool is_add_id = (octx -> op == HTP_OP_ADD_ID ); 789bool is_scalar = !is_add_id && (src1 -> ne [0 ]== 1 ); 790 791bool is_transposed = (src0 -> nb [1 ]< src0_row_size || src1 -> nb [1 ]< src1_row_size || dst -> nb [1 ]< dst_row_size ); 792 793bool is_same_shape = !is_add_id && !is_scalar && !is_transposed && 794 (src1 -> ne [0 ]== src0 -> ne [0 ]&& src0 -> ne [0 ] %VLEN == 0 )&& 795 (src1 -> ne [1 ]== src0 -> ne [1 ]|| src1 -> ne [1 ]== 1 )&& 796 (src1 -> ne [2 ]== src0 -> ne [2 ]|| src1 -> ne [2 ]== 1 )&& 797 (src1 -> ne [3 ]== src0 -> ne [3 ]|| src1 -> ne [3 ]== 1 ); 798 799bool is_row_bcast = is_same_shape && (src1 -> ne [1 ]== 1 && src1 -> ne [2 ]== 1 && src1 -> ne [3 ]== 1 ); 800bool is_complex = !is_add_id && !is_scalar && !is_same_shape && (src1 -> ne [0 ]== src0 -> ne [0 ]); 801bool is_repeat = !is_add_id && !is_scalar && !is_same_shape && (src1 -> ne [0 ]!= src0 -> ne [0 ]); 802 803size_t spad_row_total ; 804if (is_same_shape ) { 805spad_row_total = 2 * (src0_row_size_aligned + src1_row_size_aligned + dst_row_size_aligned ); 806 }else { 807spad_row_total = 2 * (src0_row_size_aligned + dst_row_size_aligned ); 808 } 809 810size_t rows_per_buffer = octx -> ctx -> vtcm_size / (n_threads * spad_row_total ); 811 812// Adjust for static src1 in row_bcast case 813if (is_row_bcast ) { 814size_t needed_static = src1_row_size_aligned ; 815if (octx -> ctx -> vtcm_size < needed_static )return HTP_STATUS_VTCM_TOO_SMALL ; 816size_t avail = octx -> ctx -> vtcm_size - needed_static ; 817rows_per_buffer = avail / (n_threads * spad_row_total ); 818 } 819 820if (rows_per_buffer < 1 ) { 821FARF (ERROR ,"binary: VTCM too small\n" ); 822return HTP_STATUS_VTCM_TOO_SMALL ; 823 } 824 825octx -> src0_spad .size_per_thread = rows_per_buffer * 2 * src0_row_size_aligned ; 826octx -> dst_spad .size_per_thread = rows_per_buffer * 2 * dst_row_size_aligned ; 827 828if (is_add_id || is_scalar || is_complex || is_repeat || is_row_bcast ) { 829octx -> src1_spad .size_per_thread = 0 ; 830 }else { 831octx -> src1_spad .size_per_thread = rows_per_buffer * 2 * src1_row_size_aligned ; 832 } 833 834octx -> dst_spad .size = n_threads * octx -> dst_spad .size_per_thread ; 835octx -> src0_spad .size = n_threads * octx -> src0_spad .size_per_thread ; 836if (is_row_bcast ) { 837octx -> src1_spad .size = src1_row_size_aligned ; 838 }else { 839octx -> src1_spad .size = n_threads * octx -> src1_spad .size_per_thread ; 840 } 841 842if (octx -> ctx -> vtcm_size < (octx -> src0_spad .size + octx -> src1_spad .size + octx -> dst_spad .size )) { 843return HTP_STATUS_VTCM_TOO_SMALL ; 844 } 845 846octx -> src0_spad .data = octx -> ctx -> vtcm_base ;octx -> src0_spad .src = NULL ; 847octx -> src1_spad .data = octx -> src0_spad .data + octx -> src0_spad .size ;octx -> src1_spad .src = NULL ; 848octx -> dst_spad .data = octx -> src1_spad .data + octx -> src1_spad .size ;octx -> dst_spad .src = NULL ; 849 850if ((octx -> flags & HTP_OPFLAGS_SKIP_COMPUTE )) { 851return HTP_STATUS_OK ; 852 } 853 854dma_queue * q = octx -> ctx -> dma [0 ]; 855if (is_row_bcast ) { 856dma_queue_push (q ,dma_make_ptr (octx -> src1_spad .data , (const void * )src1 -> data ),src1_row_size_aligned ,0 ,src1 -> ne [0 ]* elem_size ,1 ); 857 } 858 859struct htp_binary_context bctx ; 860bctx .octx = octx ; 861bctx .nrows_per_thread = fastdiv (nrows + n_threads - 1 ,& octx -> n_threads_div ); 862bctx .total_rows = nrows ; 863bctx .row_start = row_start ; 864bctx .block_max = rows_per_buffer ; 865bctx .src0_row_size_aligned = src0_row_size_aligned ; 866bctx .src1_row_size_aligned = src1_row_size_aligned ; 867bctx .dst_row_size_aligned = dst_row_size_aligned ; 868 869bctx .src0_dim1_div = init_fastdiv_values (src0 -> ne [1 ]); 870bctx .src0_dim2_div = init_fastdiv_values (src0 -> ne [2 ]); 871bctx .src0_dim12_div = init_fastdiv_values (src0 -> ne [1 ]* src0 -> ne [2 ]); 872 873bctx .src1_dim1_div = init_fastdiv_values (src1 -> ne [1 ]); 874bctx .src1_dim2_div = init_fastdiv_values (src1 -> ne [2 ]); 875bctx .src1_dim3_div = init_fastdiv_values (src1 -> ne [3 ]); 876 877bool src0_contig_dim1 = (src0 -> nb [2 ]== src0 -> ne [1 ]* src0 -> nb [1 ]); 878bool dst_contig_dim1 = (dst -> nb [2 ]== src0 -> ne [1 ]* dst -> nb [1 ]); 879 880bool src0_contig_dim2 = (src0 -> nb [3 ]== src0 -> ne [2 ]* src0 -> nb [2 ]); 881bool dst_contig_dim2 = (dst -> nb [3 ]== src0 -> ne [2 ]* dst -> nb [2 ]); 882 883bctx .split_at_ne01 = (src0 -> ne [2 ]> 1 )&& ((src1 -> ne [1 ]> 1 )|| (src1 -> ne [2 ]> 1 )|| !src0_contig_dim1 || !dst_contig_dim1 ); 884bctx .split_at_ne02 = (src0 -> ne [3 ]> 1 )&& ((src1 -> ne [2 ]> 1 )|| (src1 -> ne [3 ]> 1 )|| !src0_contig_dim2 || !dst_contig_dim2 ); 885 886worker_callback_t worker_func ; 887if (is_add_id )worker_func = binary_job_add_id ; 888else if (is_scalar )worker_func = binary_job_scalar ; 889else if (is_row_bcast )worker_func = binary_job_vector_row_broadcast ; 890else if (is_same_shape )worker_func = binary_job_vector_same_shape ; 891else if (is_complex )worker_func = binary_job_vector_complex ; 892else worker_func = binary_job_element_repeat ; 893 894if (is_row_bcast ) { 895dma_queue_pop (q ); 896 } 897 898work_queue_run (octx -> ctx -> work_queue ,worker_func ,& bctx ,n_threads ); 899 900return HTP_STATUS_OK ; 901} 902 903int op_binary (struct htp_ops_context * octx ) { 904 905// Does not support permutations of src1 906const struct htp_tensor * src1 = octx -> src [1 ]; 907if (src1 -> nb [1 ]< src1 -> nb [0 ]) { 908return HTP_STATUS_NO_SUPPORT ; 909 } 910 911const uint32_t src0_type = octx -> src [0 ]-> type ; 912if ((src0_type == HTP_TYPE_F32 )|| (src0_type == HTP_TYPE_F16 )) { 913return execute_op_binary (octx ); 914 } 915 916return HTP_STATUS_NO_SUPPORT ; 917}