char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
192067b72
char/aliceai-t5-moe
1#ifndef HTP_DMA_H 2#define HTP_DMA_H 3 4#include <HAP_farf.h> 5#include <hexagon_types.h> 6#include <stdbool.h> 7#include <stdint.h> 8#include "hex-utils.h" 9 10#include "hex-profile.h" 11 12#ifdef __cplusplus 13extern "C" { 14#endif 15 16// Define the HW descriptor structs here since the ones in HexSDK are a bit out of date 17typedef struct dma_descriptor_1d_s { 18void * next ; 19uint32_t size :24 ; 20uint32_t desc_size :2 ; 21uint32_t dst_comp :1 ; 22uint32_t src_comp :1 ; 23uint32_t dst_bypass :1 ; 24uint32_t src_bypass :1 ; 25uint32_t order :1 ; 26uint32_t done :1 ; 27void * src ; 28void * dst ; 29}dma_descriptor_1d ; 30 31#if __HVX_ARCH__ < 75 32 33typedef struct dma_descriptor_2d_s { 34void * next ; 35uint32_t reserved0 :24 ; 36uint32_t desc_size :2 ; 37uint32_t dst_comp :1 ; 38uint32_t src_comp :1 ; 39uint32_t dst_bypass :1 ; 40uint32_t src_bypass :1 ; 41uint32_t order :1 ; 42uint32_t done :1 ; 43void * src ; 44void * dst ; 45uint32_t desc_type :8 ; 46uint32_t reserved1 :24 ; 47uint32_t row_size :16 ; 48uint32_t nrows :16 ; 49uint32_t src_stride :16 ; 50uint32_t dst_stride :16 ; 51uint32_t src_offset :16 ; 52uint32_t dst_offset :16 ; 53}dma_descriptor_2d ; 54 55#else 56 57typedef struct dma_descriptor_2d_s { 58void * next ; 59uint32_t dst_stride :24 ; 60uint32_t desc_size :2 ; 61uint32_t dst_comp :1 ; 62uint32_t src_comp :1 ; 63uint32_t dst_bypass :1 ; 64uint32_t src_bypass :1 ; 65uint32_t order :1 ; 66uint32_t done :1 ; 67void * src ; 68void * dst ; 69uint32_t desc_type :8 ; 70uint32_t reserved0 :24 ; 71uint32_t row_size :24 ; 72uint32_t nrows_lo :8 ; 73uint32_t nrows_hi :8 ; 74uint32_t src_stride :24 ; 75uint32_t offset :24 ; 76uint32_t reserved1 :8 ; 77}dma_descriptor_2d ; 78 79#endif 80 81typedef struct { 82void * dst ; 83const void * src ; 84}dma_ptr ; 85 86typedef struct dma_ring_s dma_ring ; 87struct dma_ring_s { 88dma_descriptor_2d * desc ;// descriptor pointers 89dma_descriptor_2d * tail ;// tail pointer 90dma_ptr * dptr ;// dst/src pointers 91uint32_t push_idx ; 92uint32_t pop_idx ; 93uint32_t capacity ; 94uint32_t idx_mask ; 95struct htp_thread_trace * trace ; 96uintptr_t vtcm_base ; 97uintptr_t vtcm_end ; 98}; 99 100typedef struct dma_queue_s dma_queue ; 101typedef dma_queue * dma_queue_t ; 102 103struct dma_queue_s { 104dma_ring * ring ;// Points to the descriptor ring state 105uint8_t nocache ;// Queue-specific bypass flag 106bool alias ;// When set, dma_queue_delete will not free the ring 107}; 108 109 110 111size_t dma_queue_sizeof (size_t capacity ); 112size_t dma_queue_alignof (void ); 113dma_queue_t dma_queue_init (void * ptr ,size_t capacity ,uintptr_t vtcm_base ,size_t vtcm_size ,struct htp_thread_trace * trace ); 114void dma_queue_free (dma_queue_t q ); 115 116size_t dma_queue_alias_sizeof (void ); 117dma_queue_t dma_queue_alias_init (void * ptr ,dma_queue_t main_q ,uint8_t nocache ); 118void dma_queue_alias_free (dma_queue_t q ); 119 120// TODO: technically we don't need these and could use Q6_dmstart/wait/etc instead 121// but those do not seem to always compiler properly. 122static inline void dmstart (void * next ) { 123 asmvolatile (" release(%0):at" : :"r" (next )); 124 asmvolatile (" dmstart(%0)" : :"r" (next )); 125} 126 127static inline void dmlink (void * cur ,void * next ) { 128 asmvolatile (" release(%0):at" : :"r" (next )); 129 asmvolatile (" dmlink(%0, %1)" : :"r" (cur ),"r" (next )); 130} 131 132static inline unsigned int dmpoll (void ) { 133unsigned int ret = 0 ; 134 asmvolatile (" %0 = dmpoll" :"=r" (ret ) : :"memory" ); 135return ret ; 136} 137 138static inline unsigned int dmwait (void ) { 139unsigned int ret = 0 ; 140 asmvolatile (" %0 = dmwait" :"=r" (ret ) : :"memory" ); 141return ret ; 142} 143 144static inline dma_ptr dma_make_ptr (void * dst ,const void * src ) 145{ 146dma_ptr p = {dst ,src }; 147return p ; 148} 149 150static inline bool dma_is_vtcm (const dma_queue * q ,const void * ptr ) { 151return (uintptr_t )ptr >=q -> ring -> vtcm_base && (uintptr_t )ptr < q -> ring -> vtcm_end ; 152} 153 154static inline bool dma_queue_push_single_1d (dma_queue * q ,dma_ptr dptr ,size_t size ) { 155dma_ring * r = q -> ring ; 156if (((r -> push_idx + 1 )& r -> idx_mask )== r -> pop_idx ) { 157return false; 158 } 159 160dma_descriptor_1d * desc = (dma_descriptor_1d * )& r -> desc [r -> push_idx ]; 161desc -> src = (void * )dptr .src ; 162desc -> dst = (void * )dptr .dst ; 163desc -> size = size ; 164 165r -> dptr [r -> push_idx ]= dptr ; 166 167htp_trace_event_start (r -> trace ,HTP_TRACE_EVT_DMA ,r -> push_idx ); 168 169if (size ) { 170desc -> next = NULL ; 171desc -> desc_size = 0 ;// 1D mode 172desc -> src_bypass = dma_is_vtcm (q ,dptr .src ) ?1 :q -> nocache ; 173desc -> dst_bypass = dma_is_vtcm (q ,dptr .dst ) ?1 :q -> nocache ; 174desc -> order = 0 ; 175desc -> done = 0 ; 176 177dmlink (r -> tail ,desc ); 178r -> tail = (dma_descriptor_2d * )desc ; 179 }else { 180desc -> desc_size = 0 ; 181desc -> done = 1 ; 182 } 183 184r -> push_idx = (r -> push_idx + 1 )& r -> idx_mask ; 185return true; 186} 187 188static inline bool dma_queue_push_single_2d (dma_queue * q ,dma_ptr dptr ,size_t dst_stride ,size_t src_stride ,size_t row_size ,size_t nrows ) { 189dma_ring * r = q -> ring ; 190if (((r -> push_idx + 1 )& r -> idx_mask )== r -> pop_idx ) { 191return false; 192 } 193 194dma_descriptor_2d * desc = & r -> desc [r -> push_idx ]; 195 196desc -> next = NULL ; 197desc -> reserved0 = 0 ; 198desc -> reserved1 = 0 ; 199desc -> desc_size = 1 ;// 2d mode 200desc -> src_bypass = dma_is_vtcm (q ,dptr .src ) ?1 :q -> nocache ; 201desc -> dst_bypass = dma_is_vtcm (q ,dptr .dst ) ?1 :q -> nocache ; 202desc -> src_comp = 0 ; 203desc -> dst_comp = 0 ; 204desc -> order = 0 ; 205desc -> done = 0 ; 206desc -> src_stride = src_stride ; 207desc -> dst_stride = dst_stride ; 208desc -> src = (void * )dptr .src ; 209desc -> dst = (void * )dptr .dst ; 210desc -> row_size = row_size ; 211 212#if __HVX_ARCH__ < 75 213desc -> desc_type = 0 ;// 2d (16-bit) mode 214desc -> nrows = nrows ; 215desc -> src_offset = 0 ; 216desc -> dst_offset = 0 ; 217#else 218desc -> desc_type = 9 ;// 2d (24-bit) mode 219desc -> nrows_lo = (nrows & 0xff ); 220desc -> nrows_hi = (nrows >>8 ); 221desc -> offset = 0 ; 222#endif 223 224r -> dptr [r -> push_idx ]= dptr ; 225 226htp_trace_event_start (r -> trace ,HTP_TRACE_EVT_DMA ,r -> push_idx ); 227 228if (nrows ) { 229dmlink (r -> tail ,desc ); 230r -> tail = desc ; 231 }else { 232desc -> done = 1 ; 233 } 234 235r -> push_idx = (r -> push_idx + 1 )& r -> idx_mask ; 236return true; 237} 238 239static inline dma_ptr dma_queue_pop (dma_queue * q ) { 240dma_ring * r = q -> ring ; 241dma_ptr dptr = {NULL }; 242 243if (r -> push_idx == r -> pop_idx ) { 244return dptr ; 245 } 246 247dptr = r -> dptr [r -> pop_idx ]; 248 249volatile dma_descriptor_2d * desc = & r -> desc [r -> pop_idx ]; 250 251// Wait for desc to complete 252if (!desc -> done ) { 253// FARF(ALWAYS, "dma-poll: idx %u dst %p src %p", r->pop_idx, dptr.dst, dptr.src); 254while (!desc -> done ) { 255dmpoll (); 256 } 257 } 258 259htp_trace_event_stop (r -> trace ,HTP_TRACE_EVT_DMA ,r -> pop_idx ); 260 261r -> pop_idx = (r -> pop_idx + 1 )& r -> idx_mask ; 262return dptr ; 263} 264 265static inline dma_ptr dma_queue_pop_nowait (dma_queue * q ) { 266dma_ring * r = q -> ring ; 267dma_ptr dptr = {NULL }; 268 269if (r -> push_idx == r -> pop_idx ) { 270return dptr ; 271 } 272 273dptr = r -> dptr [r -> pop_idx ]; 274 275htp_trace_event_stop (r -> trace ,HTP_TRACE_EVT_DMA ,r -> pop_idx ); 276 277r -> pop_idx = (r -> pop_idx + 1 )& r -> idx_mask ; 278return dptr ; 279} 280 281static inline bool dma_queue_empty (dma_queue * q ) { 282return q -> ring -> push_idx == q -> ring -> pop_idx ; 283} 284 285static inline void dma_queue_flush (dma_queue * q ) { 286while (dma_queue_pop (q ).dst != NULL ) ; 287} 288 289static inline uint32_t dma_queue_depth (dma_queue * q ) { 290return (q -> ring -> push_idx - q -> ring -> pop_idx )& q -> ring -> idx_mask ; 291} 292 293static inline uint32_t dma_queue_capacity (dma_queue * q ) { 294return q -> ring -> capacity ; 295} 296 297#if __HVX_ARCH__ < 75 298 299// Overflow-safe DMA push: all 2d descriptor fields (row_size, nrows, src_stride, dst_stride) are 16-bit, max 65535. 300// This version transparently handles values that exceed the 16-bit limit and submits chained DMA transtions. 301 302#define DMA_MAX_FIELD_VAL 65535u 303 304static inline bool dma_queue_push (dma_queue * q ,dma_ptr dptr ,size_t dst_stride ,size_t src_stride ,size_t row_size ,size_t nrows ) { 305// Fast path: everything fits in 16 bits 306if (nrows == 0 || __builtin_expect ( 307row_size <=DMA_MAX_FIELD_VAL && 308nrows <=DMA_MAX_FIELD_VAL && 309src_stride <=DMA_MAX_FIELD_VAL && 310dst_stride <=DMA_MAX_FIELD_VAL ,1 )) { 311return dma_queue_push_single_2d (q ,dptr ,dst_stride ,src_stride ,row_size ,nrows ); 312 } 313 314// Contiguous block 315// Use 1d DMA mode which supports sizes up to 24-bits (16MB) 316if (nrows == 1 || (row_size == src_stride && row_size == dst_stride )) { 317size_t total = row_size * nrows ; 318return dma_queue_push_single_1d (q ,dptr ,total ); 319 } 320 321// Stride overflow - fall back to row-by-row. 322 { 323const uint8_t * src = (const uint8_t * )dptr .src ; 324uint8_t * dst = (uint8_t * )dptr .dst ; 325size_t r = 0 ; 326while (r + 1 < nrows ) { 327dma_ptr p = dma_make_ptr (dst + r * dst_stride ,src + r * src_stride ); 328if (!dma_queue_push_single_1d (q ,p ,row_size )) { 329dma_queue_flush (q ); 330 }else { 331r ++ ; 332 } 333 } 334dma_queue_flush (q ); 335dma_ptr p = dma_make_ptr (dst + r * dst_stride ,src + r * src_stride ); 336return dma_queue_push_single_1d (q ,p ,row_size ); 337 } 338} 339 340#else // HVX_ARCH >= 75 341 342static inline bool dma_queue_push (dma_queue * q ,dma_ptr dptr ,size_t dst_stride ,size_t src_stride ,size_t row_size ,size_t nrows ) { 343// On v75 and up we always use 2d 24-bit mode 344return dma_queue_push_single_2d (q ,dptr ,dst_stride ,src_stride ,row_size ,nrows ); 345} 346 347#endif 348 349static inline bool dma_queue_push_ddr_to_vtcm (dma_queue * q ,dma_ptr dptr ,size_t dst_row_size ,size_t src_row_size ,size_t nrows ) { 350return dma_queue_push (q ,dptr ,dst_row_size ,src_row_size ,src_row_size ,nrows ); 351} 352 353static inline bool dma_queue_push_vtcm_to_ddr (dma_queue * q ,dma_ptr dptr ,size_t dst_row_size ,size_t src_row_size ,size_t nrows ) { 354return dma_queue_push (q ,dptr ,dst_row_size ,src_row_size ,dst_row_size ,nrows ); 355} 356 357#define DMA_CACHE_MAX_SIZE 256U 358 359typedef struct { 360uint8_t * base ; 361uint32_t line_size ; 362uint32_t capacity ; 363uint32_t src [DMA_CACHE_MAX_SIZE ]; 364uint16_t age [DMA_CACHE_MAX_SIZE ]; 365}dma_cache ; 366 367static inline void dma_cache_init (dma_cache * c ,uint8_t * base ,uint32_t line_size ,uint32_t capacity ) 368{ 369c -> capacity = (capacity > DMA_CACHE_MAX_SIZE ) ?DMA_CACHE_MAX_SIZE :capacity ; 370c -> base = base ; 371c -> line_size = line_size ; 372 373for (unsigned i = 0 ;i < c -> capacity ;i ++ ) { 374c -> src [i ]= 0 ; 375c -> age [i ]= 0 ; 376 } 377} 378 379static inline bool dma_cache_push (dma_queue * q ,dma_cache * c ,const uint8_t * src ,uint32_t dst_stride ,uint32_t src_stride ,uint32_t row_size ,uint32_t nrows ) 380{ 381uint32_t o_idx = 0 ; 382uint16_t o_age = 0 ; 383uint8_t * dst = 0 ; 384 385for (unsigned i = 0 ;i < c -> capacity ;i ++ ) { 386if (c -> src [i ]== (uint32_t )src ) { 387c -> age [i ]= 0 ; 388dst = c -> base + (i * c -> line_size );nrows = 0 ;// dummy dma 389 }else { 390c -> age [i ]++ ; 391if (c -> age [i ]> o_age ) {o_age = c -> age [i ];o_idx = i ; } 392 } 393 } 394if (!dst ) { 395c -> age [o_idx ]= 0 ; 396c -> src [o_idx ]= (uint32_t )src ; 397dst = c -> base + o_idx * c -> line_size ;// normal nrows dma 398return dma_queue_push (q ,dma_make_ptr (dst ,src ),dst_stride ,src_stride ,row_size ,nrows ); 399 } 400 401return dma_queue_push_single_1d (q ,dma_make_ptr (dst ,src ),0 ); 402} 403 404#ifdef __cplusplus 405} // extern "C" 406#endif 407 408#endif /* HTP_DMA_H */