/*
|
* FIR_acc.c
|
*
|
* Created on: 2022Äê5ÔÂ13ÈÕ
|
* Author: graydon
|
*/
|
#include <services/int/adi_int.h>
|
#include <string.h>
|
#include <time.h>
|
#include <stdio.h>
|
#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)<<BITP_FIR_CTL1_CH|BITM_FIR_CTL1_BURSTEN;
|
*pREG_FIR0_CTL1 = BITM_FIR_CTL1_EN|BITM_FIR_CTL1_DMAEN|((firHead.num -1)<<BITP_FIR_CTL1_CH);
|
|
firHead.status = acc_processing;
|
}
|
}
|
|
ufloat* fir_get_input_dataptr(const uvoid* tcb)
|
{
|
struct FIR_tcb* fir = (struct FIR_tcb*)tcb;
|
if(tcb) {
|
return fir->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;
|
}
|
}
|
}
|