char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
eafe15a5e
char/aliceai-t5-moe
1#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" 2#pragma clang diagnostic ignored "-Wunused-function" 3#pragma clang diagnostic ignored "-Wunused-variable" 4#pragma clang diagnostic ignored "-Wunused-but-set-variable" 5 6#include <HAP_farf.h> 7#include <HAP_perf.h> 8#include <AEEStdErr.h> 9#include <dspqueue.h> 10#include <HAP_compute_res.h> 11#include <HAP_etm_config.h> 12#include <HAP_mem.h> 13#include <HAP_power.h> 14#include <HAP_ps.h> 15#include <HAP_dcvs.h> 16#include <qurt.h> 17#include <qurt_thread.h> 18#include <qurt_memory.h> 19#include <remote.h> 20#include <string.h> 21#include <stdatomic.h> 22 23#include "hex-utils.h" 24#include "hex-dma.h" 25#include "hmx-queue.h" 26 27#define GGML_COMMON_DECL_C 28#include "ggml-common.h" 29#include "hex-bitmap.h" 30#include "htp-ctx.h" 31#include "htp-ops.h" 32#include "htp-tensor.h" 33#include "htp_iface.h" 34#include "work-queue.h" 35#include "hex-profile.h" 36#include "allreduce-ops.h" 37#include "htp-fence.h" 38 39#define HMX_QUEUE_CAPACITY 16 40#define HMX_QUEUE_STACK_SIZE 16384 41#define WORK_QUEUE_CAPACITY 16 42#define WORK_QUEUE_STACK_SIZE 16384 43#define MAIN_THREAD_STACK_SIZE 32768 44 45_Static_assert (WORK_QUEUE_MAX_N_THREADS >=HTP_MAX_NTHREADS , 46"work-queue thread cap must be >= HTP_MAX_NTHREADS" ); 47 48struct htp_handle { 49struct htp_context * ctx ; 50}; 51 52static inline void * htp_mmap (uint32_t fd ,uint32_t size ) { 53void * va = (void * )-1 ; 54for (int retry = 0 ;retry < 2 ;retry ++ ) { 55#if __HVX_ARCH__ > 73 56va = HAP_mmap2 (NULL ,size ,HAP_PROT_READ |HAP_PROT_WRITE ,0 ,fd ,0 ); 57#else 58if (size > HTP_MMAP_MAX_VMEM ) { 59FARF (ERROR ,"mmap failed : size %u exceeds 2GB limit for HAP_mmap" , (uint32_t )size ); 60abort (); 61 } 62va = HAP_mmap (NULL ,size ,HAP_PROT_READ |HAP_PROT_WRITE ,0 ,fd ,0 ); 63#endif 64if (va != (void * )-1 && va != NULL ) { 65return va ; 66 } 67if (retry == 0 ) { 68FARF (HIGH ,"mmap failed first try (va %p fd %u size %u), retrying..." ,va ,fd ,size ); 69 } 70 } 71return NULL ; 72} 73 74static inline void htp_munmap (void * va ,uint32_t size ) { 75#if __HVX_ARCH__ > 73 76HAP_munmap2 (va ,size ); 77#else 78HAP_munmap (va ,size ); 79#endif 80} 81 82AEEResult htp_iface_open (const char * uri ,remote_handle64 * handle ) { 83 (void )uri ; 84struct htp_handle * h = calloc (1 ,sizeof (* h )); 85if (h == NULL ) { 86return AEE_ENOMEMORY ; 87 } 88 89* handle = (remote_handle64 )h ; 90return AEE_SUCCESS ; 91} 92 93AEEResult htp_iface_etm (remote_handle64 handle ,uint32_t enable ) { 94struct htp_handle * h = (struct htp_handle * )handle ; 95if (!h ) { 96return AEE_EBADPARM ; 97 } 98 99int err = enable ?HAP_user_etm_enable () :HAP_user_etm_disable (); 100if (err ) { 101if (err == AEE_EVERSIONNOTSUPPORT ) { 102FARF (ERROR ,"API HAP_user_etm_enable/disable is not supported\n" ); 103 }else { 104FARF (ERROR ,"Error executing HAP_user_etm_enable/disable with error code : 0x%x\n" ,err ); 105 } 106 } 107return err ; 108} 109 110AEEResult htp_iface_profiler (remote_handle64 handle ,uint32_t mode ,const htp_iface_pmu_conf * pmu_conf ) { 111struct htp_handle * h = (struct htp_handle * )handle ; 112if (!h || !h -> ctx ) { 113return AEE_EBADPARM ; 114 } 115struct htp_context * ctx = h -> ctx ; 116 117if (mode == HTP_PROF_PMU ) { 118const uint32_t * events = pmu_conf -> events ; 119 120// Pack 4 event IDs (low 8 bits) into each 32-bit config register 121uint32_t evtcfg = 0 ,evtcfg1 = 0 ,cfg = 0 ,i = 0 ; 122for (;i < HEX_NUM_PMU_COUNTERS /2 ;i ++ ) { 123evtcfg |= ((events [i + 0 ]& 0xFF ) << (i * 8 )); 124evtcfg1 |= ((events [i + 4 ]& 0xFF ) << (i * 8 )); 125 } 126 127// For events >255 pack high 2 bits of all 8 event IDs into cfg register 128// 2 bits per counter: bits [1:0] for counter 0, [3:2] for counter 1, etc. 129for (i = 0 ;i < HEX_NUM_PMU_COUNTERS ;i ++ ) { 130cfg |= (((events [i ] >>8 )& 3 ) << (i * 2 )); 131 } 132 133FARF (ALWAYS ,"Configuring PMU registers: evtcfg = 0x%x, evtcfg1 = 0x%x, pmucfg = 0x%x" ,evtcfg ,evtcfg1 ,cfg ); 134 135// Configure PMU registers 136qurt_pmu_set (QURT_PMUCFG ,cfg ); 137qurt_pmu_set (QURT_PMUEVTCFG ,evtcfg ); 138qurt_pmu_set (QURT_PMUEVTCFG1 ,evtcfg1 ); 139qurt_pmu_enable (1 ); 140 } 141 142ctx -> profiler = mode ; 143 144return AEE_SUCCESS ; 145} 146 147AEEResult htp_iface_close (remote_handle64 handle ) { 148struct htp_handle * h = (struct htp_handle * )handle ; 149if (!h ) { 150return AEE_EBADPARM ; 151 } 152 153struct htp_context * ctx = h -> ctx ; 154if (ctx ) { 155if (ctx -> dsp_queue ) { 156FARF (ERROR ,"Closing handle with queue still open" ); 157return AEE_EITEMBUSY ; 158 } 159 160// release the mmaps (if any) 161for (uint32_t i = 0 ;i < HTP_MAX_MMAPS ;i ++ ) { 162if (ctx -> mmap [i ].size ) { 163htp_munmap ((void * )ctx -> mmap [i ].base ,ctx -> mmap [i ].size ); 164ctx -> mmap [i ].size = 0 ; 165ctx -> mmap [i ].base = NULL ; 166ctx -> mmap [i ].fd = -1 ; 167 } 168 } 169 170if (ctx -> profiler ) { 171qurt_pmu_enable (1 ); 172 } 173 174if (ctx -> etm ) { 175HAP_user_etm_disable (); 176 } 177 178// Free the unified block (ctx is the base address of the block) 179free (ctx ); 180h -> ctx = NULL ; 181 } 182 183free (h ); 184return AEE_SUCCESS ; 185} 186 187AEEResult htp_iface_mmap (remote_handle64 handle ,uint32_t fd ,uint32_t size ) { 188struct htp_handle * h = (struct htp_handle * )handle ; 189if (!h || !h -> ctx ) { 190return AEE_EBADPARM ; 191 } 192struct htp_context * ctx = h -> ctx ; 193 194// See if we already have this mapping 195for (uint32_t i = 0 ;i < HTP_MAX_MMAPS ;i ++ ) { 196struct htp_mmap * m = & ctx -> mmap [i ]; 197if (m -> fd == fd ) { 198return AEE_SUCCESS ; 199 } 200 } 201 202// Add new mapping 203for (uint32_t i = 0 ;i < HTP_MAX_MMAPS ;i ++ ) { 204struct htp_mmap * m = & ctx -> mmap [i ]; 205if (!m -> size ) { 206FARF (HIGH ,"mmap : fd %u size %u" ,fd ,size ); 207void * va = htp_mmap (fd ,size ); 208if (va == NULL ) { 209FARF (ERROR ,"mmap failed : fd %u size %u" ,fd , (uint32_t )size ); 210return AEE_EFAILED ; 211 } 212 213m -> base = (uint64_t )va ; 214m -> fd = fd ; 215m -> size = size ; 216 217return AEE_SUCCESS ; 218 } 219 } 220 221return AEE_ENOMEMORY ; 222} 223 224AEEResult htp_iface_munmap (remote_handle64 handle ,uint32 fd ) { 225struct htp_handle * h = (struct htp_handle * )handle ; 226if (!h || !h -> ctx ) { 227return AEE_EBADPARM ; 228 } 229struct htp_context * ctx = h -> ctx ; 230 231for (uint32_t i = 0 ;i < HTP_MAX_MMAPS ;i ++ ) { 232struct htp_mmap * m = & ctx -> mmap [i ]; 233if (fd < 0 || m -> fd == fd ) { 234FARF (HIGH ,"unmmap : base %p fd %u size %u" , (void * )m -> base ,m -> fd , (uint32_t )m -> size ); 235htp_munmap ((void * )m -> base ,m -> size ); 236m -> size = 0 ; 237m -> base = NULL ; 238m -> fd = -1 ; 239 } 240 } 241 242return AEE_SUCCESS ; 243} 244 245static void vtcm_acquire (struct htp_context * ctx ) { 246if (!ctx -> vtcm_valid ) { 247int err = HAP_compute_res_acquire_cached (ctx -> vtcm_rctx ,10000000u ); 248if (err != 0 ) { 249FARF (ERROR ,"ggml-hex: failed to acquire VTCM: 0x%08x" , (unsigned )err ); 250abort (); 251 } 252 253ctx -> vtcm_needs_release = false; 254ctx -> vtcm_valid = true; 255 256// Drop the priority to make sure we get the release callback from other GGML-HTP and QNN-HTP sessions 257HAP_compute_res_update_priority (ctx -> vtcm_rctx ,ctx -> thread_prio + 10 ); 258 } 259} 260 261static void vtcm_release (struct htp_context * ctx ) { 262if (ctx -> vtcm_valid ) { 263ctx -> vtcm_valid = false; 264ctx -> vtcm_needs_release = false; 265HAP_compute_res_release_cached (ctx -> vtcm_rctx ); 266 } 267} 268 269static int vtcm_release_callback (unsigned int rctx ,void * state ) { 270struct htp_context * ctx = (struct htp_context * )state ; 271ctx -> vtcm_needs_release = true; 272return 0 ; 273} 274 275static int vtcm_alloc (struct htp_context * ctx ) { 276unsigned int vtcm_size = 8 * 1024 * 1024 ;// 8MB default 277HAP_compute_res_query_VTCM (0 ,& vtcm_size ,NULL ,NULL ,NULL ); 278 279compute_res_attr_t attr ; 280HAP_compute_res_attr_init (& attr ); 281HAP_compute_res_attr_set_serialize (& attr ,0 ); 282HAP_compute_res_attr_set_cache_mode (& attr ,1 ); 283HAP_compute_res_attr_set_vtcm_param_v2 (& attr ,vtcm_size ,vtcm_size ,vtcm_size );// single page 284HAP_compute_res_attr_set_release_callback (& attr ,vtcm_release_callback , (void * )ctx ); 285HAP_compute_res_attr_set_hmx_param (& attr ,1 ); 286 287// Allocate VTCM for scratch pads 288uint32_t rctx = HAP_compute_res_acquire (& attr ,1000000 /* timeout */ ); 289if (!rctx ) { 290FARF (ERROR ,"failed to allocate %zu bytes VTCM\n" ,ctx -> vtcm_size ); 291return AEE_ENOMEMORY ; 292 } 293 294void * vtcm_ptr ; 295if (HAP_compute_res_attr_get_vtcm_ptr_v2 (& attr ,& vtcm_ptr ,& vtcm_size )!= 0 ) { 296HAP_compute_res_release (rctx ); 297FARF (ERROR ,"failed to allocate %zu bytes VTCM (new)\n" ,ctx -> vtcm_size ); 298return AEE_ENOMEMORY ; 299 } 300 301ctx -> vtcm_base = (uint8_t * )vtcm_ptr ; 302ctx -> vtcm_size = vtcm_size ; 303ctx -> vtcm_rctx = rctx ; 304ctx -> vtcm_valid = false; 305ctx -> vtcm_needs_release = false; 306 307return 0 ; 308} 309 310static void vtcm_free (struct htp_context * ctx ) { 311if (ctx -> vtcm_rctx ) { 312HAP_compute_res_release (ctx -> vtcm_rctx ); 313ctx -> vtcm_base = 0 ; 314ctx -> vtcm_rctx = 0 ; 315 } 316} 317 318static void htp_main_thread (void * context ); 319static void htp_packet_callback (dspqueue_t queue ,int error ,void * context ); 320static void htp_error_callback (dspqueue_t queue ,int error ,void * context ); 321 322AEEResult htp_iface_start (remote_handle64 handle ,uint32_t sess_id ,uint64_t dsp_queue_id ,uint32_t n_hvx ,uint32_t n_hmx ,uint64_t max_vmem ) { 323struct htp_handle * h = (struct htp_handle * )handle ; 324if (!h ) { 325return AEE_EBADPARM ; 326 } 327 328if (h -> ctx ) { 329FARF (ERROR ,"Queue already open" ); 330return AEE_EITEMBUSY ; 331 } 332 333// Cache the original FastRPC thread priority, then calculate compute priority 334int fastrpc_tid = qurt_thread_get_id (); 335int fastrpc_prio = qurt_thread_get_priority (fastrpc_tid ); 336int main_prio = fastrpc_prio - 10 ; 337if (main_prio < 1 )main_prio = 1 ; 338 339dspqueue_t dsp_queue = NULL ; 340bool use_callbacks = false; 341 342// Import queue with NULL callbacks to avoid starting dspueue internal threads 343int err = dspqueue_import (dsp_queue_id ,NULL ,NULL , (void * )h ,& dsp_queue ); 344if (err == AEE_EBADPARM ) { 345// Fallback for devices that don't support NULL callbacks 346FARF (HIGH ,"dspqueue import with NULL callbacks failed, trying with callbacks" ); 347use_callbacks = true; 348err = dspqueue_import (dsp_queue_id ,htp_packet_callback ,htp_error_callback , (void * )h ,& dsp_queue ); 349 } 350 351if (err ) { 352FARF (ERROR ,"Queue import failed with 0x%08x" , (unsigned )err ); 353return err ; 354 } 355 356qurt_sysenv_max_hthreads_t hw_threads ; 357qurt_sysenv_get_max_hw_threads (& hw_threads ); 358uint32_t hw_nhvx = (qurt_hvx_get_units () >>8 )& 0xFF ; 359 360if (n_hvx == 0 ) { 361n_hvx = hw_nhvx ; 362 } 363if (n_hvx > hw_threads .max_hthreads ) { 364n_hvx = hw_threads .max_hthreads ; 365 } 366if (n_hvx > HTP_MAX_NTHREADS ) { 367n_hvx = HTP_MAX_NTHREADS ; 368 } 369 370// layout segments of our contiguous block 371 372// 1. htp_context : sits at the base (block is 4K-aligned via memalign below) 373size_t offset = sizeof (struct htp_context ); 374 375// 2. main_stack 376size_t offset_main_stack = 0 ; 377size_t size_main_stack = 0 ; 378if (!use_callbacks ) { 379offset_main_stack = hex_align_up (offset ,4096 ); 380size_main_stack = MAIN_THREAD_STACK_SIZE ; 381offset = offset_main_stack + size_main_stack ; 382 } 383 384// 3. work_queue 385size_t wq_align = work_queue_alignof (); 386size_t offset_wq = hex_align_up (offset ,wq_align ); 387size_t size_wq = work_queue_sizeof (n_hvx ,WORK_QUEUE_CAPACITY ,WORK_QUEUE_STACK_SIZE ); 388offset = offset_wq + size_wq ; 389 390// 4. dma_queue 391size_t dma_align = dma_queue_alignof (); 392size_t offset_dma = hex_align_up (offset ,dma_align ); 393size_t size_dma = 0 ; 394for (uint32_t i = 0 ;i < n_hvx ;i ++ ) { 395size_dma = hex_align_up (size_dma ,dma_queue_alignof ()); 396size_dma += dma_queue_sizeof (256 ); 397size_dma = hex_align_up (size_dma ,dma_queue_alignof ()); 398size_dma += dma_queue_alias_sizeof (); 399 } 400offset = offset_dma + size_dma ; 401 402// 5. hmx_queue 403size_t offset_hmx = 0 ; 404size_t size_hmx = 0 ; 405if (n_hmx ) { 406size_t hmx_align = hmx_queue_alignof (); 407offset_hmx = hex_align_up (offset ,hmx_align ); 408size_hmx = hmx_queue_sizeof (HMX_QUEUE_CAPACITY ,HMX_QUEUE_STACK_SIZE ); 409offset = offset_hmx + size_hmx ; 410 } 411 412size_t footprint = hex_align_up (offset ,128 ); 413 414void * block = memalign (4096 ,footprint ); 415if (!block ) { 416FARF (ERROR ,"Unable to allocate unified block of size %zu\n" ,footprint ); 417dspqueue_close (dsp_queue ); 418return AEE_ENOMEMORY ; 419 } 420memset (block ,0 ,footprint ); 421 422h -> ctx = (struct htp_context * )block ; 423struct htp_context * ctx = h -> ctx ; 424ctx -> footprint = footprint ; 425 426ctx -> thread_id = fastrpc_tid ; 427ctx -> thread_prio = main_prio ; 428ctx -> max_vmem = max_vmem ; 429ctx -> dsp_queue = dsp_queue ; 430 431err = vtcm_alloc (ctx ); 432if (err != AEE_SUCCESS ) { 433FARF (ERROR ,"Unable to allocate VTCM" ); 434htp_iface_stop (handle ); 435return AEE_ENOMEMORY ; 436 } 437 438HAP_setFARFRuntimeLoggingParams (0xffff ,NULL ,0 ); 439 440// Set client class 441 { 442HAP_power_request_t request ; 443memset (& request ,0 ,sizeof (HAP_power_request_t )); 444request .type = HAP_power_set_apptype ; 445request .apptype = HAP_POWER_COMPUTE_CLIENT_CLASS ; 446 447if ((err = HAP_power_set ((void * )ctx ,& request ))!= 0 ) { 448htp_iface_stop (handle ); 449return err ; 450 } 451 } 452 453// DCVS setup 454 { 455HAP_power_request_t request ; 456memset (& request ,0 ,sizeof (request )); 457 458request .type = HAP_power_set_DCVS_v3 ; 459request .dcvs_v3 .set_dcvs_enable = TRUE; 460request .dcvs_v3 .dcvs_enable = FALSE; 461request .dcvs_v3 .set_bus_params = TRUE; 462request .dcvs_v3 .bus_params .min_corner = HAP_DCVS_VCORNER_MAX ; 463request .dcvs_v3 .bus_params .max_corner = HAP_DCVS_VCORNER_MAX ; 464request .dcvs_v3 .bus_params .target_corner = HAP_DCVS_VCORNER_MAX ; 465request .dcvs_v3 .set_core_params = TRUE; 466request .dcvs_v3 .core_params .min_corner = HAP_DCVS_VCORNER_MAX ; 467request .dcvs_v3 .core_params .max_corner = HAP_DCVS_VCORNER_MAX ; 468request .dcvs_v3 .core_params .target_corner = HAP_DCVS_VCORNER_MAX ; 469request .dcvs_v3 .set_sleep_disable = TRUE; 470request .dcvs_v3 .sleep_disable = TRUE; 471 472#if (__HEXAGON_ARCH__ >=79 ) 473HAP_set_dcvs_v3_protected_bus_corners (& request ,1 ); 474#endif 475if ((err = HAP_power_set ((void * )ctx ,& request ))!= 0 ) { 476htp_iface_stop (handle ); 477return err ; 478 } 479 480memset (& request ,0 ,sizeof (request )); 481request .type = HAP_power_set_HVX ; 482request .hvx .power_up = TRUE; 483if ((err = HAP_power_set ((void * )ctx ,& request ))!= 0 ) { 484htp_iface_stop (handle ); 485return err ; 486 } 487 } 488 489#if __HVX_ARCH__ >=75 490 { 491// Power on HMX and set HMX clock 492HAP_power_request_t request ; 493memset (& request ,0 ,sizeof (HAP_power_request_t )); 494request .type = HAP_power_set_HMX_v2 ; 495request .hmx_v2 .set_power = TRUE; 496request .hmx_v2 .power_up = TRUE; 497request .hmx_v2 .set_clock = TRUE; 498request .hmx_v2 .target_corner = HAP_DCVS_EXP_VCORNER_MAX ; 499request .hmx_v2 .min_corner = HAP_DCVS_EXP_VCORNER_MAX ; 500request .hmx_v2 .max_corner = HAP_DCVS_EXP_VCORNER_MAX ; 501request .hmx_v2 .perf_mode = HAP_CLK_PERF_HIGH ; 502FARF (ALWAYS ,"Setting HMX clock\n" ); 503err = HAP_power_set ((void * )ctx ,& request ); 504if (err != AEE_SUCCESS ) { 505FARF (ERROR ,"ggml-hex: error setting HMX clock." ); 506htp_iface_stop (handle ); 507return err ; 508 } 509 } 510#else 511 { 512// Power on HMX 513HAP_power_request_t request ; 514memset (& request ,0 ,sizeof (HAP_power_request_t )); 515request .type = HAP_power_set_HMX ; 516request .hmx .power_up = TRUE; 517FARF (ALWAYS ,"Powering HMX on\n" ); 518err = HAP_power_set ((void * )ctx ,& request ); 519if (err != AEE_SUCCESS ) { 520FARF (ERROR ,"ggml-hex: error powering on HMX." ); 521htp_iface_stop (handle ); 522return err ; 523 } 524 } 525#endif 526 527ctx -> hmx_enabled = n_hmx ; 528ctx -> hmx_queue = NULL ; 529if (n_hmx ) { 530void * hmx_ptr = (void * ) ((uintptr_t )block + offset_hmx ); 531ctx -> hmx_queue = hmx_queue_init (hmx_ptr ,HMX_QUEUE_CAPACITY ,HMX_QUEUE_STACK_SIZE ,ctx -> vtcm_rctx ,& ctx -> trace [HTP_MAX_NTHREADS ]); 532 } 533FARF (HIGH ,"HMX %s (n_hmx=%d)" ,ctx -> hmx_enabled ?"enabled" :"disabled" ,n_hmx ); 534 535ctx -> n_threads = n_hvx ; 536ctx -> n_threads_div = init_fastdiv_values (ctx -> n_threads ); 537 538// Initialize DMA queues 539uint8_t * dma_ptr_curr = (uint8_t * ) ((uintptr_t )block + offset_dma ); 540size_t size_dma_q = dma_queue_sizeof (256 ); 541size_t size_dma_alias = dma_queue_alias_sizeof (); 542 543for (int i = 0 ;i < ctx -> n_threads ;i ++ ) { 544dma_ptr_curr = (uint8_t * )hex_align_up ((uintptr_t )dma_ptr_curr ,dma_queue_alignof ()); 545ctx -> dma_cached [i ]= dma_queue_init (dma_ptr_curr ,256 , (uintptr_t )ctx -> vtcm_base ,ctx -> vtcm_size ,& ctx -> trace [i ]); 546dma_ptr_curr += size_dma_q ; 547 548dma_ptr_curr = (uint8_t * )hex_align_up ((uintptr_t )dma_ptr_curr ,dma_queue_alignof ()); 549ctx -> dma [i ]= dma_queue_alias_init (dma_ptr_curr ,ctx -> dma_cached [i ],1 ); 550dma_ptr_curr += size_dma_alias ; 551 } 552 553ctx -> ddr_spad_size = 512 * 1024 ;// 512 KB 554ctx -> ddr_spad_base = memalign (128 ,ctx -> ddr_spad_size ); 555 556void * wq_ptr = (void * ) ((uintptr_t )block + offset_wq ); 557ctx -> work_queue = work_queue_init (wq_ptr ,n_hvx ,WORK_QUEUE_CAPACITY ,WORK_QUEUE_STACK_SIZE ); 558 559ctx -> main_stack = NULL ; 560ctx -> main_thread = 0 ; 561atomic_store (& ctx -> killed , false); 562 563if (!use_callbacks ) { 564// Start main compute thread 565ctx -> main_stack = (void * ) ((uintptr_t )block + offset_main_stack ); 566 567qurt_thread_attr_t attr ; 568qurt_thread_attr_init (& attr ); 569qurt_thread_attr_set_stack_addr (& attr ,ctx -> main_stack ); 570qurt_thread_attr_set_stack_size (& attr ,size_main_stack ); 571qurt_thread_attr_set_priority (& attr ,main_prio ); 572qurt_thread_attr_set_name (& attr ,"htp-main" ); 573 574int err_thread = qurt_thread_create (& ctx -> main_thread ,& attr ,htp_main_thread ,ctx ); 575if (err_thread ) { 576FARF (ERROR ,"Unable to create htp main thread: %d" ,err_thread ); 577htp_iface_stop (handle ); 578return AEE_ENOMEMORY ; 579 } 580 } 581 582FARF (HIGH ,"session %u started: n-hvx %u vtcm-size %zu vtcm-rctx %u n-threads %u thread-id %d thread-prio %d \n" , 583sess_id ,hw_nhvx ,ctx -> vtcm_size ,ctx -> vtcm_rctx ,ctx -> n_threads ,ctx -> thread_id ,ctx -> thread_prio ); 584 585return AEE_SUCCESS ; 586} 587 588AEEResult htp_iface_stop (remote_handle64 handle ) { 589struct htp_handle * h = (struct htp_handle * )handle ; 590if (!h || !h -> ctx ) { 591return AEE_EBADPARM ; 592 } 593struct htp_context * ctx = h -> ctx ; 594 595if (ctx -> main_thread ) { 596atomic_store (& ctx -> killed , true); 597int status ; 598 (void )qurt_thread_join (ctx -> main_thread ,& status ); 599ctx -> main_thread = 0 ; 600 } 601 602int err = dspqueue_close (ctx -> dsp_queue );ctx -> dsp_queue = NULL ; 603if (err != 0 ) { 604FARF (ERROR ,"Queue close failed with 0x%08x" , (unsigned )err ); 605return err ; 606 } 607 608work_queue_free (ctx -> work_queue ); 609 610for (int i = 0 ;i < ctx -> n_threads ;i ++ ) { 611dma_queue_alias_free (ctx -> dma [i ]); 612dma_queue_free (ctx -> dma_cached [i ]); 613 } 614 615if (ctx -> hmx_queue ) { 616hmx_queue_free (ctx -> hmx_queue ); 617ctx -> hmx_queue = NULL ; 618 } 619ctx -> hmx_enabled = false; 620 621vtcm_free (ctx ); 622 623if (ctx -> ddr_spad_base ) { 624free (ctx -> ddr_spad_base ); 625ctx -> ddr_spad_base = NULL ; 626ctx -> ddr_spad_size = 0 ; 627 } 628 629free (ctx ); 630h -> ctx = NULL ; 631 632return AEE_SUCCESS ; 633} 634 635AEEResult htp_iface_hwinfo (remote_handle64 handle ,uint32_t * n_threads ,uint32_t * n_hvx ,uint32_t * n_hmx ,uint64_t * vtcm_size ) { 636 (void )handle ; 637if (!n_threads || !n_hvx || !n_hmx || !vtcm_size ) { 638return AEE_EBADPARM ; 639 } 640 641qurt_sysenv_max_hthreads_t hw_threads ; 642qurt_sysenv_get_max_hw_threads (& hw_threads ); 643uint32_t hw_nhvx = (qurt_hvx_get_units () >>8 )& 0xFF ; 644 645uint32_t n_hvx_val = hw_nhvx ; 646if (n_hvx_val > hw_threads .max_hthreads ) { 647n_hvx_val = hw_threads .max_hthreads ; 648 } 649if (n_hvx_val > HTP_MAX_NTHREADS ) { 650n_hvx_val = HTP_MAX_NTHREADS ; 651 } 652 653// for now we force n_threads == n_hvx 654* n_threads = n_hvx_val ; 655* n_hvx = n_hvx_val ; 656* n_hmx = 1 ; 657 658uint32_t vtcm_sz = 8 * 1024 * 1024 ;// 8MB default fallback 659HAP_compute_res_query_VTCM (0 , (unsigned int * )& vtcm_sz ,NULL ,NULL ,NULL ); 660* vtcm_size = vtcm_sz ; 661 662return AEE_SUCCESS ; 663} 664 665static void htp_error_callback (dspqueue_t queue ,int error ,void * context ) { 666// No errors expected on the DSP. 667FARF (ERROR ,"Error callback: 0x%08x" , (unsigned )error ); 668} 669 670struct profile_data { 671uint64_t usecs ; 672uint64_t cycles_start ; 673uint64_t cycles_stop ; 674uint32_t pmu_counters [HEX_NUM_PMU_COUNTERS ]; 675}; 676 677static inline void profile_start (uint32_t mode ,struct profile_data * d ) { 678switch (mode ) { 679case HTP_PROF_PMU : 680hex_get_pmu (d -> pmu_counters ); 681// fallthrough 682case HTP_PROF_BASIC : 683case HTP_PROF_TRACE : 684d -> usecs = HAP_perf_get_qtimer_count (); 685d -> cycles_start = hex_get_cycles (); 686break ; 687default : 688break ; 689 } 690} 691 692static inline void profile_stop (uint32_t mode ,struct profile_data * d ) { 693uint32_t pmu_counters [HEX_NUM_PMU_COUNTERS ]; 694switch (mode ) { 695case HTP_PROF_PMU : 696hex_get_pmu (pmu_counters ); 697for (int i = 0 ;i < HEX_NUM_PMU_COUNTERS ;i ++ ) { 698d -> pmu_counters [i ]= pmu_counters [i ]- d -> pmu_counters [i ]; 699 } 700// fallthrough 701case HTP_PROF_BASIC : 702case HTP_PROF_TRACE : 703d -> usecs = HAP_perf_qtimer_count_to_us (HAP_perf_get_qtimer_count ()- d -> usecs ); 704d -> cycles_stop = hex_get_cycles (); 705break ; 706default : 707break ; 708 } 709} 710 711static int op_fence (struct htp_ops_context * octx ) { 712struct htp_context * ctx = octx -> ctx ; 713struct htp_thread_trace * tr = & ctx -> trace [0 ]; 714const uint32_t seq = (uint32_t )octx -> op_params [0 ]; 715const uint32_t mode = (uint32_t )octx -> op_params [1 ]; 716 717htp_trace_event_start (tr ,HTP_TRACE_EVT_FENCE , (uint16_t )seq ); 718 719const struct htp_tensor * sync = octx -> src [0 ]; 720atomic_uint * sync_fence = (atomic_uint * ) (uintptr_t )sync -> data ; 721 722if (mode == 1 ) { 723htp_flush_dirty_ranges (ctx ); 724 725htp_mdev_group_barrier (octx ); 726 727if (ctx -> mdev .idx == 0 ) { 728htp_fence_write (sync_fence ,seq ,octx -> status ); 729 } 730htp_trace_event_stop (tr ,HTP_TRACE_EVT_FENCE , (uint16_t )seq ); 731FARF (HIGH ,"ggml-hex: sync-signal : fence %p seq 0x%x status %d\n" ,sync_fence ,seq ,octx -> status ); 732return octx -> status ; 733 } 734 735int status = HTP_STATUS_OK ; 736uint64_t spins = 0 ; 737while (1 ) { 738uint32_t sync_seq ; 739uint32_t sync_status ; 740htp_fence_read (sync_fence ,& sync_seq ,& sync_status ); 741if ((int32_t )(sync_seq - seq ) >=0 ) { 742if (sync_status > HTP_STATUS_OK ) { 743FARF (ERROR ,"ggml-hex: sync-wait peer failed with status %u : fence %p seq 0x%x\n" ,sync_status ,sync_fence ,seq ); 744status = sync_status ; 745 } 746break ; 747 } 748if (++ spins > HTP_FENCE_TIMEOUT ) { 749FARF (ERROR ,"ggml-hex: sync-wait TIMEOUT : fence %p spins %llu seq 0x%x\n" ,sync_fence ,spins ,seq ); 750status = HTP_STATUS_INTERNAL_ERR ; 751break ; 752 } 753hex_pause (); 754 } 755 756htp_trace_event_stop (tr ,HTP_TRACE_EVT_FENCE , (uint16_t )seq ); 757 758FARF (HIGH ,"ggml-hex: sync-done : fence %p spins %llu seq 0x%x\n" ,sync_fence ,spins ,seq ); 759return status ; 760} 761 762static int op_mdev_group (struct htp_ops_context * octx ) { 763struct htp_context * ctx = octx -> ctx ; 764const struct htp_tensor * sync = octx -> src [0 ]; 765ctx -> mdev .idx = (uint16_t )octx -> op_params [0 ]; 766ctx -> mdev .count = (uint16_t )sync -> ne [1 ]; 767if (ctx -> mdev .count > 1 ) { 768ctx -> mdev .count_div = init_fastdiv_values (ctx -> mdev .count ); 769ctx -> mdev .fence_base = (uint8_t * )sync -> data ; 770 } 771return HTP_STATUS_OK ; 772} 773 774static int execute_op (struct htp_ops_context * octx ) { 775switch (octx -> op ) { 776case HTP_OP_MDEV_GROUP : 777return op_mdev_group (octx ); 778 779case HTP_OP_FENCE : 780return op_fence (octx ); 781 782case HTP_OP_ALLREDUCE : 783case HTP_OP_ALLREDUCE_ADD : 784return op_allreduce (octx ); 785 786case HTP_OP_MUL_MAT : 787case HTP_OP_MUL_MAT_ADD : 788return op_matmul (octx ); 789 790case HTP_OP_MUL_MAT_ID : 791return op_matmul_id (octx ); 792 793case HTP_OP_MUL_MAT_ID_NX : 794return op_matmul_id_nx (octx ); 795 796case HTP_OP_MUL_MAT_NX : 797return op_matmul_nx (octx ); 798 799case HTP_OP_MUL : 800case HTP_OP_ADD : 801case HTP_OP_SUB : 802case HTP_OP_DIV : 803case HTP_OP_ADD_ID : 804return op_binary (octx ); 805 806case HTP_OP_NORM : 807case HTP_OP_RMS_NORM : 808case HTP_OP_RMS_NORM_MUL : 809case HTP_OP_SCALE : 810case HTP_OP_CLAMP : 811case HTP_OP_LEAKY_RELU : 812case HTP_OP_SQR : 813case HTP_OP_SQRT : 814case HTP_OP_UNARY_SOFTPLUS : 815case HTP_OP_UNARY_SIGMOID : 816case HTP_OP_UNARY_SILU : 817case HTP_OP_UNARY_GELU : 818case HTP_OP_UNARY_NEG : 819case HTP_OP_UNARY_EXP : 820case HTP_OP_UNARY_TANH : 821case HTP_OP_UNARY_ABS : 822case HTP_OP_UNARY_LOG : 823case HTP_OP_UNARY_RELU : 824case HTP_OP_L2_NORM : 825return op_unary (octx ); 826 827case HTP_OP_GLU_SWIGLU : 828case HTP_OP_GLU_SWIGLU_OAI : 829case HTP_OP_GLU_SWIGLU_CLAMP : 830case HTP_OP_GLU_GEGLU : 831return op_activations (octx ); 832 833case HTP_OP_SOFTMAX : 834return op_softmax (octx ); 835 836case HTP_OP_ROPE : 837return op_rope (octx ); 838 839case HTP_OP_FLASH_ATTN_EXT : 840return op_flash_attn_ext (octx ); 841 842case HTP_OP_SET_ROWS : 843return op_set_rows (octx ); 844 845case HTP_OP_GET_ROWS : 846return op_get_rows (octx ); 847 848case HTP_OP_SUM_ROWS : 849return op_sum_rows (octx ); 850 851case HTP_OP_CPY : 852case HTP_OP_CPY_FENCE : 853return op_cpy (octx ); 854 855case HTP_OP_REPEAT : 856return op_repeat (octx ); 857 858case HTP_OP_ARGSORT : 859return op_argsort (octx ); 860 861case HTP_OP_SSM_CONV : 862return op_ssm_conv (octx ); 863 864case HTP_OP_CUMSUM : 865return op_cumsum (octx ); 866 867case HTP_OP_FILL : 868return op_fill (octx ); 869 870case HTP_OP_DIAG : 871return op_diag (octx ); 872 873case HTP_OP_SOLVE_TRI : 874return op_solve_tri (octx ); 875 876case HTP_OP_PAD : 877return op_pad (octx ); 878 879case HTP_OP_IM2COL : 880return op_im2col (octx ); 881 882case HTP_OP_CONCAT : 883return op_concat (octx ); 884 885case HTP_OP_GATED_DELTA_NET : 886return op_gated_delta_net (octx ); 887 888case HTP_OP_TRI : 889return op_unary (octx ); 890 891case HTP_OP_INVALID : 892break ; 893 } 894 895FARF (ERROR ,"Unknown Op %u" ,octx -> op ); 896return HTP_STATUS_NO_SUPPORT ; 897} 898 899static inline bool reuse_buf (struct htp_context * ctx ,uint32_t * m_reuse ,struct htp_buf_desc * b ) { 900b -> base = NULL ; 901 902for (uint32_t i = 0 ;i < HTP_MAX_MMAPS ;i ++ ) { 903struct htp_mmap * m = ctx -> mmap + i ; 904if (m -> size && m -> fd == b -> fd ) { 905b -> base = m -> base ; 906* m_reuse |= (1 <<i ); 907return true; 908 } 909 } 910 911return false; 912} 913 914static inline void drop_mmap (struct htp_context * ctx ,struct htp_mmap * m ) { 915if (m -> size ) { 916FARF (ALWAYS ,"unmap : fd %u base %p size %u" ,m -> fd , (void * )m -> base , (uint32_t )m -> size ); 917htp_munmap ((void * )m -> base ,m -> size ); 918m -> size = 0 ; 919m -> base = 0 ; 920m -> fd = -1 ; 921 } 922} 923 924static inline bool mmap_buf (struct htp_context * ctx ,struct htp_buf_desc * b ) { 925if (b -> base )return true;// already mapped 926 927// find unused mapping 928for (uint32_t i = 0 ;i < HTP_MAX_MMAPS ;i ++ ) { 929struct htp_mmap * m = & ctx -> mmap [i ]; 930if (!m -> size ) { 931void * va = htp_mmap (b -> fd ,b -> size ); 932if (va == NULL ) { 933FARF (HIGH ,"mmap failed (will attempt defrag) : fd %u size %u" ,b -> fd , (uint32_t )b -> size ); 934return false; 935 } 936 937m -> base = b -> base = (uint64_t )va ; 938m -> fd = b -> fd ; 939m -> size = b -> size ; 940 941FARF (ALWAYS ,"mmap : fd %u base %p size %u" ,m -> fd , (void * )m -> base , (uint32_t )m -> size ); 942return true; 943 } 944 } 945 946FARF (ERROR ,"mmap failed : exceeded mapping capacity limit of %u" ,HTP_MAX_MMAPS ); 947return false; 948} 949 950static void prep_op_bufs (struct htp_context * ctx ,struct htp_buf_desc * bufs ,uint32_t n_bufs ) { 951uint32_t m_reuse = 0 ;// mmap reuse mask (index from ctx->mmap array) 952uint32_t b_reuse = 0 ;// buf reuse count 953 954uint64_t m_vmem = 0 ;// mapped vmem 955uint64_t e_vmem = 0 ;// extra vmem 956 957// See what we can reuse 958for (uint32_t i = 0 ;i < n_bufs ;i ++ ) { 959struct htp_buf_desc * b = bufs + i ; 960if (reuse_buf (ctx ,& m_reuse ,b )) {b_reuse ++ ; }else {e_vmem += b -> size ; } 961FARF (HIGH ,"prep-buf #%u : pass0 fd %u base %p size %u flags 0x%x" ,i ,b -> fd , (void * )b -> base , (uint32_t )b -> size ,b -> flags ); 962 } 963 964if (b_reuse == n_bufs )return ;// all bufs reuse existing mappings 965 966// See how much vmem we have mmaped right now 967for (uint32_t i = 0 ;i < HTP_MAX_MMAPS ;i ++ ) {m_vmem += ctx -> mmap [i ].size ; } 968 969FARF (HIGH ,"prep-bufs : pass1 mmap-vmem %zu extra-vmem %zu max-vmem %zu : n-bufs %u b-reuse %u" , 970 (size_t )m_vmem , (size_t )e_vmem , (size_t )ctx -> max_vmem ,n_bufs ,b_reuse ); 971 972if ((m_vmem + e_vmem )> ctx -> max_vmem ) { 973// Drop unused mappings 974for (uint32_t i = 0 ;i < HTP_MAX_MMAPS ;i ++ ) { 975bool used = m_reuse & (1 <<i ); 976if (!used ) {drop_mmap (ctx ,ctx -> mmap + i ); } 977 } 978 } 979 980// Create missing mappings (pass 1) 981bool mmap_ok = true; 982for (uint32_t i = 0 ;i < n_bufs ;i ++ ) { 983struct htp_buf_desc * b = bufs + i ; 984if (!mmap_buf (ctx ,b )) { 985mmap_ok = false; 986break ; 987 } 988FARF (HIGH ,"prep-buf #%u : pass1 fd %u base %p size %u flags 0x%x" ,i ,b -> fd , (void * )b -> base , (uint32_t )b -> size ,b -> flags ); 989 } 990 991if (!mmap_ok ) { 992// Attempt clean defragmentation: drop all mappings and remap (pass 2) 993FARF (HIGH ,"prep-bufs : dropping all mappings to defragment address space" ); 994for (uint32_t i = 0 ;i < HTP_MAX_MMAPS ;i ++ ) {drop_mmap (ctx ,ctx -> mmap + i ); } 995 996for (uint32_t i = 0 ;i < n_bufs ;i ++ ) { 997struct htp_buf_desc * b = bufs + i ; 998b -> base = 0 ; 999if (!mmap_buf (ctx ,b )) { 1000FARF (ERROR ,"prep-bufs : mmap failed after defragmentation (fd %u size %u)" ,b -> fd , (uint32_t )b -> size ); 1001abort (); 1002 } 1003FARF (HIGH ,"prep-buf #%u : pass2 fd %u base %p size %u flags 0x%x" ,i ,b -> fd , (void * )b -> base , (uint32_t )b -> size ,b -> flags ); 1004 } 1005 } 1006} 1007 1008static void prep_tensor (struct htp_context * ctx ,struct htp_buf_desc * bufs ,struct htp_tensor * tens ,uint32_t idx ,struct htp_tensor * t ) { 1009uint32_t offset = t -> data ; 1010uint32_t size = t -> size ; 1011uint32_t bi = t -> bi ; 1012 1013t -> data = (uint32_t ) (bufs [bi ].base + offset );// update data to the actual pointer 1014 1015FARF (HIGH ,"prep-tensor #%u: bi %u offset %u size %u data %p : %u:%u:%u:%u" ,idx ,t -> bi ,offset ,t -> size , (void * )t -> data , 1016t -> ne [0 ],t -> ne [1 ],t -> ne [3 ],t -> ne [3 ]); 1017} 1018 1019static void prep_tensors (struct htp_context * ctx ,struct htp_buf_desc * bufs ,struct htp_tensor * tens ,uint32_t n_tens ) { 1020for (uint32_t i = 0 ;i < n_tens ;i ++ ) { 1021prep_tensor (ctx ,bufs ,tens ,i ,tens + i ); 1022 } 1023} 1024 1025static void mdev_group_init (struct htp_context * ctx ,const struct htp_opbatch_req * req ) { 1026memset (& ctx -> mdev ,0 ,sizeof (ctx -> mdev )); 1027ctx -> mdev .fence_seq = (uint32_t )((req -> seq & 0xfffff ) <<12 ); 1028} 1029 1030static int proc_op_req (struct htp_ops_context * octx ,struct htp_buf_desc * bufs ,uint32_t n_bufs , 1031struct htp_tensor * tens ,uint32_t idx ,struct htp_op_desc * op ) { 1032memcpy (octx -> op_params ,op -> params ,sizeof (octx -> op_params )); 1033memcpy (octx -> kernel_params ,op -> kernel_params ,sizeof (octx -> kernel_params )); 1034octx -> flags = op -> flags ; 1035octx -> op = op -> opcode ; 1036octx -> n_threads = octx -> ctx -> n_threads ; 1037octx -> n_threads_div = octx -> ctx -> n_threads_div ; 1038 1039FARF (HIGH ,"proc-op #%u: opcode %u flags 0x%x" ,idx ,octx -> op ,octx -> flags ); 1040 1041// Prep input tensors 1042for (uint32_t i = 0 ;i < HTP_OP_MAX_INPUTS ;i ++ ) { 1043uint16_t src_idx = op -> src [i ]; 1044if (src_idx == 0xffff ) { 1045octx -> src [i ]= NULL ; 1046octx -> src_dma [i ]= NULL ; 1047continue ; 1048 } 1049 1050struct htp_tensor * src = tens + src_idx ; 1051octx -> src [i ]= src ; 1052octx -> src_dma [i ]= octx -> ctx -> dma ;// FIXME: ? octx->ctx->dma_cached : octx->ctx->dma; 1053 1054FARF (HIGH ,"prep-src #%u: data %p size %u : %u:%u:%u:%u" ,op -> src [i ], (void * )src -> data ,src -> size , 1055src -> ne [0 ],src -> ne [1 ],src -> ne [2 ],src -> ne [3 ]); 1056 } 1057 1058htp_tensor_flush_all (octx -> ctx ,octx -> src ,HTP_OP_MAX_INPUTS ); 1059 1060// Prep output tensors 1061for (uint32_t i = 0 ;i < HTP_OP_MAX_OUTPUTS ;i ++ ) { 1062uint16_t dst_idx = op -> dst [i ]; 1063if (dst_idx == 0xffff ) { 1064octx -> dsts [i ]= NULL ; 1065octx -> dst_dma [i ]= NULL ; 1066continue ; 1067 } 1068struct htp_tensor * dst = tens + dst_idx ; 1069octx -> dsts [i ]= dst ; 1070octx -> dst_dma [i ]= octx -> ctx -> dma ;// FIXME: ? octx->ctx->dma_cached : octx->ctx->dma; 1071 1072FARF (HIGH ,"prep-dst[%u] #%u: data %p size %u : %u:%u:%u:%u" ,i ,dst_idx , (void * )dst -> data ,dst -> size , 1073dst -> ne [0 ],dst -> ne [1 ],dst -> ne [2 ],dst -> ne [3 ]); 1074 } 1075 1076htp_tensor_dirty_all (octx -> ctx ,octx -> dsts ,HTP_OP_MAX_OUTPUTS ); 1077 1078htp_mdev_group_barrier (octx ); 1079 1080int status = execute_op (octx ); 1081 1082htp_ops_context_set_status (octx ,status ); 1083 1084octx -> src0_spad .src = NULL ; 1085octx -> src1_spad .src = NULL ; 1086octx -> src2_spad .src = NULL ; 1087octx -> src3_spad .src = NULL ; 1088octx -> dst_spad .src = NULL ; 1089 1090return octx -> status ; 1091} 1092 1093static void process_opbatch (struct htp_context * ctx ,const struct htp_opbatch_req * req ,const struct dspqueue_buffer * dbuf ) { 1094dspqueue_t queue = ctx -> dsp_queue ; 1095int err ; 1096 1097const uint32_t n_bufs = req -> n_bufs ; 1098const uint32_t n_tens = req -> n_tensors ; 1099const uint32_t n_ops = req -> n_ops ; 1100 1101const uint32_t b_size = sizeof (struct htp_buf_desc )* n_bufs ; 1102const uint32_t t_size = sizeof (struct htp_tensor )* n_tens ; 1103const uint32_t o_size = sizeof (struct htp_op_desc )* n_ops ; 1104const uint32_t p_size = sizeof (struct htp_prof_desc )* n_ops ; 1105const uint32_t tr_size = (HTP_MAX_NTHREADS + 1 )* req -> n_traces * sizeof (struct htp_trace_desc ); 1106 1107if (dbuf -> size < b_size + t_size + o_size + p_size + tr_size ) { 1108FARF (ERROR ,"invalid opbatch memory block size %u (req %u)" ,dbuf -> size ,b_size + t_size + o_size + p_size + tr_size ); 1109return ; 1110 } 1111 1112FARF (HIGH ,"processing opbatch #%llu: n-bufs %u n-tensors %u n-ops %u n-traces %u : m-size %u b-size %u t-size %u o-size %u" , (unsigned long long )req -> seq , 1113n_bufs ,n_tens ,n_ops ,req -> n_traces ,dbuf -> size ,b_size ,t_size ,o_size ); 1114 1115// Setup descriptor pointers 1116uint8_t * m_ptr = dbuf -> ptr ; 1117struct htp_buf_desc * bufs = (struct htp_buf_desc * )m_ptr ;m_ptr += b_size ; 1118struct htp_tensor * tens = (struct htp_tensor * )m_ptr ;m_ptr += t_size ; 1119struct htp_op_desc * ops = (struct htp_op_desc * )m_ptr ;m_ptr += o_size ; 1120struct htp_prof_desc * pds = (struct htp_prof_desc * )m_ptr ; 1121 1122struct profile_data batch_prof ; 1123profile_start (HTP_PROF_BASIC ,& batch_prof ); 1124 1125memset (ctx -> trace ,0 ,sizeof (ctx -> trace )); 1126if (ctx -> profiler == HTP_PROF_TRACE ) { 1127struct htp_trace_desc * trace_events = (struct htp_trace_desc * ) (m_ptr + p_size ); 1128for (int t = 0 ;t <=HTP_MAX_NTHREADS ;t ++ ) { 1129ctx -> trace [t ].events = & trace_events [t * req -> n_traces ]; 1130ctx -> trace [t ].max_events = req -> n_traces ; 1131 } 1132 } 1133 1134// Clean cache at the start of the batch 1135htp_trace_event_start (& ctx -> trace [0 ],HTP_TRACE_EVT_L2FLUSH ,0 ); 1136qurt_mem_cache_clean ((qurt_addr_t )0 ,0 ,QURT_MEM_CACHE_FLUSH_INVALIDATE_ALL ,QURT_MEM_DCACHE ); 1137hex_l2fetch_block (ctx ,ctx -> footprint ); 1138memset (ctx -> dirty_ranges ,0 ,sizeof (ctx -> dirty_ranges )); 1139htp_trace_event_stop (& ctx -> trace [0 ],HTP_TRACE_EVT_L2FLUSH ,0 ); 1140 1141htp_trace_event_start (& ctx -> trace [0 ],HTP_TRACE_EVT_BUFF ,0 ); 1142prep_op_bufs (ctx ,bufs ,n_bufs ); 1143htp_trace_event_stop (& ctx -> trace [0 ],HTP_TRACE_EVT_BUFF ,0 ); 1144 1145prep_tensors (ctx ,bufs ,tens ,n_tens ); 1146 1147struct htp_ops_context * octx = & ctx -> octx ; 1148memset (octx ,0 ,sizeof (* octx )); 1149octx -> n_threads = ctx -> n_threads ; 1150octx -> n_threads_div = ctx -> n_threads_div ; 1151octx -> ctx = ctx ; 1152 1153mdev_group_init (ctx ,req ); 1154 1155work_queue_wakeup (ctx -> work_queue ); 1156if (ctx -> hmx_queue ) { 1157hmx_queue_wakeup (ctx -> hmx_queue ); 1158 } 1159 1160int op_status = HTP_STATUS_OK ; 1161octx -> status = HTP_STATUS_OK ; 1162for (uint32_t i = 0 ;i < n_ops ;i ++ ) { 1163struct profile_data prof ; 1164 1165profile_start (ctx -> profiler ,& prof ); 1166 1167op_status = proc_op_req (octx ,bufs ,n_bufs ,tens ,i ,& ops [i ]); 1168 1169profile_stop (ctx -> profiler ,& prof ); 1170 1171htp_ops_context_set_status (octx ,op_status ); 1172 1173if (ctx -> profiler ) { 1174pds [i ].opcode = ops [i ].opcode ; 1175pds [i ].usecs = prof .usecs ; 1176pds [i ].cycles_start = prof .cycles_start ; 1177pds [i ].cycles_stop = prof .cycles_stop ; 1178for (int j = 0 ;j < HEX_NUM_PMU_COUNTERS ;j ++ ) { 1179pds [i ].pmu [j ]= prof .pmu_counters [j ]; 1180 } 1181 } 1182 } 1183 1184if (ctx -> hmx_queue ) { 1185hmx_queue_suspend (ctx -> hmx_queue ); 1186hmx_queue_flush (ctx -> hmx_queue ); 1187 } 1188work_queue_suspend (ctx -> work_queue ); 1189 1190// Flush remaining dirty tensors at the end of the batch 1191htp_trace_event_start (& ctx -> trace [0 ],HTP_TRACE_EVT_L2FLUSH ,0 ); 1192qurt_mem_cache_clean ((qurt_addr_t )0 ,0 ,QURT_MEM_CACHE_FLUSH_INVALIDATE_ALL ,QURT_MEM_DCACHE ); 1193htp_trace_event_stop (& ctx -> trace [0 ],HTP_TRACE_EVT_L2FLUSH ,0 ); 1194 1195htp_mdev_group_barrier (octx ); 1196 1197profile_stop (HTP_PROF_BASIC ,& batch_prof ); 1198 1199struct htp_opbatch_rsp rsp ; 1200memset (& rsp ,0 ,sizeof (rsp )); 1201rsp .seq = req -> seq ; 1202rsp .status = octx -> status ; 1203rsp .n_bufs = n_bufs ; 1204rsp .n_tensors = n_tens ; 1205rsp .n_ops = n_ops ; 1206rsp .usecs = batch_prof .usecs ; 1207rsp .cycles_start = batch_prof .cycles_start ; 1208rsp .cycles_stop = batch_prof .cycles_stop ; 1209 1210if (ctx -> profiler == HTP_PROF_TRACE ) { 1211for (int t = 0 ;t <=HTP_MAX_NTHREADS ;t ++ ) { 1212rsp .n_traces [t ]= ctx -> trace [t ].count ; 1213 } 1214 } 1215 1216struct dspqueue_buffer write_dbuf = * dbuf ; 1217write_dbuf .flags = DSPQUEUE_BUFFER_FLAG_FLUSH_SENDER |DSPQUEUE_BUFFER_FLAG_INVALIDATE_RECIPIENT ; 1218 1219err = dspqueue_write (queue ,0 ,1 ,& write_dbuf ,sizeof (rsp ), (const uint8_t * )& rsp ,DSPQUEUE_TIMEOUT_NONE ); 1220if (err != 0 ) { 1221FARF (ERROR ,"dspqueue_write failed: 0x%08x" , (unsigned )err ); 1222 } 1223} 1224 1225#define DSPQUEUE_READ_TIMEOUT_USEC 5000 1226#define DSPQUEUE_POLL_TIMEOUT_USEC 100 1227#define DSPQUEUE_POLL_COUNT 100 1228 1229static void process_ops (struct htp_context * ctx ) { 1230dspqueue_t queue = ctx -> dsp_queue ; 1231int err ; 1232 1233uint32_t poll_count = DSPQUEUE_POLL_COUNT ; 1234 1235vtcm_acquire (ctx ); 1236 1237while (!ctx -> vtcm_needs_release && !atomic_load (& ctx -> killed )) { 1238struct htp_opbatch_req req ; 1239uint32_t r_size = sizeof (req ); 1240 1241struct dspqueue_buffer dbuf ; 1242uint32_t n_dbufs = 1 ; 1243uint32_t flags = 0 ; 1244 1245err = dspqueue_read_noblock (queue ,& flags ,n_dbufs ,& n_dbufs ,& dbuf ,r_size ,& r_size , (uint8_t * )& req ); 1246if (err == AEE_EWOULDBLOCK ) { 1247if (-- poll_count ) { 1248qurt_sleep (DSPQUEUE_POLL_TIMEOUT_USEC ); 1249continue ; 1250 } 1251break ; 1252 } 1253 1254if (err != 0 ) { 1255FARF (ERROR ,"dspqueue_read_noblock failed: 0x%08x" , (unsigned )err ); 1256break ; 1257 } 1258 1259if (r_size < sizeof (req )|| n_dbufs != 1 ) { 1260FARF (ERROR ,"invalid request : size %u n-dbufs %u" ,r_size ,n_dbufs ); 1261continue ; 1262 } 1263 1264// Reset poll count for valid requests 1265poll_count = DSPQUEUE_POLL_COUNT ; 1266 1267process_opbatch (ctx ,& req ,& dbuf ); 1268 } 1269 1270vtcm_release (ctx ); 1271} 1272 1273static void htp_packet_callback (dspqueue_t queue ,int error ,void * context ) { 1274 (void )queue ; 1275 (void )error ; 1276struct htp_handle * h = (struct htp_handle * )context ; 1277if (h && h -> ctx ) { 1278process_ops (h -> ctx ); 1279 } 1280} 1281 1282static void htp_main_thread (void * context ) { 1283struct htp_context * ctx = (struct htp_context * )context ; 1284 1285FARF (HIGH ,"htp-main-thread: started" ); 1286 1287while (!atomic_load (& ctx -> killed )) { 1288uint32_t flags = 0 ; 1289uint32_t num_buffers = 0 ; 1290uint32_t message_length = 0 ; 1291 1292int err = dspqueue_peek (ctx -> dsp_queue ,& flags ,& num_buffers ,& message_length ,50000 ); 1293if (err == 0 ) { 1294process_ops (ctx ); 1295 }else if (err == AEE_EWOULDBLOCK || err == AEE_EEXPIRED ) { 1296continue ; 1297 }else { 1298FARF (ERROR ,"dspqueue_peek failed: 0x%08x" , (unsigned )err ); 1299break ; 1300 } 1301 } 1302 1303FARF (HIGH ,"htp-main-thread: stopped" ); 1304}