doubao_chat/apps/common/jl_math/jl_fft.c

1728 lines
73 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "system/includes.h"
#include "app_config.h"
#include "fftvec_math_drv.h"
#include "_kiss_fft_guts.h"
#if defined CONFIG_ASR_ALGORITHM || defined CONFIG_REVERB_MODE_ENABLE || defined CONFIG_AEC_ENC_ENABLE || defined CONFIG_DNS_ENC_ENABLE || defined CONFIG_M4A_DEC_ENABLE || defined CONFIG_NEW_M4A_DEC_ENABLE || defined CONFIG_AAC_DEC_ENABLE || defined CONFIG_WMA_DEC_ENABLE || defined CONFIG_SPECTRUM_FFT_EFFECT_ENABLE
static DEFINE_SPINLOCK(fft_lock);
#define FFT_REAL 1 //complex
#define IFFT_DIV2 (3-FFT_REAL)
#define FFT_ISR_IE 0
//软件fft算法
/* #define KISS_FFT */
#define SHR(a,shift) ((a) >> (shift))
#define PSHR(a,shift) ((a)>=0?(SHR((a)+(1<<(shift-1)),shift)):\
(SHR((a)+(1<<(shift-1))-1,shift)))
#if defined CONFIG_WMA_DEC_ENABLE
#define MAX_FFT_SUPPORT_POINT_NUM 2048
#else
#define MAX_FFT_SUPPORT_POINT_NUM 1024
#endif
#if defined CONFIG_CPU_WL82 && defined CONFIG_ASR_ALGORITHM
sec(.fft_data) static int datain[MAX_FFT_SUPPORT_POINT_NUM];
sec(.fft_data) static int datain_y[MAX_FFT_SUPPORT_POINT_NUM];
sec(.fft_data) static int dataout[MAX_FFT_SUPPORT_POINT_NUM + 2];
#else
#if defined CONFIG_VIDEO_ENABLE
sec(.fft_data) static int datain[MAX_FFT_SUPPORT_POINT_NUM + 2];
sec(.fft_data) static int *dataout = datain;
sec(.fft_data) static int datain_y[0];
#else
sec(.fft_data) static int datain[MAX_FFT_SUPPORT_POINT_NUM];
sec(.fft_data) static int dataout[MAX_FFT_SUPPORT_POINT_NUM + 2];
sec(.fft_data) static int datain_y[0];
#endif
#endif
typedef struct fft_config_dat {
unsigned long fft0_con;
unsigned long fft0_iadr;
unsigned long fft0_oadr;
unsigned long fft0_null;
} fft_config_struct;
sec(.fft_data) static fft_config_struct fft_config;
sec(.fft_data) static hwvec_ctx_t g_vector_core_set;
static const struct {
u32 block;
u32 config;
} complex_tab[] = {
{ 128, COMPLEX_FFT128_CONFIG },
{ 128, COMPLEX_IFFT128_CONFIG },
{ 256, COMPLEX_FFT256_CONFIG },
{ 256, COMPLEX_IFFT256_CONFIG },
{ 512, COMPLEX_FFT512_CONFIG },
{ 512, COMPLEX_IFFT512_CONFIG },
{ 1024, COMPLEX_FFT1024_CONFIG },
{ 1024, COMPLEX_IFFT1024_CONFIG},
{ 2048, COMPLEX_FFT2048_CONFIG },
{ 2048, COMPLEX_IFFT2048_CONFIG},
{ 10, COMPLEX_FFT10_CONFIG },
{ 10, COMPLEX_IFFT10_CONFIG },
{ 15, COMPLEX_FFT15_CONFIG },
{ 15, COMPLEX_IFFT15_CONFIG },
{ 20, COMPLEX_FFT20_CONFIG },
{ 20, COMPLEX_IFFT20_CONFIG },
{ 30, COMPLEX_FFT30_CONFIG },
{ 30, COMPLEX_IFFT30_CONFIG },
{ 32, COMPLEX_FFT32_CONFIG },
{ 32, COMPLEX_IFFT32_CONFIG },
{ 40, COMPLEX_FFT40_CONFIG },
{ 40, COMPLEX_IFFT40_CONFIG },
{ 60, COMPLEX_FFT60_CONFIG },
{ 60, COMPLEX_IFFT60_CONFIG },
{ 64, COMPLEX_FFT64_CONFIG },
{ 64, COMPLEX_IFFT64_CONFIG },
{ 80, COMPLEX_FFT80_CONFIG },
{ 80, COMPLEX_IFFT80_CONFIG },
{ 120, COMPLEX_FFT120_CONFIG },
{ 120, COMPLEX_IFFT120_CONFIG },
{ 160, COMPLEX_FFT160_CONFIG },
{ 160, COMPLEX_IFFT160_CONFIG },
{ 240, COMPLEX_FFT240_CONFIG },
{ 240, COMPLEX_IFFT240_CONFIG },
{ 320, COMPLEX_FFT320_CONFIG },
{ 320, COMPLEX_IFFT320_CONFIG },
{ 480, COMPLEX_FFT480_CONFIG },
{ 480, COMPLEX_IFFT480_CONFIG },
{ 960, COMPLEX_FFT960_CONFIG },
{ 960, COMPLEX_IFFT960_CONFIG },
};
static const struct {
u32 block;
u32 config;
} real_tab[] = {
{ 128, REAL_FFT128_CONFIG },
{ 128, REAL_IFFT128_CONFIG },
{ 256, REAL_FFT256_CONFIG },
{ 256, REAL_IFFT256_CONFIG },
{ 512, REAL_FFT512_CONFIG },
{ 512, REAL_IFFT512_CONFIG },
{ 1024, REAL_FFT1024_CONFIG },
{ 1024, REAL_IFFT1024_CONFIG},
{ 2048, REAL_FFT2048_CONFIG },
{ 2048, REAL_IFFT2048_CONFIG},
{ 20, REAL_FFT20_CONFIG },
{ 20, REAL_IFFT20_CONFIG },
{ 30, REAL_FFT30_CONFIG },
{ 30, REAL_IFFT30_CONFIG },
{ 40, REAL_FFT40_CONFIG },
{ 40, REAL_IFFT40_CONFIG },
{ 60, REAL_FFT60_CONFIG },
{ 60, REAL_IFFT60_CONFIG },
{ 64, REAL_FFT64_CONFIG },
{ 64, REAL_IFFT64_CONFIG },
{ 80, REAL_FFT80_CONFIG },
{ 80, REAL_IFFT80_CONFIG },
{ 120, REAL_FFT120_CONFIG },
{ 120, REAL_IFFT120_CONFIG },
{ 160, REAL_FFT160_CONFIG },
{ 160, REAL_IFFT160_CONFIG },
{ 240, REAL_FFT240_CONFIG },
{ 240, REAL_IFFT240_CONFIG },
{ 320, REAL_FFT320_CONFIG },
{ 320, REAL_IFFT320_CONFIG },
{ 480, REAL_FFT480_CONFIG },
{ 480, REAL_IFFT480_CONFIG },
{ 960, REAL_FFT960_CONFIG },
{ 960, REAL_IFFT960_CONFIG },
};
#ifdef KISS_FFT
//是否使用软硬混合fft
#define SOFT_FFT_ENABLE
typedef struct kiss_config {
kiss_fft_cfg forward;
kiss_fft_cfg backward;
int N;
float *fft_in;
float *fft_out;
} kiss_config_t;
static kiss_config_t *kiss_512;
static kiss_config_t *kiss_1024;
static u8 spin_is_lock()
{
return fft_lock.rwlock;
}
//input: only real
//output: interleave real and image, size is (N/2+1)*2
__attribute__((always_inline))
void kiss_cfg_fft(void *table, int *in, int *out)
{
kiss_config_t *t = (kiss_config_t *)table;
float scale = 1;// / t->N;
for (int i = 0; i < t->N; i++) {
t->fft_in[i * 2] = in[i] * scale;
t->fft_in[i * 2 + 1] = 0;
}
kiss_fft(t->forward, t->fft_in, t->fft_out);
for (int i = 0; i < t->N + 2; i++) {
out[i] = t->fft_out[i];
}
}
//output: only real
//input: interleave real and image, size is (N/2+1)*2
__attribute__((always_inline))
void kiss_cfg_ifft(void *table, int *in, int *out)
{
kiss_config_t *t = (kiss_config_t *)table;
float scale;
int i;
scale = 1.0f / t->N;
for (int i = 0; i < t->N / 2 + 1; i++) {
t->fft_in[i * 2] = in[i * 2];
t->fft_in[i * 2 + 1] = in[i * 2 + 1];
}
for (int i = t->N / 2 + 1; i < t->N; i++) {
t->fft_in[i * 2] = t->fft_in[(t->N - i) * 2];
t->fft_in[i * 2 + 1] = -t->fft_in[(t->N - i) * 2 + 1];
}
kiss_fft(t->backward, t->fft_in, t->fft_out);
for (int i = 0; i < t->N; i++) {
out[i] = t->fft_out[i * 2];
}
for (i = 0; i < t->N; i++) {
out[i] *= scale;
}
}
void kiss_config_uninit()
{
if (kiss_512->fft_in) {
free(kiss_512->fft_in);
kiss_512->fft_in = NULL;
}
if (kiss_512->fft_out) {
free(kiss_512->fft_out);
kiss_512->fft_out = NULL;
}
kiss_fft_free(kiss_512->forward);
kiss_fft_free(kiss_512->backward);
free(kiss_512);
if (kiss_1024->fft_in) {
free(kiss_1024->fft_in);
kiss_1024->fft_in = NULL;
}
if (kiss_1024->fft_out) {
free(kiss_1024->fft_out);
kiss_1024->fft_out = NULL;
}
kiss_fft_free(kiss_1024->forward);
kiss_fft_free(kiss_1024->backward);
free(kiss_1024);
}
void kiss_config_init()
{
kiss_512 = (kiss_config_t *)calloc(1, sizeof(kiss_config_t));
if (!kiss_512) {
printf("%s, kiss_512 malloc fail\n\r", __func__);
return;
}
kiss_1024 = (kiss_config_t *)calloc(1, sizeof(kiss_config_t));
if (!kiss_1024) {
printf("%s, kiss_1024 malloc fail\n\r", __func__);
return;
}
kiss_512->N = 512;
kiss_512->forward = kiss_fft_alloc(kiss_512->N, 0, NULL, NULL);
kiss_512->backward = kiss_fft_alloc(kiss_512->N, 1, NULL, NULL);
kiss_512->fft_in = (float *)calloc(1, sizeof(float) * kiss_512->N * 2);
if (!kiss_512->fft_in) {
printf("%s, kiss_512 fft_in malloc fail\n\r", __func__);
return;
}
kiss_512->fft_out = (float *)calloc(1, sizeof(float) * kiss_512->N * 2);
if (!kiss_512->fft_out) {
printf("%s, kiss_512 fft_out malloc fail\n\r", __func__);
return;
}
kiss_1024->N = 1024;
kiss_1024->forward = kiss_fft_alloc(kiss_1024->N, 0, NULL, NULL);
kiss_1024->backward = kiss_fft_alloc(kiss_1024->N, 1, NULL, NULL);
kiss_1024->fft_in = (float *)calloc(1, sizeof(float) * kiss_1024->N * 2);
if (!kiss_1024->fft_in) {
printf("%s, kiss_1024 fft_in malloc fail\n\r", __func__);
return;
}
kiss_1024->fft_out = (float *)calloc(1, sizeof(float) * kiss_1024->N * 2);
if (!kiss_1024->fft_out) {
printf("%s, kiss_1024 fft_out malloc fail\n\r", __func__);
return;
}
}
late_initcall(kiss_config_init);
#endif
__attribute__((always_inline))
static int vc_hw_fft(int *coef_in, int blockbit, int *coef_out, int real, int same)
{
//init pi32v2 fft hardware
int blocklen = 1 << blockbit;
JL_FFT->CON = 0;
#ifdef CONFIG_CPU_WL82
int i;
if (real) {
for (i = 0; i < ARRAY_SIZE(real_tab); i += 2) {
if (blocklen == real_tab[i].block) {
fft_config.fft0_con = real_tab[i].config | (same << 0);
break;
}
}
if (i >= ARRAY_SIZE(real_tab)) {
return -1;
}
} else {
for (i = 0; i < ARRAY_SIZE(complex_tab); i += 2) {
if (blocklen == complex_tab[i].block) {
fft_config.fft0_con = complex_tab[i].config | (same << 0);
break;
}
}
if (i >= ARRAY_SIZE(complex_tab)) {
return -1;
}
}
#else
fft_config.fft0_con = (blocklen << 16) | ((blockbit - 1 - real) << 8) | ((blockbit - real - 2) << 4) | (0 << 2) | (real << 1) | (same << 0);
#endif
fft_config.fft0_iadr = (unsigned int)coef_in;
fft_config.fft0_oadr = (unsigned int)coef_out;
JL_FFT->CADR = (unsigned int)&fft_config;
JL_FFT->CON = (1 << 8) | (0 << 6) | (FFT_ISR_IE << 2) | (0 << 1) | (1 << 0);
while ((JL_FFT->CON & (1 << 7)) == 0);
JL_FFT->CON |= (1 << 6);
return 0;
}
__attribute__((always_inline))
static int vc_hw_ifft(int *coef_in, int blockbit, int *coef_out, int real, int same)
{
//init pi32v2 fft hardware
int blocklen = 1 << blockbit;
JL_FFT->CON = 0;
#ifdef CONFIG_CPU_WL82
int i;
if (real) {
for (i = 0; i < ARRAY_SIZE(real_tab); i += 2) {
if (blocklen == real_tab[i + 1].block) {
fft_config.fft0_con = real_tab[i + 1].config | (same << 0);
break;
}
}
if (i >= ARRAY_SIZE(real_tab)) {
return -1;
}
} else {
for (i = 0; i < ARRAY_SIZE(complex_tab); i += 2) {
if (blocklen == complex_tab[i + 1].block) {
fft_config.fft0_con = complex_tab[i + 1].config | (same << 0);
break;
}
}
if (i >= ARRAY_SIZE(complex_tab)) {
return -1;
}
}
#else
fft_config.fft0_con = (blocklen << 16) | ((blockbit - 1 - real) << 8) | ((3 - real) << 4) | (1 << 2) | (real << 1) | (same << 0);
#endif
fft_config.fft0_iadr = (unsigned int)coef_in;
fft_config.fft0_oadr = (unsigned int)coef_out;
JL_FFT->CADR = (unsigned int)&fft_config;
JL_FFT->CON = (1 << 8) | (0 << 6) | (FFT_ISR_IE << 2) | (0 << 1) | (1 << 0);
while ((JL_FFT->CON & (1 << 7)) == 0);
JL_FFT->CON |= (1 << 6);
return 0;
}
/* SEC_USED(.fft_text) */
__attribute__((always_inline))
void jl_fft_1024(short *in, int *out)
{
spin_lock(&fft_lock);
for (int i = 0; i < 1024; i++) {
datain[i] = in[i];
}
vc_hw_fft(datain, 10, dataout, 1, datain == dataout ? 1 : 0);
memcpy(out, dataout, sizeof(int) * 1026);
spin_unlock(&fft_lock);
}
/* SEC_USED(.fft_text) */
__attribute__((always_inline))
void jl_fft_1024_ex(int *in, int *out)
{
#ifdef SOFT_FFT_ENABLE
if (spin_is_lock()) {
kiss_cfg_fft(kiss_1024, in, out);
} else
#endif
{
spin_lock(&fft_lock);
memcpy(datain, in, sizeof(int) * 1024);
vc_hw_fft(datain, 10, dataout, 1, datain == dataout ? 1 : 0);
memcpy(out, dataout, sizeof(int) * 1026);
spin_unlock(&fft_lock);
}
}
/* SEC_USED(.fft_text) */
__attribute__((always_inline))
void jl_fft_512(int *in, int *out)
{
#ifdef SOFT_FFT_ENABLE
if (spin_is_lock()) {
kiss_cfg_fft(kiss_512, in, out);
} else
#endif
{
spin_lock(&fft_lock);
memcpy(datain, in, sizeof(int) * 512);
vc_hw_fft(datain, 9, dataout, 1, datain == dataout ? 1 : 0);
memcpy(out, dataout, sizeof(int) * 514);
spin_unlock(&fft_lock);
}
}
/* SEC_USED(.fft_text) */
__attribute__((always_inline))
int jl_ifft_1024(int *in, short *out)
{
int i;
int tData_tmp = 0, tData_max = 0, shift = 0;
spin_lock(&fft_lock);
memcpy(dataout, in, sizeof(int) * 1026);
vc_hw_ifft(dataout, 10, datain, 1, dataout == datain ? 1 : 0);
for (i = 0; i < 1024; i++) {
tData_tmp = datain[i] > 0 ? datain[i] : (-datain[i]);
if (tData_max < tData_tmp) {
tData_max = tData_tmp;
}
}
while (tData_max > 32767) {
tData_max >>= 1;
shift += 1;
}
for (i = 0; i < 1024; i += 4) {
out[i] = PSHR(datain[i], shift);
out[i + 1] = PSHR(datain[i + 1], shift);
out[i + 2] = PSHR(datain[i + 2], shift);
out[i + 3] = PSHR(datain[i + 3], shift);
}
spin_unlock(&fft_lock);
return shift;
}
/* SEC_USED(.fft_text) */
__attribute__((always_inline))
void jl_ifft_1024_ex(int *in, int *out)
{
#ifdef SOFT_FFT_ENABLE
if (spin_is_lock()) {
kiss_cfg_ifft(kiss_1024, in, out);
} else
#endif
{
spin_lock(&fft_lock);
memcpy(dataout, in, sizeof(int) * 1026);
vc_hw_ifft(dataout, 10, datain, 1, dataout == datain ? 1 : 0);
memcpy(out, datain, sizeof(int) * 1024);
spin_unlock(&fft_lock);
}
}
/* SEC_USED(.fft_text) */
__attribute__((always_inline))
void jl_ifft_512(int *in, int *out)
{
#ifdef SOFT_FFT_ENABLE
if (spin_is_lock()) {
kiss_cfg_ifft(kiss_512, in, out);
} else
#endif
{
spin_lock(&fft_lock);
memcpy(datain, in, sizeof(int) * 514);
vc_hw_ifft(datain, 9, dataout, 1, dataout == datain ? 1 : 0);
memcpy(out, dataout, sizeof(int) * 512);
spin_unlock(&fft_lock);
}
}
__attribute__((always_inline))
static u32 find_pow(u32 value)
{
u32 i = 0;
while (value) {
value >>= 1;
if (++i > 11) {
ASSERT(NULL, "pow <= 10");
}
}
return i - 1;
}
__attribute__((always_inline))
void jl_fft_N(int *in, int *out, int fft_N)
{
spin_lock(&fft_lock);
memcpy(datain, in, sizeof(int) * fft_N);
vc_hw_fft(datain, find_pow(fft_N), dataout, 1, dataout == datain ? 1 : 0);
memcpy(out, dataout, sizeof(int) * (fft_N + 2));
spin_unlock(&fft_lock);
}
__attribute__((always_inline))
void jl_ifft_N(int *in, int *out, int fft_N)
{
spin_lock(&fft_lock);
memcpy(dataout, in, sizeof(int) * (fft_N + 2));
vc_hw_ifft(dataout, find_pow(fft_N), datain, 1, dataout == datain ? 1 : 0);
memcpy(out, datain, sizeof(int) * fft_N);
spin_unlock(&fft_lock);
}
__attribute__((always_inline))
void jl_complex_fft_n(int *in, int *out, int bits)
{
int len = 1 << bits;
spin_lock(&fft_lock);
memcpy(datain, in, sizeof(int) * len);
vc_hw_fft(datain, bits - 1, dataout, 0, datain == dataout ? 1 : 0);
memcpy(out, dataout, sizeof(int) * len);
spin_unlock(&fft_lock);
}
__attribute__((always_inline))
void jl_complex_ifft_n(int *in, int *out, int bits)
{
int len = 1 << bits;
spin_lock(&fft_lock);
memcpy(datain, in, sizeof(int) * len);
vc_hw_ifft(datain, bits - 1, dataout, 0, datain == dataout ? 1 : 0);
memcpy(out, dataout, sizeof(int) * len);
spin_unlock(&fft_lock);
}
void hw_fft_run(int cfg, const int *coef_in, int *coef_out)
{
int len;
int *in = datain, *out = dataout;
if (!coef_in || !coef_out) {
return;
}
if (datain == dataout) {
cfg |= BIT(0);
} else {
cfg &= ~BIT(0);
}
if (cfg & BIT(1)) {
len = (cfg & 0xFFF0000) >> 16;
if (cfg & BIT(2)) {
len += 2;
in = dataout;
out = datain;
}
} else {
len = (cfg & 0xFFF0000) >> (16 - 1);
}
spin_lock(&fft_lock);
memcpy(in, coef_in, sizeof(int) * len);
JL_FFT->CON = 0;
fft_config.fft0_con = cfg;
fft_config.fft0_iadr = (unsigned int)in;
fft_config.fft0_oadr = (unsigned int)out;
JL_FFT->CADR = (unsigned int)&fft_config;
JL_FFT->CON = (1 << 8) | (0 << 6) | (FFT_ISR_IE << 2) | (0 << 1) | (1 << 0);
while ((JL_FFT->CON & (1 << 7)) == 0);
JL_FFT->CON |= (1 << 6);
if (cfg & BIT(1)) {
if (cfg & BIT(2)) {
len -= 2;
} else {
len += 2;
}
}
memcpy(coef_out, out, sizeof(int) * len);
spin_unlock(&fft_lock);
}
void hw_fft_wrap(fft_config_struct *ctx)
{
hw_fft_run(ctx->fft0_con, (const int *)ctx->fft0_iadr, (int *)ctx->fft0_oadr);
}
#if defined CONFIG_NEW_M4A_DEC_ENABLE
int hw_fft_core(int cfg, const int *coef_in, int *coef_out)
{
hw_fft_run(cfg, coef_in, coef_out);
}
#endif
unsigned int Get_FFT_Base(void)
{
return JL_FFT_BASE;
}
__attribute__((always_inline)) inline
void fast_i2f(const int *in, float *out, int N, float scale)
{
int tmp32_1;
asm volatile(
" 1: \n\t"
" rep %1 { \n\t"
" %0 = [%2++=4] \n\t"
" %0 = itof(%0) \n\t"
" %0 = %0 * %4 (f) \n\t"
" [%3++=4] = %0 \n\t"
" } \n\t"
" if(%1>0) goto 1b \n\t"
: "=&r"(tmp32_1),
"=&r"(N),
"=&r"(in),
"=&r"(out),
"=&r"(scale)
: "0"(tmp32_1),
"1"(N),
"2"(in),
"3"(out),
"4"(scale)
:);
}
__attribute__((always_inline)) inline
void fast_f2i(const float *in, int *out, int N, float scale)
{
int tmp32_1;
asm volatile(
" 1: \n\t"
" rep %1 { \n\t"
" %0 = [%2++=4] \n\t"
" %0 = %0 * %4 (f) \n\t"
" %0 = ftoi(%0)(even) \n\t"
" [%3++=4] = %0 \n\t"
" } \n\t"
" if(%1>0) goto 1b \n\t"
: "=&r"(tmp32_1),
"=&r"(N),
"=&r"(in),
"=&r"(out),
"=&r"(scale)
: "0"(tmp32_1),
"1"(N),
"2"(in),
"3"(out),
"4"(scale)
:);
}
//hwfft_ctx_t结构体和FFT输入输出的数据地址一定要放在内部ram
__attribute__((always_inline)) inline
void hwfft_exec_batch(hwfft_ctx_t *ctx, int nbatch)
{
spin_lock(&fft_lock);
JL_FFT->CADR = (unsigned long)(ctx);
//CLR //FFT //ie //en
JL_FFT->CON = (nbatch << 8) | (1 << 6) | (0 << 3) | (FFT_ISR_IE << 2) | (1 << 0);
while ((JL_FFT->CON & (1 << 7)) == 0);
JL_FFT->CON |= (1 << 6);
spin_unlock(&fft_lock);
};
__attribute__((always_inline)) inline
void hwfft_exec_once(hwfft_ctx_t *ctx)
{
spin_lock(&fft_lock);
JL_FFT->CADR = (unsigned long)(ctx);
//CLR //FFT //ie //en
JL_FFT->CON = (1 << 8) | (1 << 6) | (0 << 3) | (FFT_ISR_IE << 2) | (1 << 0);
while ((JL_FFT->CON & (1 << 7)) == 0);
JL_FFT->CON |= (1 << 6);
spin_unlock(&fft_lock);
};
__attribute__((always_inline)) inline
int hwfft_get_nfft(unsigned long fft_config)
{
int nfft = (fft_config >> 16) & 0xfff;
return nfft;
};
//0---forward 1---backward
__attribute__((always_inline)) inline
int hwfft_get_backward(unsigned long fft_config)
{
return ((fft_config & (1 << 2)) != 0);
};
//0---complex 1---real
__attribute__((always_inline)) inline
int hwfft_get_real(unsigned long fft_config)
{
return ((fft_config & (1 << 1)) != 0);
};
__attribute__((always_inline)) inline
int hwfft_check_fft_config(unsigned long fft_config, int nfft, int backward, int real)
{
if (hwfft_get_nfft(fft_config) != nfft) {
printf("fft nfft mismatch!\n");
return -1;
}
if (hwfft_get_backward(fft_config) != backward) {
printf("fft backward direction mismatch!\n");
return -1;
}
if (hwfft_get_real(fft_config) != real) {
printf("fft real mode mismatch!\n");
return -1;
}
return 0;
};
__attribute__((always_inline)) inline
void hwfft_fill_fft_ctx(hwfft_ctx_t *ctx, unsigned long fft_config, long *iadr, long *oadr)
{
unsigned long config;
if (iadr == oadr) {
config = fft_config | FFT_SAME_ADR;
} else {
config = fft_config & (~FFT_SAME_ADR);
}
ctx->fft_con = config;
ctx->fft_iadr = (unsigned long)iadr;
ctx->fft_oadr = (unsigned long)oadr;
ctx->fft_null = 0;
// printf("config1:%d %x\n",config,ctx->fft_iadr);
};
__attribute__((always_inline)) inline
void hwfft_ifft_scale(long *iadr, int nfft)
{
int scale;
int q;
long config = VECX_S32 | VECY_S32 | VECZ_S32;
// printf("nfft:%d\n",nfft);
if (nfft % 15 == 0) {
scale = 1118481;
q = 21;
vector_real_mul_const(iadr, iadr, nfft, q, scale, config);
} else if (nfft % 10 == 0) {
scale = 1677722;//1864135;
q = 21;
vector_real_mul_const(iadr, iadr, nfft, q, scale, config);
}
}
__attribute__((always_inline)) inline
void hwfft_fft_i32(hwfft_ctx_t *ctx)
{
hwfft_exec_once(ctx);
};
__attribute__((always_inline)) inline
void hwfft_ifft_i32(hwfft_ctx_t *ctx)
{
int real = hwfft_get_real(ctx->fft_con);
int nfft = hwfft_get_nfft(ctx->fft_con);
hwfft_exec_once(ctx);
hwfft_ifft_scale((long *)ctx->fft_oadr, nfft * (2 - real));
};
__attribute__((always_inline)) inline
void hwfft_fft_f32(hwfft_ctx_t *ctx, float scale)
{
int nfft = hwfft_get_nfft(ctx->fft_con);
int real = hwfft_get_real(ctx->fft_con);
fast_f2i((float *)ctx->fft_iadr, (int *)ctx->fft_iadr, nfft * (2 - real), scale);
hwfft_fft_i32(ctx);
fast_i2f((int *)ctx->fft_oadr, (float *)ctx->fft_oadr, nfft * (2 - real) + 2 * real, 1.0f / scale); // com 0 real 1
};
__attribute__((always_inline)) inline
void hwfft_ifft_f32(hwfft_ctx_t *ctx, float scale)
{
int nfft = hwfft_get_nfft(ctx->fft_con);
int real = hwfft_get_real(ctx->fft_con);
fast_f2i((float *)ctx->fft_iadr, (int *)ctx->fft_iadr, nfft * (2 - real) + 2 * real, scale);
hwfft_ifft_i32(ctx);
fast_i2f((int *)ctx->fft_oadr, (float *)ctx->fft_oadr, nfft * (2 - real), 1.0f / scale);
};
//////////////////////////////////////////////////////////////////////////
//VECTOR
__attribute__((always_inline)) inline
void hwvec_exec(
void *xptr,
void *yptr,
void *zptr,
short x_inc,
short y_inc,
short z_inc,
short nlen,
short nloop,
char q,
long config,
long const_dat
)
{
//硬件锁上锁
spin_lock(&fft_lock);
char vec_cpy_real = 0;
char vec_zptr_cpy_dot = 0;
//获取段内数组的地址, 硬件运算数据都需在段内进行
void *_xptr = &datain[0];
void *_yptr = &datain_y[0];
void *_zptr = &dataout[0];
//区分复制长度(nlen为数据个数)是实数还是复数, 复数需乘2
if (config & VEC_CPY_REAL_OR_VEC) {
vec_cpy_real = 1;
config &= ~VEC_CPY_REAL_OR_VEC;
#ifdef CONFIG_CPU_WL82
if (xptr < (void *)__NONCPU_ADDR__) {
_xptr = xptr;
} else
#endif
{
memcpy(_xptr, xptr, nlen * 4);
}
//是否需要复制输入YPTR
if (config & VEC_YPTR_NOCPY) {
config &= ~VEC_YPTR_NOCPY;
} else {
#ifdef CONFIG_CPU_WL82
if (yptr < (void *)__NONCPU_ADDR__) {
_yptr = yptr;
} else
#endif
{
memcpy(_yptr, yptr, nlen * 4);
}
}
} else {
#ifdef CONFIG_CPU_WL82
if (xptr < (void *)__NONCPU_ADDR__) {
_xptr = xptr;
} else
#endif
{
memcpy(_xptr, xptr, nlen * 4 * 2);
}
//是否需要复制输入YPTR
if (config & VEC_YPTR_NOCPY) {
config &= ~VEC_YPTR_NOCPY;
} else {
#ifdef CONFIG_CPU_WL82
if (yptr < (void *)__NONCPU_ADDR__) {
_yptr = yptr;
} else
#endif
{
memcpy(_yptr, yptr, nlen * 4 * 2);
}
}
}
//是否需要输入zptr数据
if (config & VEC_ZPTR_CPY) {
config &= ~VEC_ZPTR_CPY;
if (vec_cpy_real) {
#ifdef CONFIG_CPU_WL82
if (zptr < (void *)__NONCPU_ADDR__) {
_zptr = zptr;
} else
#endif
{
memcpy(_zptr, zptr, nlen * 4);
}
} else {
#ifdef CONFIG_CPU_WL82
if (zptr < (void *)__NONCPU_ADDR__) {
_zptr = zptr;
} else
#endif
{
memcpy(_zptr, zptr, nlen * 4 * 2);
}
}
} else if (zptr == xptr) {
_zptr = _xptr;
} else if (zptr == yptr) {
_zptr = _yptr;
}
//区分ZPTR输出结果复制长度是一个点还是向量
if (config & VEC_ZPTR_CPY_DOT) {
vec_zptr_cpy_dot = 1;
config &= ~VEC_ZPTR_CPY_DOT;
}
//VECTOR寄存器的配置
g_vector_core_set.vector_con = config;
g_vector_core_set.vector_config0 = (q << 24) | (nloop << 12) | (nlen);
g_vector_core_set.vector_config1 = (z_inc << 20) | (y_inc << 10) | x_inc;
//printf("nlen0:%d,nloop:%d,q:%d,config:%d,%d\n",nlen,nloop,q,config,const_dat);
g_vector_core_set.vector_xadr = (unsigned long)_xptr;
g_vector_core_set.vector_yadr = (unsigned long)_yptr;
g_vector_core_set.vector_zadr = (unsigned long)_zptr;
JL_FFT->CONST = const_dat;
JL_FFT->CADR = (unsigned long)(&g_vector_core_set);
/*printf("JL_FFT->CONST:%x\n",&g_vector_core_set);
printf("JL_FFT->vector_xadr:%x\n",g_vector_core_set.vector_xadr);
printf("JL_FFT->vector_yadr:%x\n",g_vector_core_set.vector_yadr);
printf("JL_FFT->vector_zadr:%x\n",g_vector_core_set.vector_zadr);
printf("JL_FFT->vector_config0:%x\n",g_vector_core_set.vector_config0);
printf("JL_FFT->vector_config1:%x\n",g_vector_core_set.vector_config1);*/
//开始运算
//nu | clr | vector | ie | en
JL_FFT->CON = (1 << 8) | (1 << 6) | (1 << 3) | (FFT_ISR_IE << 2) | (1 << 0);
//等待运算完成中断并清中断
while ((JL_FFT->CON & (1 << 7)) == 0);
JL_FFT->CON |= (1 << 6);
//获取输出数据
if (vec_zptr_cpy_dot) {
*(int *)zptr = *(int *)_zptr;
} else {
memcpy(zptr, _zptr, vec_cpy_real ? nlen * 4 : nlen * 4 * 2);
}
//硬件锁解锁
spin_unlock(&fft_lock);
}
//=========================================================================
// vector_complex_add
// dw bit[1:0] : x_dw 2: s32 1: s16 0:s8
// dw bit[3:2] : y_dw 2: s32 1: s16 0:s8
// dw bit[5:6] : z_dw 2: s32 1: s16 0:s8
// y_dw >= z_dw > x_dw
//
// x.real[0] = x[0], x.imge[0] = x[1]
// y.real[0] = y[0], y.imge[0] = y[1]
// *zptr, *yptr, *xptr: s32/s16/s8
// z[n] = saturated( y[n] + x[n] ) // 0 <= n < len*2
// z, y, x buf size must be(32bit x n), z_buf can be y_buf or x_buf
//=========================================================================
__attribute__((always_inline)) inline
void vector_complex_add(void *zptr, void *yptr, void *xptr, short len, long config)
{
config = config;
hwvec_exec(xptr, yptr, zptr, 0, 0, 0, (len << 1), 1, 0, config, 0);
}
//=========================================================================
// vector_complex_sub
// dw bit[1:0] : x_dw 2: s32 1: s16 0:s8
// dw bit[3:2] : y_dw 2: s32 1: s16 0:s8
// dw bit[5:6] : z_dw 2: s32 1: s16 0:s8
// y_dw >= z_dw > x_dw
//
// x.real[0] = x[0], x.imge[0] = x[1]
// y.real[0] = y[0], y.imge[0] = y[1]
// *zptr, *yptr, *xptr: s32/s16/s8
// z[n] = saturated( y[n] - x[n] ) // 0 <= n < len*2
// z, y, x buf size must be(32bit x n), z_buf can be y_buf or x_buf
//=========================================================================
__attribute__((always_inline)) inline
void vector_complex_sub(void *zptr, void *yptr, void *xptr, short len, long config)
{
config = config | VEC_SUB;
hwvec_exec(xptr, yptr, zptr, 0, 0, 0, (len << 1), 1, 0, config, 0);
}
//=========================================================================
// vector_complex_mul
// dw bit[1:0] : x_dw 2: s32 1: s16 0:s8
// dw bit[3:2] : y_dw 2: s32 1: s16 0:s8
// dw bit[5:6] : z_dw 2: s32 1: s16 0:s8
// y_dw >= z_dw > x_dw
// -32 < Q < 31
// x.real[0] = x[0], x.imge[0] = x[1]
// y.real[0] = y[0], y.imge[0] = y[1]
// z.real[0] = z[0], z.imge[0] = z[1]
// *zptr, *yptr, *xptr: s32/s16/s8
// z[n] = saturated(y[n]. * x[n]. / 2^q) // 0 <= n < len
// z, y, x buf size must be(32bit x n), z_buf can be y_buf or x_buf
//=========================================================================
__attribute__((always_inline)) inline
void vector_complex_mul(void *zptr, void *yptr, void *xptr, short len, char q, long config)
{
config = config | VEC_CPX_MUL_MODE;
hwvec_exec(xptr, yptr, zptr, 0, 0, 0, (len << 0), 1, q, config, 0);
}
//=========================================================================
// vector_complex_mac32
// dw bit[1:0] : x_dw 2: s32
// dw bit[3:2] : y_dw 2: s32
// dw bit[5:6] : z_dw 2: s32
// y_dw == z_dw == x_dw == 2
// -32 < Q < 31
// x.real[0] = x[0], x.imge[0] = x[1]
// y.real[0] = y[0], y.imge[0] = y[1]
// z.real[0] = z[0], z.imge[0] = z[1]
// *zptr, *yptr, *xptr: s32
// z[n] = saturated(z. + (y[n]. * x[n]. / 2^q)) // 0 <= n < len*2
// z, y, x buf size must be(32bit x n), z_buf can be y_buf or x_buf
//=========================================================================
__attribute__((always_inline)) inline
void vector_complex_mac32(void *zptr, void *yptr, void *xptr, short len, char q, long config)
{
//config = VEC_MAC32 | VECZ_S32 | VECY_S32 | VECX_S32 | VEC_CPX_MUL_MODE;
config = config | VEC_MAC32 | VECZ_S32 | VECY_S32 | VECX_S32 | VEC_CPX_MUL_MODE | VEC_ZPTR_CPY;
hwvec_exec(xptr, yptr, zptr, 0, 0, 0, (len << 0), 1, q, config, 0);
}
//=========================================================================
// vector_complex_msc32
// dw bit[1:0] : x_dw 2: s32
// dw bit[3:2] : y_dw 2: s32
// dw bit[5:6] : z_dw 2: s32
// y_dw == z_dw == x_dw == 2
// -32 < Q < 31
// x.real[0] = x[0], x.imge[0] = x[1]
// y.real[0] = y[0], y.imge[0] = y[1]
// z.real[0] = z[0], z.imge[0] = z[1]
// *zptr, *yptr, *xptr: s32
// z[n] = saturated(z[n]. - (y[n]. * x[n]. / 2^q)) // 0 <= n < len*2
// z, y, x buf size must be(32bit x n), z_buf can be y_buf or x_buf
//=========================================================================
__attribute__((always_inline)) inline
void vector_complex_msc32(void *zptr, void *yptr, void *xptr, short len, char q, long config)
{
config = config | VEC_MAC32 | VECZ_S32 | VECY_S32 | VECX_S32 | VEC_SUB | VEC_CPX_MUL_MODE;
hwvec_exec(xptr, yptr, zptr, 0, 0, 0, (len << 1), 1, q, config, 0);
}
//=========================================================================
// vector_complex_dot_product
// dw bit[1:0] : x_dw 2: s32 1: s16 0:s8
// dw bit[3:2] : y_dw 2: s32 1: s16 0:s8
// dw bit[5:6] : z_dw 2: s32 1: s16 0:s8
// y_dw >= z_dw > x_dw
// -32 < Q < 31
// x.real[0] = x[0], x.imge[0] = x[1]
// y.real[0] = y[0], y.imge[0] = y[1]
// z.real[0] = z[0], z.imge[0] = z[1]
// *zptr, *yptr, *xptr: s32/s16/s8
// z[n] = saturated(sum(y[n]. * x[n]. / 2^q)) // 0 <= n < len*2
// z, y, x buf size must be(32bit x n), z_buf can be y_buf or x_buf
//=========================================================================
__attribute__((always_inline)) inline
void vector_complex_dot_product(void *zptr, void *yptr, void *xptr, short len, char q, long config)
{
config = config | VEC_ACC | VEC_CPX_MUL_MODE;
hwvec_exec(xptr, yptr, zptr, 0, 0, 0, (len << 1), 1, q, config, 0);
}
//=========================================================================
// vector_complex_qdt
// dw bit[1:0] : x_dw 2: s32 1: s16 0:s8
// dw bit[3:2] : y_dw 2: s32 1: s16 0:s8
// dw bit[5:6] : z_dw 2: s32 1: s16 0:s8
// y_dw >= z_dw > x_dw
// -32 < Q < 31
// x.real[0] = x[0], x.imge[0] = x[1]
// z.real[0] = z[0], z.imge[0] = z[1]
// *zptr, *yptr, *xptr: s32/s16/s8
// z[n] = saturated((x[n].real^2 + x[n].imag^2) / 2^q) // 0 <= n < len/2
// z, y, x buf size must be(32bit x n), z_buf can be y_buf or x_buf
//=========================================================================
__attribute__((always_inline)) inline
void vector_complex_qdt(void *zptr, void *xptr, short len, char q, long config)
{
config = config | VEC_CPX_QDT | VEC_QDT | VEC_QDT_MODE | VEC_YPTR_NOCPY;
hwvec_exec(xptr, 0, zptr, 0, 0, 0, (len << 1), 1, q, config, 0);
}
//=========================================================================
// vector_complex_qdtsum
// dw bit[1:0] : x_dw 2: s32 1: s16 0:s8
// dw bit[5:6] : z_dw 3: s64 2: s32 1: s16 0:s8
// -32 < Q < 32
// *zptr, *yptr, *xptr: s32/s16/s8
// z[n] = (x[0].real^2 + x[0].image^2 + ... + x[n].real^2+ x[n].image^2) / 2^q) // 0 <= n < len
// z, y, x buf size must be(32bit x n), z_buf can be y_buf or x_buf
//=========================================================================
__attribute__((always_inline)) inline
void vector_complex_qdtsum(void *zptr, void *xptr, short len, char q, long config)
{
config = config | VEC_QDT | VEC_ACC | VEC_QDT_MODE;
hwvec_exec(xptr, 0, zptr, 0, 0, 0, (len << 1), 1, q, config, 0);
}
//=========================================================================
// vector_real_add
// dw bit[1:0] : x_dw 2: s32 1: s16 0:s8
// dw bit[3:2] : y_dw 2: s32 1: s16 0:s8
// dw bit[5:6] : z_dw 2: s32 1: s16 0:s8
// y_dw >= z_dw > x_dw
//
// *zptr, *yptr, *xptr: s32/s16/s8
// z[n] = saturated( y[n] + x[n] ) // 0 <= n < len
// z, y, x buf size must be(32bit x n), z_buf can be y_buf or x_buf
//=========================================================================
__attribute__((always_inline)) inline
void vector_real_add(void *zptr, void *yptr, void *xptr, short len, long config)
{
config = config | VEC_CPY_REAL_OR_VEC;
hwvec_exec(xptr, yptr, zptr, 0, 0, 0, len, 1, 0, config, 0);
}
//=========================================================================
// vector_real_add_dot_product
// dw bit[1:0] : x_dw 2: s32 1: s16 0:s8
// dw bit[3:2] : y_dw 2: s32 1: s16 0:s8
// dw bit[5:6] : z_dw 2: s32 1: s16 0:s8
// y_dw >= z_dw > x_dw
//
// *zptr, *yptr, *xptr: s32/s16/s8
// z = sum( y[n] + x[n] ) // 0 <= n < len
// z, y, x buf size must be(32bit x n), z_buf can be y_buf or x_buf
//=========================================================================
__attribute__((always_inline)) inline
void vector_real_add_dot_product(void *zptr, void *yptr, void *xptr, short len, long config)
{
config = config | VEC_CPY_REAL_OR_VEC | VEC_ZPTR_CPY_DOT;
hwvec_exec(xptr, yptr, zptr, 0, 0, 0, len, 1, 0, config, 0);
}
//=========================================================================
// vector_real_sub
// dw bit[1:0] : x_dw 2: s32 1: s16 0:s8
// dw bit[3:2] : y_dw 2: s32 1: s16 0:s8
// dw bit[5:6] : z_dw 2: s32 1: s16 0:s8
// y_dw >= z_dw > x_dw
//
// *zptr, *yptr, *xptr: s32/s16/s8
// z[n] = saturated( y[n] - x[n] ) // 0 <= n < len
// z, y, x buf size must be(32bit x n), z_buf can be y_buf or x_buf
//=========================================================================
__attribute__((always_inline)) inline
void vector_real_sub(void *zptr, void *yptr, void *xptr, short len, long config)
{
config = config | VEC_SUB | VEC_CPY_REAL_OR_VEC;
hwvec_exec(xptr, yptr, zptr, 0, 0, 0, len, 1, 0, config, 0);
}
//=========================================================================
// vector_real_mul
// dw bit[1:0] : x_dw 2: s32 1: s16 0:s8
// dw bit[3:2] : y_dw 2: s32 1: s16 0:s8
// dw bit[5:6] : z_dw 2: s32 1: s16 0:s8
// y_dw >= z_dw > x_dw
// -32 < Q < 32
// *zptr, *yptr, *xptr: s32/s16/s8
// z[n] = saturated(y[n] * x[n] / 2^q) // 0 <= n < len
// z, y, x buf size must be(32bit x n), z_buf can be y_buf or x_buf
//=========================================================================
__attribute__((always_inline)) inline
void vector_real_mul(void *zptr, void *yptr, void *xptr, short len, char q, long config)
{
config = config | VEC_REAL_MUL_MODE | VEC_CPY_REAL_OR_VEC;
hwvec_exec(xptr, yptr, zptr, 0, 0, 0, len, 1, q, config, 0);
}
//=========================================================================
// vector_real_mac
// dw bit[1:0] : x_dw 2: s32
// dw bit[5:6] : z_dw 2: s32
// -32 < Q < 32
// *zptr, *yptr, *xptr: s32/s16/s8
// z[n] = (z + y*x / 2^q) // 0 <= n < len
// z, y, x buf size must be(32bit x n), z_buf can be y_buf or x_buf
//=========================================================================
__attribute__((always_inline)) inline
void vector_real_mac32(void *zptr, void *yptr, void *xptr, short len, char q, long config)
{
config = config | VEC_MAC32 | VECZ_S32 | VECY_S32 | VECX_S32 | VEC_REAL_MUL_MODE | VEC_CPY_REAL_OR_VEC;
hwvec_exec(xptr, yptr, zptr, 0, 0, 0, len, 1, q, config, 0);
}
//=========================================================================
// vector_real_msc
// dw bit[1:0] : x_dw 2: s32
// dw bit[5:6] : z_dw 2: s32
// -32 < Q < 32
// *zptr, *yptr, *xptr: s32/s16/s8
// z[n] = (z - y*x / 2^q) // 0 <= n < len
// z, y, x buf size must be(32bit x n), z_buf can be y_buf or x_buf
//=========================================================================
__attribute__((always_inline)) inline
void vector_real_msc32(void *zptr, void *yptr, void *xptr, short len, char q, long config)
{
config = config | VEC_MAC32 | VECZ_S32 | VECY_S32 | VECX_S32 | VEC_SUB | VEC_REAL_MUL_MODE | VEC_CPY_REAL_OR_VEC;
hwvec_exec(xptr, yptr, zptr, 0, 0, 0, len, 1, q, config, 0);
}
//=========================================================================
// vector_real_dot_product
// dw bit[1:0] : x_dw 2: s32 1: s16 0:s8
// dw bit[3:2] : y_dw 2: s32 1: s16 0:s8
// dw bit[5:6] : z_dw 2: s32 1: s16 0:s8
// y_dw >= z_dw > x_dw
// -32 < Q < 32
// *zptr, *yptr, *xptr: s32/s16/s8
// z[n] = sum(y[n] * x[n] / 2^q) // 0 <= n < len
// z, y, x buf size must be(32bit x n), z_buf can be y_buf or x_buf
//=========================================================================
__attribute__((always_inline)) inline
void vector_real_dot_product(void *zptr, void *yptr, void *xptr, short len, char q, long config)
{
config = config | VEC_ACC | VEC_REAL_MUL_MODE | VEC_CPY_REAL_OR_VEC | VEC_ZPTR_CPY_DOT;
hwvec_exec(xptr, yptr, zptr, 0, 0, 0, len, 1, q, config, 0);
}
//=========================================================================
// vector_real_sum
// dw bit[1:0] : x_dw 2: s32 1: s16 0:s8
// dw bit[5:6] : z_dw 2: s32 1: s16 0:s8
// z_dw >= x_dw
// -32 < Q < 32
// *zptr, *xptr: s32/s16/s8
// z[n] = sum(x[n]) / 2^q // 0 <= n < len
// z, y, x buf size must be(32bit x n), z_buf can be y_buf or x_buf
//=========================================================================
__attribute__((always_inline)) inline
void vector_real_sum(void *zptr, void *xptr, short len, char q, long config)
{
config = config | VEC_ACC | VEC_QDT_MODE | VEC_CPY_REAL_OR_VEC | VEC_YPTR_NOCPY;
hwvec_exec(xptr, 0, zptr, 0, 0, 0, len, 1, q, config, 0);
}
//=========================================================================
// vector_real_sum_dot_product
// dw bit[1:0] : x_dw 2: s32 1: s16 0:s8
// dw bit[5:6] : z_dw 2: s32 1: s16 0:s8
// z_dw >= x_dw
// -32 < Q < 32
// *zptr, *xptr: s32/s16/s8
// z = sum(x[n]) / 2^q // 0 <= n < len
// z, y, x buf size must be(32bit x n), z_buf can be y_buf or x_buf
//=========================================================================
__attribute__((always_inline)) inline
void vector_real_sum_dot_product(void *zptr, void *xptr, short len, char q, long config)
{
config = config | VEC_ACC | VEC_QDT_MODE | VEC_CPY_REAL_OR_VEC | VEC_YPTR_NOCPY | VEC_ZPTR_CPY_DOT;
hwvec_exec(xptr, 0, zptr, 0, 0, 0, len, 1, q, config, 0);
}
//=========================================================================
// vector_real_qdt
// dw bit[1:0] : x_dw 2: s32 1: s16 0:s8
// dw bit[5:6] : z_dw 2: s32 1: s16 0:s8
// z_dw >= x_dw
// -32 < Q < 32
// *zptr, *xptr: s32/s16/s8
// z[n] = x[n]^2 / 2^q // 0 <= n < len
// z, y, x buf size must be(32bit x n), z_buf can be y_buf or x_buf
//=========================================================================
__attribute__((always_inline)) inline
void vector_real_qdt(void *zptr, void *xptr, short len, char q, long config)
{
config = config | VEC_QDT | VEC_QDT_MODE | VEC_CPY_REAL_OR_VEC;
hwvec_exec(xptr, 0, zptr, 0, 0, 0, len, 1, q, config, 0);
}
//=========================================================================
// vector_real_qdtsum
// dw bit[1:0] : x_dw 2: s32 1: s16 0:s8
// dw bit[5:6] : z_dw 2: s32 1: s16
// -32 < Q < 32
// *zptr, *yptr, *xptr: s32/s16/s8
// z[n] = sum(x[n]^2) / 2^q // 0 <= n < len
// z, y, x buf size must be(32bit x n), z_buf can be y_buf or x_buf
//=========================================================================
__attribute__((always_inline)) inline
void vector_real_qdtsum(void *zptr, void *xptr, short len, char q, long config)
{
config = config | VEC_QDT | VEC_ACC | VEC_QDT_MODE | VEC_CPY_REAL_OR_VEC;
hwvec_exec(xptr, 0, zptr, 0, 0, 0, len, 1, q, config, 0);
}
//=========================================================================
// vector_real_mac_const
// dw bit[1:0] : x_dw 2: s32 1: s16 0:s8
// dw bit[5:6] : z_dw 2: s32
// -32 < Q < 32
// *zptr, *yptr, *xptr: s32/s16/s8
// z[n] = x[n] + y[n] * const_dat / 2^q // 0 <= n < len
// z, y, x buf size must be(32bit x n), z_buf can be y_buf or x_buf
//=========================================================================
__attribute__((always_inline)) inline
void vector_real_mac_const(void *zptr, void *yptr, void *xptr, short len, char q, long const_dat, long config)
{
config = config | VEC_CONST_MUL | VEC_REAL_MUL_MODE | VEC_CPY_REAL_OR_VEC;
hwvec_exec(xptr, yptr, zptr, 0, 0, 0, len, 1, q, config, const_dat);
}
//=========================================================================
// vector_real_msc_const
// dw bit[1:0] : x_dw 2: s32 1: s16 0:s8
// dw bit[5:6] : z_dw 2: s32
// -32 < Q < 32
// *zptr, *yptr, *xptr: s32/s16/s8
// z[n] = x[n] - y[n] * const_dat / 2^q // 0 <= n < len
// z, y, x buf size must be(32bit x n), z_buf can be y_buf or x_buf
//=========================================================================
__attribute__((always_inline)) inline
void vector_real_msc_const(void *zptr, void *yptr, void *xptr, short len, char q, long const_dat, long config)
{
config = config | VEC_CONST_MUL | VEC_SUB | VEC_REAL_MUL_MODE | VEC_CPY_REAL_OR_VEC;
hwvec_exec(xptr, yptr, zptr, 0, 0, 0, len, 1, q, config, const_dat);
}
//=========================================================================
// vector_real_mul_const
// dw bit[1:0] : x_dw 2: s32 1: s16 0:s8
// dw bit[5:6] : z_dw 2: s32
// -32 < Q < 32
// *zptr, *yptr, *xptr: s32/s16/s8
// z[n] = (x[n] * const_dat/ 2^q) // 0 <= n < len
// z, y, x buf size must be(32bit x n), z_buf can be y_buf or x_buf
//=========================================================================
__attribute__((always_inline)) inline
void vector_real_mul_const(void *zptr, void *xptr, short len, char q, long const_dat, long config)
{
config = config | VEC_CONST_MUL | VEC_QDT | VEC_QDT_MODE | VEC_YPTR_NOCPY | VEC_CPY_REAL_OR_VEC;
hwvec_exec(xptr, 0, zptr, 0, 0, 0, len, 1, q, config, const_dat);
}
//=========================================================================
// vector_real_max
// dw bit[1:0] : x_dw 2: s32 1: s16 0:s8
// dw bit[5:6] : z_dw 2: s32
// -32 < Q < 32
// z = x*cosnt /2^q
//=========================================================================
__attribute__((always_inline)) inline
void vector_real_max(void *zptr, void *xptr, short len, char q, long config, long const_dat)
{
config = config | VEC_MAX | VEC_CONST_MUL | VEC_QDT | VEC_QDT_MODE | VEC_YPTR_NOCPY | VEC_CPY_REAL_OR_VEC;
hwvec_exec(xptr, 0, zptr, 0, 0, 0, len, 1, q, config, const_dat);
}
//=========================================================================
// vector_real_min
// dw bit[1:0] : x_dw 2: s32 1: s16 0:s8
// dw bit[5:6] : z_dw 2: s32
// -32 < Q < 32
// z = x*cosnt /2^q
//=========================================================================
__attribute__((always_inline)) inline
void vector_real_min(void *zptr, void *xptr, short len, char q, long config, long const_dat)
{
config = config | VEC_MIN | VEC_CONST_MUL | VEC_QDT | VEC_QDT_MODE | VEC_YPTR_NOCPY | VEC_CPY_REAL_OR_VEC;
hwvec_exec(xptr, 0, zptr, 0, 0, 0, len, 1, q, config, const_dat);
}
#endif
#if defined CONFIG_FPGA_TEST_ENABLE && !defined CONFIG_VIDEO_ENABLE
#include "os/os_api.h"
#include "init.h"
void REAL_FFT_FUN(int *data, int blockbit, int *oudata)
{
vc_hw_fft(data, blockbit, oudata, 1, data == oudata ? 1 : 0);
}
void REAL_IFFT_FUN(int *data, int blockbit, int *oudata)
{
vc_hw_ifft(data, blockbit, oudata, 1, data == oudata ? 1 : 0);
}
void COMPLEX_FFT_FUN(int *data, int blockbit, int *oudata)
{
vc_hw_fft(data, blockbit, oudata, 0, data == oudata ? 1 : 0);
}
void COMPLEX_IFFT_FUN(int *data, int blockbit, int *oudata)
{
vc_hw_ifft(data, blockbit, oudata, 0, data == oudata ? 1 : 0);
}
static const int real_fft_test_input_data_512[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 20, -83, 58, -40, 140, -161, 110, -102, 80, -17, 41, -101, 26, 35, -54, -28, 180, -49, -180, 87, 70, 34, -222, 272, -129, 2, 44, 86, -186, 84, 32, -99, 126, -90, 44, -44, 94, -167, 55, 42, 1, -55, 65, -15, -79, 156, -64, -29, 9, 99, -125, -10, 133, -88, -6, 0, 5, 38, -65, 25, -64, 104, -79, -10, 28, -50, 105, -89, 92, -125, 159, -143, 27, 41, -25, 56, -135, 134, -108, 87, -26, 0, -35, 62, 18, -83, 41, 42, -66, -1, 69, -54, -14, 26, 48, -64, 5, 38, -4, -44, 74, -59, 10, 24, 1, -40, 23, 31, -81, 58, -2, -10, 0, 26, -44, 2, 25, -1, -30, 37, -27, 0, 5, 8, -13, -13, 37, -25, 13, -10, 23, -30, 22, -1, -10, 2, 4, -2, -3, 11, -10, 0, 4, 3, -10, 9, -2, -2, -2, 4, -1, -2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
static const int real_fft_test_output_data_real_512[] = {
16, -15, 15, -17, 26, -39, 50, -51, 32, 7, -43, 45, -16, -17, 23, -17, 24, -44, 49, -24, -13, 45, -66, 89, -108, 116, -105, 84, -62, 32, 12, -50, 47, 1, -49, 49, -6, -43, 65, -66, 56, -32, -7, 39, -47, 36, -19, -2, 31, -63, 85, -93, 108, -133, 143, -118, 84, -87, 144, -208, 224, -189, 147, -128, 120, -96, 57, -37, 61, -110, 128, -80, -11, 75, -78, 48, -28, 3, 71, -191, 288, -305, 258, -221, 246, -327, 414, -452, 431, -398, 392, -369, 263, -116, 66, -174, 336, -418, 401, -357, 321, -271, 216, -212, 277, -323, 242, -45, -122, 116, 52, -226, 269, -148, -72, 294, -446, 496, -449, 285, 6, -372, 672, -793, 715, -487, 226, -92, 164, -326, 374, -266, 153, -156, 263, -421, 568, -591, 393, -52, -214, 290, -257, 287, -498, 837, -1075, 991, -594, 77, 383, -612, 327, 521, -1311, 1229, -380, -106, -581, 1888, -2622, 2366, -1699, 1257, -1084, 895, -529, 57, 313, -397, 220, -37, 51, -157, 113, 89, -177, -41, 439, -717, 718, -534, 347, -270, 308, -409, 498, -498, 373, -180, 32, 4, 38, -58, 14, 48, -84, 109, -155, 233, -351, 532, -725, 773, -562, 194, 76, -64, -199, 484, -517, 207, 197, -297, -22, 465, -727, 837, -953, 932, -417, -602, 1538, -1694, 934, 243, -1241, 1793, -1868, 1439, -612, -169, 432, -182, -193, 514, -872, 1058, -524, -755, 1863, -1893, 1041, -279, 131, -279, 279, -114, -20, 88, -168, 270, -355, 420, -474, 507, -516
};
static const int real_fft_test_output_data_img_512[] = {
0, -5, 14, -22, 29, -28, 16, 9, -34, 43, -20, -21, 43, -30, 3, 9, -11, 30, -72, 111, -127, 123, -115, 104, -81, 46, -12, -11, 29, -44, 44, -10, -43, 70, -40, -19, 53, -42, 11, 18, -44, 66, -68, 41, -3, -31, 52, -72, 86, -85, 73, -67, 68, -59, 29, -5, 23, -75, 105, -72, 3, 49, -60, 55, -65, 83, -80, 49, -17, 34, -102, 172, -181, 123, -49, 3, 29, -85, 150, -164, 99, -11, -22, -23, 100, -146, 128, -66, 22, -23, 28, 6, -32, -55, 252, -417, 433, -339, 248, -200, 166, -132, 130, -154, 123, 18, -207, 293, -212, 59, -11, 151, -404, 636, -750, 718, -573, 374, -153, -62, 203, -174, -50, 381, -688, 861, -833, 633, -438, 418, -536, 604, -526, 389, -308, 327, -484, 777, -1067, 1169, -1061, 910, -887, 1009, -1137, 1074, -736, 284, 1, 27, -367, 1010, -1776, 2123, -1622, 733, -531, 1372, -2304, 2202, -1105, -10, 489, -525, 579, -784, 973, -952, 668, -273, 34, -63, 176, -141, 3, -26, 293, -573, 585, -306, -39, 235, -241, 150, -69, 68, -167, 332, -477, 507, -413, 285, -227, 248, -278, 269, -248, 255, -284, 318, -348, 331, -176, -119, 383, -395, 116, 268, -497, 427, -154, -8, -217, 741, -1159, 1200, -996, 784, -512, -6, 604, -725, 8, 1224, -2201, 2400, -1873, 961, 80, -1027, 1537, -1407, 919, -605, 653, -883, 1299, -2131, 3144, -3489, 2686, -1398, 712, -893, 1285, -1333, 1126, -971, 908, -817, 681, -553, 442, -328, 215, -108, 0
};
static const int complex_fft_test_output_data_256[] = {
65280, 65536, -21115, 20602, -10685, 10172, -7207, 6694, -5467, 4955, -4423, 3912, -3727, 3214, -3229, 2716, -2855, 2343, -2564, 2053, -2332, 1820, -2142, 1629, -1982, 1470, -1847, 1335, -1731, 1220, -1631, 1119, -1543, 1031, -1465, 953, -1396, 884, -1334, 822, -1278, 766, -1227, 716, -1181, 669, -1139, 627, -1100, 588, -1064, 552, -1030, 519, -1000, 488, -972, 459, -944, 432, -919, 407, -896, 384, -874, 362, -853, 341, -833, 322, -814, 303, -797, 286, -781, 268, -764, 252, -749, 237, -735, 223, -721, 209, -708, 196, -695, 183, -683, 171, -671, 160, -660, 149, -650, 138, -639, 127, -629, 117, -620, 107, -610, 98, -601, 89, -593, 81, -584, 72, -576, 64, -568, 56, -560, 48, -553, 41, -546, 33, -539, 27, -532, 20, -525, 13, -518, 6, -512, 0, -506, -6, -500, -13, -494, -18, -488, -24, -482, -30, -477, -35, -471, -41, -466, -46, -461, -51, -456, -56, -451, -61, -446, -66, -441, -71, -436, -76, -432, -80, -427, -85, -423, -90, -418, -94, -414, -98, -410, -103, -405, -107, -401, -111, -397, -115, -393, -119, -389, -123, -385, -127, -381, -131, -377, -135, -373, -139, -370, -143, -366, -146, -362, -150, -358, -154, -355, -157, -351, -161, -348, -164, -344, -168, -340, -171, -337, -175, -334, -178, -331, -182, -327, -185, -324, -189, -320, -192, -317, -195, -313, -199, -310, -202, -307, -205, -304, -208, -301, -212, -297, -215, -294, -218, -291, -221, -288, -224, -284, -228, -281, -231, -278, -234, -275, -237, -272, -241, -269, -243, -265, -247, -262, -250, -259, -253, -256, -256, -253, -259, -250, -262, -247, -265, -243, -269, -241, -272, -237, -275, -234, -278, -231, -281, -228, -284, -224, -288, -221, -291, -218, -294, -215, -297, -212, -301, -208, -304, -205, -307, -202, -310, -199, -313, -195, -317, -192, -320, -189, -324, -185, -327, -182, -331, -178, -334, -175, -337, -171, -340, -168, -344, -164, -348, -161, -351, -157, -355, -154, -358, -150, -362, -146, -366, -143, -370, -139, -373, -135, -377, -131, -381, -127, -385, -123, -389, -119, -393, -115, -397, -111, -401, -107, -405, -103, -410, -98, -414, -94, -418, -90, -423, -85, -427, -80, -432, -76, -436, -71, -441, -66, -446, -61, -451, -56, -456, -51, -461, -46, -466, -41, -471, -35, -477, -30, -482, -24, -488, -18, -494, -13, -500, -6, -506, 0, -512, 6, -518, 13, -525, 20, -532, 27, -539, 33, -546, 41, -553, 48, -560, 56, -568, 64, -576, 72, -584, 81, -593, 89, -601, 98, -610, 107, -620, 117, -629, 127, -639, 138, -650, 149, -660, 160, -671, 171, -683, 183, -695, 196, -708, 209, -721, 223, -735, 237, -749, 252, -764, 268, -781, 286, -797, 303, -814, 322, -833, 341, -853, 362, -874, 384, -896, 407, -919, 432, -944, 459, -972, 488, -1000, 519, -1030, 552, -1064, 588, -1100, 627, -1139, 669, -1181, 716, -1227, 766, -1278, 822, -1334, 884, -1396, 953, -1465, 1031, -1543, 1119, -1631, 1220, -1731, 1335, -1847, 1470, -1982, 1629, -2142, 1820, -2332, 2053, -2564, 2343, -2855, 2716, -3229, 3214, -3727, 3912, -4423, 4955, -5467, 6694, -7207, 10172, -10685, 20602, -21115
};
static const int complex_fft_test_output_data_512[] = {
261632, 262144, -83954, 82931, -42230, 41204, -28325, 27297, -21369, 20345, -17196, 16168, -14414, 13386, -12426, 11398, -10934, 9909, -9773, 8752, -8844, 7823, -8084, 7063, -7453, 6429, -6917, 5894, -6457, 5433, -6058, 5036, -5711, 4686, -5402, 4379, -5128, 4105, -4883, 3861, -4663, 3638, -4463, 3438, -4283, 3257, -4117, 3090, -3964, 2939, -3824, 2799, -3694, 2670, -3575, 2551, -3463, 2438, -3358, 2335, -3262, 2238, -3172, 2148, -3086, 2062, -3007, 1983, -2931, 1907, -2859, 1835, -2792, 1769, -2729, 1704, -2668, 1644, -2610, 1587, -2556, 1533, -2503, 1481, -2454, 1431, -2406, 1384, -2362, 1338, -2319, 1294, -2277, 1254, -2238, 1214, -2200, 1176, -2163, 1139, -2128, 1104, -2095, 1070, -2062, 1038, -2030, 1006, -2001, 976, -1971, 947, -1943, 919, -1915, 892, -1890, 866, -1864, 840, -1839, 815, -1815, 792, -1792, 769, -1770, 746, -1748, 724, -1727, 703, -1706, 682, -1687, 662, -1667, 643, -1648, 624, -1630, 606, -1612, 588, -1594, 571, -1578, 554, -1561, 537, -1545, 521, -1529, 505, -1514, 490, -1499, 475, -1484, 461, -1470, 446, -1456, 432, -1442, 419, -1429, 405, -1416, 391, -1403, 378, -1391, 366, -1378, 354, -1366, 342, -1355, 330, -1343, 319, -1332, 308, -1321, 296, -1310, 286, -1299, 275, -1289, 265, -1278, 254, -1269, 244, -1259, 234, -1248, 225, -1239, 215, -1230, 206, -1220, 196, -1211, 188, -1202, 178, -1193, 170, -1185, 161, -1176, 153, -1168, 144, -1160, 136, -1152, 128, -1144, 120, -1136, 112, -1128, 104, -1121, 96, -1113, 89, -1105, 82, -1099, 74, -1091, 67, -1084, 60, -1077, 53, -1070, 46, -1063, 39, -1057, 33, -1050, 26, -1043, 19, -1037, 13, -1030, 6, -1024, 0, -1018, -6, -1012, -12, -1006, -19, -1000, -25, -994, -31, -988, -36, -982, -43, -976, -48, -970, -54, -965, -59, -959, -65, -954, -70, -948, -76, -943, -81, -938, -87, -932, -92, -927, -97, -922, -102, -917, -107, -912, -113, -906, -118, -901, -123, -897, -128, -892, -132, -887, -138, -882, -142, -878, -147, -873, -151, -868, -156, -864, -161, -859, -165, -854, -170, -850, -175, -845, -179, -841, -183, -836, -188, -832, -192, -827, -197, -823, -201, -819, -205, -815, -209, -811, -213, -806, -218, -802, -222, -798, -226, -794, -230, -790, -234, -786, -238, -782, -243, -778, -246, -774, -251, -770, -254, -766, -258, -762, -262, -758, -266, -754, -270, -750, -274, -747, -278, -743, -281, -739, -285, -735, -289, -731, -293, -728, -296, -724, -300, -720, -304, -717, -307, -713, -311, -709, -315, -706, -318, -702, -322, -699, -325, -695, -329, -692, -332, -688, -336, -685, -339, -681, -343, -678, -346, -674, -350, -671, -353, -667, -357, -664, -360, -660, -364, -657, -367, -654, -370, -650, -374, -647, -377, -643, -381, -640, -384, -637, -387, -634, -390, -630, -394, -627, -397, -624, -400, -621, -404, -617, -407, -614, -410, -611, -414, -607, -417, -604, -420, -601, -423, -598, -427, -594, -430, -591, -433, -588, -436, -585, -439, -582, -442, -578, -445, -575, -449, -572, -452, -569, -455, -566, -458, -562, -462, -559, -465, -556, -468, -553, -471, -550, -474, -547, -478, -543, -481, -540, -484, -537, -487, -534, -490, -531, -493, -528, -496, -525, -499, -521, -503, -518, -506, -515, -509, -512, -512, -509, -515, -506, -518, -503, -521, -499, -525, -496, -528, -493, -531, -490, -534, -487, -537, -484, -540, -481, -543, -478, -547, -474, -550, -471, -553, -468, -556, -465, -559, -462, -562, -458, -566, -455, -569, -452, -572, -449, -575, -445, -578, -442, -582, -439, -585, -436, -588, -433, -591, -430, -594, -427, -598, -423, -601, -420, -604, -417, -607, -414, -611, -410, -614, -407, -617, -404, -621, -400, -624, -397, -627, -394, -630, -390, -634, -387, -637, -384, -640, -381, -643, -377, -647, -374, -650, -370, -654, -367, -657, -364, -660, -360, -664, -357, -667, -353, -671, -350, -674, -346, -678, -343, -681, -339, -685, -336, -688, -332, -692, -329, -695, -325, -699, -322, -702, -318, -706, -315, -709, -311, -713, -307, -717, -304, -720, -300, -724, -296, -728, -293, -731, -289, -735, -285, -739, -281, -743, -278, -747, -274, -750, -270, -754, -266, -758, -262, -762, -258, -766, -254, -770, -251, -774, -246, -778, -243, -782, -238, -786, -234, -790, -230, -794, -226, -798, -222, -802, -218, -806, -213, -811, -209, -815, -205, -819, -201, -823, -197, -827, -192, -832, -188, -836, -183, -841, -179, -845, -175, -850, -170, -854, -165, -859, -161, -864, -156, -868, -151, -873, -147, -878, -142, -882, -138, -887, -132, -892, -128, -897, -123, -901, -118, -906, -113, -912, -107, -917, -102, -922, -97, -927, -92, -932, -87, -938, -81, -943, -76, -948, -70, -954, -65, -959, -59, -965, -54, -970, -48, -976, -43, -982, -36, -988, -31, -994, -25, -1000, -19, -1006, -12, -1012, -6, -1018, 0, -1024, 6, -1030, 13, -1037, 19, -1043, 26, -1050, 33, -1057, 39, -1063, 46, -1070, 53, -1077, 60, -1084, 67, -1091, 74, -1099, 82, -1105, 89, -1113, 96, -1121, 104, -1128, 112, -1136, 120, -1144, 128, -1152, 136, -1160, 144, -1168, 153, -1176, 161, -1185, 170, -1193, 178, -1202, 188, -1211, 196, -1220, 206, -1230, 215, -1239, 225, -1248, 234, -1259, 244, -1269, 254, -1278, 265, -1289, 275, -1299, 286, -1310, 296, -1321, 308, -1332, 319, -1343, 330, -1355, 342, -1366, 354, -1378, 366, -1391, 378, -1403, 391, -1416, 405, -1429, 419, -1442, 432, -1456, 446, -1470, 461, -1484, 475, -1499, 490, -1514, 505, -1529, 521, -1545, 537, -1561, 554, -1578, 571, -1594, 588, -1612, 606, -1630, 624, -1648, 643, -1667, 662, -1687, 682, -1706, 703, -1727, 724, -1748, 746, -1770, 769, -1792, 792, -1815, 815, -1839, 840, -1864, 866, -1890, 892, -1915, 919, -1943, 947, -1971, 976, -2001, 1006, -2030, 1038, -2062, 1070, -2095, 1104, -2128, 1139, -2163, 1176, -2200, 1214, -2238, 1254, -2277, 1294, -2319, 1338, -2362, 1384, -2406, 1431, -2454, 1481, -2503, 1533, -2556, 1587, -2610, 1644, -2668, 1704, -2729, 1769, -2792, 1835, -2859, 1907, -2931, 1983, -3007, 2062, -3086, 2148, -3172, 2238, -3262, 2335, -3358, 2438, -3463, 2551, -3575, 2670, -3694, 2799, -3824, 2939, -3964, 3090, -4117, 3257, -4283, 3438, -4463, 3638, -4663, 3861, -4883, 4105, -5128, 4379, -5402, 4686, -5711, 5036, -6058, 5433, -6457, 5894, -6917, 6429, -7453, 7063, -8084, 7823, -8844, 8752, -9773, 9909, -10934, 11398, -12426, 13386, -14414, 16168, -17196, 20345, -21369, 27297, -28325, 41204, -42230, 82931, -83954
};
static const int real_fft_test_output_data_1024[] = {
523776, 0, -511, 166887, -514, 83437, -515, 55627, -512, 41720, -516, 33372, -515, 27809, -515, 23835, -512, 20855, -510, 18539, -509, 16683, -509, 15164, -513, 13901, -511, 12831, -512, 11912, -511, 11117, -512, 10422, -511, 9808, -512, 9261, -511, 8774, -513, 8333, -514, 7934, -514, 7575, -514, 7243, -513, 6941, -513, 6662, -512, 6405, -512, 6168, -513, 5945, -512, 5739, -512, 5547, -512, 5369, -512, 5198, -512, 5042, -512, 4891, -512, 4749, -511, 4617, -513, 4491, -512, 4372, -512, 4259, -511, 4151, -511, 4048, -511, 3952, -511, 3857, -511, 3769, -513, 3685, -512, 3603, -512, 3526, -512, 3452, -512, 3380, -512, 3311, -513, 3246, -512, 3182, -512, 3120, -513, 3063, -512, 3006, -512, 2950, -512, 2897, -512, 2847, -512, 2797, -512, 2750, -511, 2704, -512, 2659, -512, 2616, -512, 2574, -512, 2533, -512, 2494, -512, 2456, -512, 2419, -512, 2382, -512, 2348, -512, 2313, -512, 2280, -512, 2248, -511, 2216, -511, 2186, -512, 2156, -512, 2127, -512, 2098, -512, 2071, -512, 2044, -512, 2017, -512, 1993, -512, 1967, -512, 1942, -513, 1918, -513, 1895, -513, 1872, -512, 1850, -512, 1828, -512, 1807, -512, 1786, -513, 1765, -512, 1745, -512, 1726, -512, 1708, -512, 1688, -512, 1670, -512, 1652, -512, 1633, -512, 1616, -512, 1599, -512, 1582, -511, 1566, -512, 1550, -511, 1534, -512, 1518, -511, 1503, -512, 1489, -512, 1474, -512, 1459, -512, 1445, -512, 1431, -512, 1417, -512, 1404, -512, 1390, -512, 1377, -512, 1365, -513, 1351, -512, 1340, -512, 1327, -511, 1315, -512, 1303, -512, 1292, -512, 1281, -512, 1269, -512, 1258, -512, 1247, -512, 1236, -512, 1225, -512, 1215, -512, 1205, -512, 1195, -512, 1184, -512, 1174, -512, 1164, -512, 1155, -512, 1146, -511, 1136, -512, 1127, -512, 1118, -512, 1109, -512, 1100, -512, 1091, -512, 1083, -512, 1074, -512, 1066, -512, 1058, -512, 1049, -512, 1040, -512, 1033, -512, 1025, -512, 1017, -512, 1009, -512, 1002, -512, 994, -512, 987, -512, 979, -512, 973, -512, 965, -512, 958, -512, 951, -512, 944, -512, 937, -512, 930, -512, 923, -512, 917, -512, 911, -512, 904, -512, 897, -512, 891, -512, 885, -512, 878, -512, 872, -512, 866, -512, 860, -512, 854, -512, 848, -512, 842, -512, 837, -512, 831, -512, 825, -512, 819, -512, 814, -512, 808, -512, 803, -512, 798, -512, 792, -512, 787, -512, 782, -512, 776, -512, 771, -512, 766, -512, 761, -512, 756, -512, 751, -512, 746, -512, 741, -512, 737, -512, 732, -512, 727, -512, 722, -512, 718, -512, 713, -512, 708, -512, 704, -512, 699, -512, 695, -512, 690, -512, 686, -512, 681, -512, 677, -512, 673, -512, 668, -512, 664, -512, 660, -512, 656, -512, 652, -512, 648, -512, 644, -512, 640, -512, 636, -512, 632, -512, 628, -512, 624, -512, 620, -512, 616, -512, 612, -512, 608, -512, 605, -512, 601, -512, 597, -512, 594, -512, 590, -512, 586, -512, 583, -512, 579, -512, 575, -512, 572, -512, 568, -512, 565, -512, 561, -512, 558, -512, 555, -512, 551, -512, 548, -512, 544, -512, 541, -512, 538, -512, 534, -512, 531, -512, 528, -512, 525, -512, 522, -512, 518, -512, 515, -512, 512, -512, 509, -512, 506, -512, 503, -512, 500, -512, 496, -512, 493, -512, 490, -512, 487, -512, 485, -512, 482, -512, 479, -512, 476, -512, 473, -512, 470, -512, 467, -512, 464, -512, 461, -512, 458, -512, 456, -512, 453, -512, 450, -512, 447, -512, 444, -512, 442, -512, 439, -512, 436, -512, 434, -512, 431, -512, 428, -512, 426, -512, 423, -512, 420, -512, 418, -512, 415, -512, 412, -512, 410, -512, 407, -512, 405, -512, 402, -512, 400, -512, 397, -512, 395, -512, 392, -512, 390, -512, 387, -512, 385, -512, 382, -512, 380, -512, 377, -512, 375, -512, 372, -512, 370, -512, 368, -512, 365, -512, 363, -512, 361, -512, 358, -512, 356, -512, 354, -512, 351, -512, 349, -512, 347, -512, 344, -512, 342, -512, 340, -512, 338, -512, 335, -512, 333, -512, 331, -512, 329, -512, 326, -512, 324, -512, 322, -512, 320, -512, 318, -512, 316, -512, 313, -512, 311, -512, 309, -512, 307, -512, 305, -512, 303, -512, 301, -512, 298, -512, 296, -512, 294, -512, 292, -512, 290, -512, 288, -512, 286, -512, 284, -512, 282, -512, 280, -512, 278, -512, 276, -512, 274, -512, 272, -512, 270, -512, 268, -512, 266, -512, 264, -512, 262, -512, 260, -512, 258, -512, 256, -512, 254, -512, 252, -512, 250, -512, 248, -512, 246, -512, 244, -512, 242, -512, 240, -512, 238, -512, 236, -512, 235, -512, 233, -512, 230, -512, 229, -512, 227, -512, 225, -512, 223, -512, 221, -512, 220, -512, 218, -512, 216, -512, 214, -512, 212, -512, 210, -512, 208, -512, 207, -512, 205, -512, 203, -512, 201, -512, 199, -512, 198, -512, 196, -512, 194, -512, 192, -512, 190, -512, 189, -512, 187, -512, 185, -512, 183, -512, 182, -512, 180, -512, 178, -512, 176, -512, 174, -512, 173, -512, 171, -512, 169, -512, 167, -512, 166, -512, 164, -512, 162, -512, 160, -512, 159, -512, 157, -512, 155, -512, 154, -512, 152, -512, 150, -512, 149, -512, 147, -512, 145, -512, 143, -512, 142, -512, 140, -512, 139, -512, 137, -512, 135, -512, 133, -512, 132, -512, 130, -512, 128, -512, 127, -512, 125, -512, 123, -512, 122, -512, 120, -512, 118, -512, 117, -512, 115, -512, 113, -512, 112, -512, 110, -512, 108, -512, 107, -512, 105, -512, 104, -512, 102, -512, 100, -512, 99, -512, 97, -512, 95, -512, 94, -512, 92, -512, 90, -512, 89, -512, 87, -512, 86, -512, 84, -512, 82, -512, 81, -512, 79, -512, 78, -512, 76, -512, 74, -512, 73, -512, 71, -512, 70, -512, 68, -512, 66, -512, 65, -512, 63, -512, 62, -512, 60, -512, 58, -512, 57, -512, 55, -512, 54, -512, 52, -512, 50, -512, 49, -512, 47, -512, 46, -512, 44, -512, 43, -512, 41, -512, 39, -512, 38, -512, 36, -512, 35, -512, 33, -512, 32, -512, 30, -512, 28, -512, 27, -512, 25, -512, 24, -512, 22, -512, 20, -512, 19, -512, 17, -512, 16, -512, 14, -512, 13, -512, 11, -512, 9, -512, 8, -512, 6, -512, 5, -512, 3, -512, 2, -512, 0
};
SEC_USED(.fft_data) static int test_datain[4096];
SEC_USED(.fft_data) static int test_dataout[4096];
SEC_USED(.fft_data) static fft_config_struct test_fft_config;
___interrupt
static void fft_isr(void)
{
if (JL_FFT->CON & BIT(7)) {
}
}
static void hw_fft_test(void)
{
#if 0
REAL_FFT_FUN(datain, 7, datain); //输入数据为128个实数,放在datain,输出数据是65个复数,排布为实部,虚部,实部,虚部。。。
puts("REAL_FFT_FUN RES:\n");
for (int i = 0; i < sizeof(datain) / sizeof(datain[0]); i++) {
printf("%d, ", datain[i]);
}
REAL_IFFT_FUN(datain, 7, dataout); //反变换,得到128个实数
puts("REAL_IFFT_FUN RES:\n");
for (int i = 0; i < sizeof(dataout) / sizeof(dataout[0]); i++) {
printf("%d, ", dataout[i]);
}
COMPLEX_FFT_FUN(datain, 6, datain); //输入数据为64个复数,放在datain,输出数据是64个复数,排布为实部,虚部,实部,虚部。。。
puts("COMPLEX_FFT_FUN RES:\n");
for (int i = 0; i < sizeof(datain) / sizeof(datain[0]); i++) {
printf("%d, ", datain[i]);
}
COMPLEX_IFFT_FUN(datain, 6, dataout); //反变换,得到64个复数
puts("COMPLEX_IFFT_FUN RES:\n");
for (int i = 0; i < sizeof(dataout) / sizeof(dataout[0]); i++) {
printf("%d, ", dataout[i]);
}
#endif
/* request_irq(IRQ_FFT_IDX, 0, fft_isr, 0); */
static u8 fft_test_cnt = 0;
int *out_ptr = NULL;
if (fft_test_cnt++ % 2) {
out_ptr = test_datain;
} else {
out_ptr = test_dataout;
}
if (fft_test_cnt == 64) {
fft_test_cnt = 0;
}
hwfft_fill_fft_ctx((hwfft_ctx_t *)&test_fft_config, REAL_FFT512_CONFIG, (long *)test_datain, (long *)out_ptr);
for (int i = 0; i < ARRAY_SIZE(real_fft_test_input_data_512); i++) {
test_datain[i] = real_fft_test_input_data_512[i];
}
hwfft_fft_i32((hwfft_ctx_t *)&test_fft_config);
for (int i = 0; i < ARRAY_SIZE(real_fft_test_input_data_512) + 2; i++) {
/* printf("%d, ", out_ptr[i]); */
if (i % 2 == 0 && out_ptr[i] != real_fft_test_output_data_real_512[i / 2]) {
___trig;
printf("fft test real fail !!!\n");
put_buf((u8 *)out_ptr, sizeof(real_fft_test_input_data_512) + 8);
while (1);
} else if (i % 2 && out_ptr[i] != real_fft_test_output_data_img_512[i / 2]) {
___trig;
printf("fft test img fail !!!\n");
put_buf((u8 *)out_ptr, sizeof(real_fft_test_input_data_512) + 8);
while (1);
}
}
if (out_ptr != test_datain) {
memset(test_datain, 0, sizeof(test_datain));
}
hwfft_fill_fft_ctx((hwfft_ctx_t *)&test_fft_config, REAL_IFFT512_CONFIG, (long *)out_ptr, (long *)test_datain);
hwfft_ifft_i32((hwfft_ctx_t *)&test_fft_config);
for (int i = 0; i < ARRAY_SIZE(real_fft_test_input_data_512); i++) {
/* printf("%d, ", test_datain[i]); */
if (test_datain[i] != real_fft_test_input_data_512[i]) {
___trig;
printf("ifft test real fail !!!\n");
put_buf((u8 *)test_datain, sizeof(real_fft_test_input_data_512));
while (1);
}
}
hwfft_fill_fft_ctx((hwfft_ctx_t *)&test_fft_config, COMPLEX_FFT256_CONFIG, (long *)test_datain, (long *)out_ptr);
for (int i = 0; i < ARRAY_SIZE(complex_fft_test_output_data_256); i++) {
test_datain[i] = i;
}
hwfft_fft_i32((hwfft_ctx_t *)&test_fft_config);
for (int i = 0; i < ARRAY_SIZE(complex_fft_test_output_data_256); i++) {
/* printf("%d, ", out_ptr[i]); */
if (out_ptr[i] != complex_fft_test_output_data_256[i]) {
___trig;
printf("fft test complex fail !!!\n");
put_buf((u8 *)out_ptr, sizeof(complex_fft_test_output_data_256));
while (1);
}
}
if (out_ptr != test_datain) {
memset(test_datain, 0, sizeof(test_datain));
}
hwfft_fill_fft_ctx((hwfft_ctx_t *)&test_fft_config, COMPLEX_IFFT256_CONFIG, (long *)out_ptr, (long *)test_datain);
hwfft_ifft_i32((hwfft_ctx_t *)&test_fft_config);
for (int i = 0; i < ARRAY_SIZE(complex_fft_test_output_data_256); i++) {
/* printf("%d, ", test_datain[i]); */
if (test_datain[i] != i) {
___trig;
printf("ifft test complex fail !!!\n");
put_buf((u8 *)test_datain, sizeof(complex_fft_test_output_data_256));
while (1);
}
}
hwfft_fill_fft_ctx((hwfft_ctx_t *)&test_fft_config, COMPLEX_FFT512_CONFIG, (long *)test_datain, (long *)out_ptr);
for (int i = 0; i < ARRAY_SIZE(complex_fft_test_output_data_512); i++) {
test_datain[i] = i;
}
hwfft_fft_i32((hwfft_ctx_t *)&test_fft_config);
for (int i = 0; i < ARRAY_SIZE(complex_fft_test_output_data_512); i++) {
/* printf("%d, ", out_ptr[i]); */
if (out_ptr[i] != complex_fft_test_output_data_512[i]) {
___trig;
printf("fft test complex fail !!!\n");
put_buf((u8 *)out_ptr, sizeof(complex_fft_test_output_data_512));
while (1);
}
}
if (out_ptr != test_datain) {
memset(test_datain, 0, sizeof(test_datain));
}
hwfft_fill_fft_ctx((hwfft_ctx_t *)&test_fft_config, COMPLEX_IFFT512_CONFIG, (long *)out_ptr, (long *)test_datain);
hwfft_ifft_i32((hwfft_ctx_t *)&test_fft_config);
for (int i = 0; i < ARRAY_SIZE(complex_fft_test_output_data_512); i++) {
/* printf("%d, ", test_datain[i]); */
if (test_datain[i] != i) {
___trig;
printf("ifft test complex fail !!!\n");
put_buf((u8 *)test_datain, sizeof(complex_fft_test_output_data_512));
while (1);
}
}
hwfft_fill_fft_ctx((hwfft_ctx_t *)&test_fft_config, REAL_FFT1024_CONFIG, (long *)test_datain, (long *)out_ptr);
for (int i = 0; i < ARRAY_SIZE(real_fft_test_output_data_1024) - 2; i++) {
test_datain[i] = i;
}
hwfft_fft_i32((hwfft_ctx_t *)&test_fft_config);
for (int i = 0; i < ARRAY_SIZE(real_fft_test_output_data_1024); i++) {
/* printf("%d, ", out_ptr[i]); */
if (out_ptr[i] != real_fft_test_output_data_1024[i]) {
___trig;
printf("fft test complex fail !!!\n");
put_buf((u8 *)out_ptr, sizeof(real_fft_test_output_data_1024));
while (1);
}
}
if (out_ptr != test_datain) {
memset(test_datain, 0, sizeof(test_datain));
}
hwfft_fill_fft_ctx((hwfft_ctx_t *)&test_fft_config, REAL_IFFT1024_CONFIG, (long *)out_ptr, (long *)test_datain);
hwfft_ifft_i32((hwfft_ctx_t *)&test_fft_config);
for (int i = 0; i < ARRAY_SIZE(real_fft_test_output_data_1024) - 2; i++) {
/* printf("%d, ", test_datain[i]); */
if (test_datain[i] != i) {
___trig;
printf("ifft test complex fail !!!\n");
put_buf((u8 *)test_datain, sizeof(real_fft_test_output_data_1024) - 2);
while (1);
}
}
//循环测试
for (int n = 0; n < ARRAY_SIZE(real_tab); n += 2) {
hwfft_fill_fft_ctx((hwfft_ctx_t *)&test_fft_config, real_tab[n].config, (long *)test_datain, (long *)out_ptr);
for (int i = 0; i < real_tab[n].block; i++) {
test_datain[i] = i * fft_test_cnt;
}
hwfft_fft_i32((hwfft_ctx_t *)&test_fft_config);
if (out_ptr != test_datain) {
memset(test_datain, 0, sizeof(test_datain));
}
hwfft_fill_fft_ctx((hwfft_ctx_t *)&test_fft_config, real_tab[n + 1].config, (long *)out_ptr, (long *)test_datain);
hwfft_ifft_i32((hwfft_ctx_t *)&test_fft_config);
for (int i = 0; i < real_tab[n + 1].block; i++) {
/* printf("%d, ", test_datain[i]); */
if (test_datain[i] != i * fft_test_cnt && test_datain[i] != i * fft_test_cnt + 1 && test_datain[i] != i * fft_test_cnt - 1) {
___trig;
printf("real test fail n : %d, i : %d, cnt : %d !!!\n", n, i, fft_test_cnt);
for (int i = 0; i < real_tab[n + 1].block; i++) {
printf("%d, ", test_datain[i]);
}
/* put_buf((u8 *)test_datain, real_tab[n + 1].block * 4); */
while (1);
}
}
}
for (int n = 0; n < ARRAY_SIZE(complex_tab); n += 2) {
hwfft_fill_fft_ctx((hwfft_ctx_t *)&test_fft_config, complex_tab[n].config, (long *)test_datain, (long *)out_ptr);
for (int i = 0; i < complex_tab[n].block * 2; i++) {
test_datain[i] = i;
}
hwfft_fft_i32((hwfft_ctx_t *)&test_fft_config);
if (out_ptr != test_datain) {
memset(test_datain, 0, sizeof(test_datain));
}
hwfft_fill_fft_ctx((hwfft_ctx_t *)&test_fft_config, complex_tab[n + 1].config, (long *)out_ptr, (long *)test_datain);
hwfft_ifft_i32((hwfft_ctx_t *)&test_fft_config);
for (int i = 0; i < complex_tab[n + 1].block * 2; i++) {
/* printf("%d, ", test_datain[i]); */
if (test_datain[i] != i) {
___trig;
printf("complex test fail n : %d, i : %d, cnt : %d !!!\n", n, i, 2);
for (int i = 0; i < real_tab[n + 1].block * 2; i++) {
printf("%d, ", test_datain[i]);
}
/* put_buf((u8 *)test_datain, complex_tab[n + 1].block * 2 * 4); */
while (1);
}
}
}
}
static void fft_test_task(void *priv)
{
while (1) {
hw_fft_test();
os_time_dly(1);
}
}
static int fft_test_init(void)
{
return thread_fork("fft_test", 0, 256, 0, 0, fft_test_task, NULL);
}
late_initcall(fft_test_init);
#endif