/* * FIR_acc.c * * Created on: 2022Äê5ÔÂ13ÈÕ * Author: graydon */ #include #include #include #include #include "FIR_acc.h" #include "memory.h" #define MP_OFFSET 0x0A000000 #define saddr(x) ((s32)(x)>>2)|MP_OFFSET /* Declaring the external buffers needed for FIR Accelerator*/ struct FIR_tcb { u16 id; u8 cp_update; ubool pad; u32 tap; ufloat* ip_buff; //ÊäÈëÊý¾ÝBUFFER. TAPS+WINDOW_SIZE-1 ufloat* op_buff; //Êä³öÊý¾ÝBUFFER.WINDOW_SIZE ufloat* cf_buff; //ϵÊýBUFFER. TAPS,×î´ó1024. ufloat* cf_temp; //ϵÊýÁÙʱBUFFER. TAPS,×î´ó1024. s32* tcb ;//DMA tcb. struct FIR_tcb* next; uvoid* content; acc_completely_handler callback; }; struct FIR_tcb_head { u8 status; u8 num ; u16 pad ; u32 count; clock_t clock_start; clock_t clock_stop; clock_t cycles; struct FIR_tcb* first; struct FIR_tcb* last; }; static volatile struct FIR_tcb_head firHead ; uvoid FirAccIsr (u32 iid, uvoidptr arg) { if(*pREG_FIR0_DMASTAT & BITM_FIR_DMASTAT_ACDONE){ //All Channels Done firHead.clock_stop = clock(); firHead.cycles = firHead.clock_stop-firHead.clock_start; //Disable accelerator *pREG_FIR0_CTL1 &= ~(BITM_FIR_CTL1_EN); firHead.status = acc_completely; firHead.count++; } if(firHead.status == acc_completely) { for(struct FIR_tcb* fir = firHead.first; fir != NULL ; fir = fir->next) { if(fir->callback) fir->callback(fir->content); } firHead.status = acc_idle; } } uvoid fir_acc_init() { firHead.count =0; firHead.num =0 ; firHead.status = acc_idle ; firHead.first = NULL; firHead.last = NULL; adi_int_InstallHandler(INTR_FIR0_DMA, FirAccIsr, 0, true); } //Æô¶¯FIR¼ÓËÙÆ÷ uvoid fir_acc_startup() { s32 restarting = 0; if(firHead.status == acc_idle && firHead.num > 0) { for(struct FIR_tcb* fir = firHead.first; fir != NULL ; fir = fir->next) { if(fir->cp_update) { memcpy((uvoid*)fir->cf_buff, fir->cf_temp , fir->tap*sizeof(ufloat)); fir->cp_update = ufalse; } } restarting = 1; } if(restarting) { //firHead.last->tcb[0] = saddr(firHead.first->tcb+12) ; //restart *pREG_FIR0_CHNPTR = (uint32_t)(saddr(firHead.first->tcb+12)); firHead.clock_start = clock(); //Initializing the chain pointer register //*pREG_FIR0_CTL1 = BITM_FIR_CTL1_EN|BITM_FIR_CTL1_DMAEN|(firHead.num -1)<ip_buff; } return NULL; } ufloat* fir_get_output_dataptr(const uvoid* tcb) { struct FIR_tcb* fir = (struct FIR_tcb*)tcb; if(tcb) { return fir->op_buff; } return NULL; } uvoid fir_get_dataptr(const uvoid* tcb, ufloat** ip, ufloat**op , ufloat**cf,ufloat**cf_tmp) { struct FIR_tcb* fir = (struct FIR_tcb*)tcb; if(fir) { *ip = fir->ip_buff ; *op = fir->op_buff ; *cf = fir->cf_buff ; *cf_tmp = fir->cf_temp; } } const uvoid* fir_acc_add(u16 win_size ,u16 tap ,ufloat* cp ,uvoid* content ,acc_completely_handler cb) { struct FIR_tcb* fir = NULL; // if(firHead.num >= 8) { // return NULL; // } fir = (struct FIR_tcb*)sram_malloc(SRAM_L2, mem_any, sizeof(struct FIR_tcb)); if(fir == NULL) { printf("fir malloc fail.\n"); return NULL; } //Çý¶¯Óõ½µÄBUFFER±ØÐë·Åµ½L1ÄÚ²¿. s32* tcb = sram_malloc(SRAM_L1, mem_any, sizeof(s32)*13); ufloat* input_buffer = sram_malloc(SRAM_L1, mem_any, sizeof(ufloat)*(win_size+tap-1)); ufloat* output_buffer = sram_malloc(SRAM_L1, mem_any, sizeof(ufloat)*win_size); ufloat* coeffs_buffer = sram_malloc(SRAM_L1, mem_any, sizeof(ufloat)*tap); if(!tcb || !input_buffer || !output_buffer || !coeffs_buffer) { printf("fir buffer malloc fail.\n"); free(input_buffer); free(output_buffer); free(coeffs_buffer); free(tcb); return NULL; } memset(coeffs_buffer , 0 ,tap*sizeof(ufloat)); memset(output_buffer , 0 ,win_size*sizeof(ufloat)); memset(input_buffer , 0 ,(tap+win_size -1)*sizeof(ufloat)); fir->ip_buff = input_buffer; fir->op_buff = output_buffer; fir->cf_buff = coeffs_buffer; fir->cf_temp = cp; fir->tcb = tcb ; fir->content = content; fir->cp_update = ufalse; fir->tap = tap; fir->callback = cb; //page 38¨C23 fir->tcb[0] = 0; //FIR_CHNPTR fir->tcb[1] = tap; //FIR_COEFCNT fir->tcb[2] = 1; //FIR_COEFMOD fir->tcb[3] = saddr(coeffs_buffer); //FIR_COEFIDX fir->tcb[4] = saddr(output_buffer); //FIR_OUTBASE fir->tcb[5] = win_size; //FIR_OUTCNT fir->tcb[6] = 1; //FIR_OUTMOD fir->tcb[7] = saddr(output_buffer);//saddr(output_buffer); //FIR_OUTIDX fir->tcb[8] = saddr(input_buffer); //FIR_INBASE fir->tcb[9] = tap+win_size-1; //FIR_INCNT fir->tcb[10] = 1; //FIR_INMOD fir->tcb[11] = saddr(input_buffer); //FIR_INIDX fir->tcb[12] = (tap-1)|((win_size-1)<<14); //FIR_CTL2 fir->next = NULL; if(firHead.first == NULL) { firHead.first = fir; firHead.last = fir; } else { firHead.last->tcb[0] = saddr(fir->tcb+12) ; firHead.last->next = fir; firHead.last = fir ; } firHead.num ++; return fir; } uvoid fir_acc_update_coeffs(const uvoid* tcb) { struct FIR_tcb* fir = (struct FIR_tcb*)tcb; if(tcb != NULL) { fir->cp_update = 1; } } uvoid fir_acc_remove(const uvoid* tcb) { struct FIR_tcb* fir = firHead.first; struct FIR_tcb* prev = firHead.first; struct FIR_tcb* elem = (struct FIR_tcb*)tcb; //delete tcb. while(fir != NULL) { if(fir == elem){ if(fir == prev) { //ɾ³ýµÚÒ»¸öÔªËØ firHead.first = fir->next ; prev = fir = fir->next ; } else { prev->next = fir->next ; fir = fir->next; } free(elem->ip_buff); free(elem->op_buff); free(elem->cf_buff); free(elem->tcb); free(elem); firHead.num --; } else { prev = fir; fir = fir->next; } } }