test(fft): update fft_dma example
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -10,6 +10,7 @@
|
|||||||
#define FFT_STAT_DONE (1 << 1)
|
#define FFT_STAT_DONE (1 << 1)
|
||||||
#define FFT_STAT_BUSY (1 << 0)
|
#define FFT_STAT_BUSY (1 << 0)
|
||||||
#define FFT_POINT_NUM 1024
|
#define FFT_POINT_NUM 1024
|
||||||
|
#define FFT_SAMPLE_BITS 16
|
||||||
|
|
||||||
void fft_start();
|
void fft_start();
|
||||||
void fft_wait();
|
void fft_wait();
|
||||||
|
|||||||
@@ -67,7 +67,8 @@ void sw_fft(float re[], float im[], int n) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 全局对齐数组:作为 DMA 的源和目的内存
|
// 全局对齐数组:作为 DMA 的源和目的内存。
|
||||||
|
// FFT 外设仍按 32-bit AXI word 编址,每个 word 的低 16 bit 作为一个 signed 样本。
|
||||||
int32_t hw_in_re_arr[FFT_POINT_NUM] __attribute__((aligned(64)));
|
int32_t hw_in_re_arr[FFT_POINT_NUM] __attribute__((aligned(64)));
|
||||||
int32_t hw_in_im_arr[FFT_POINT_NUM] __attribute__((aligned(64)));
|
int32_t hw_in_im_arr[FFT_POINT_NUM] __attribute__((aligned(64)));
|
||||||
int32_t hw_out_re_arr[FFT_POINT_NUM] __attribute__((aligned(64)));
|
int32_t hw_out_re_arr[FFT_POINT_NUM] __attribute__((aligned(64)));
|
||||||
@@ -95,13 +96,13 @@ int main(int argc, char** argv)
|
|||||||
float sw_in_im[FFT_POINT_NUM];
|
float sw_in_im[FFT_POINT_NUM];
|
||||||
|
|
||||||
for (int i = 0; i < FFT_POINT_NUM; i++) {
|
for (int i = 0; i < FFT_POINT_NUM; i++) {
|
||||||
int32_t sample = fft_test_sample((unsigned int)i);
|
int16_t sample = (int16_t)fft_test_sample((unsigned int)i);
|
||||||
|
|
||||||
sw_in_re[i] = (float)sample;
|
sw_in_re[i] = (float)sample;
|
||||||
sw_in_im[i] = 0.0f;
|
sw_in_im[i] = 0.0f;
|
||||||
|
|
||||||
// 硬件输入需要转为整数存入无缓存内存
|
// 硬件输入为 16-bit signed,写入 32-bit word 的低半字。
|
||||||
uncached_in_re[i] = sample;
|
uncached_in_re[i] = (int32_t)sample;
|
||||||
uncached_in_im[i] = 0;
|
uncached_in_im[i] = 0;
|
||||||
|
|
||||||
// 清理输出内存以防干扰
|
// 清理输出内存以防干扰
|
||||||
@@ -116,7 +117,7 @@ int main(int argc, char** argv)
|
|||||||
printf("\n--- Starting Hardware FFT with DMA ---\n");
|
printf("\n--- Starting Hardware FFT with DMA ---\n");
|
||||||
tick_start = get_ns(); // 开始计时
|
tick_start = get_ns(); // 开始计时
|
||||||
|
|
||||||
uint32_t transfer_bytes = FFT_POINT_NUM * 4; // 1024个点 * 4字节
|
uint32_t transfer_bytes = FFT_POINT_NUM * 4; // 1024个点 * 4字节,低16位有效
|
||||||
|
|
||||||
// MA 将数据从内存搬运到 FFT 输入外设
|
// MA 将数据从内存搬运到 FFT 输入外设
|
||||||
dma_start_transfer(0, ((uint32_t)hw_in_re_arr & 0x1FFFFFFF), phys_fft_in_re, transfer_bytes, 100);
|
dma_start_transfer(0, ((uint32_t)hw_in_re_arr & 0x1FFFFFFF), phys_fft_in_re, transfer_bytes, 100);
|
||||||
@@ -158,19 +159,31 @@ int main(int argc, char** argv)
|
|||||||
printf("Speedup Ratio : %.2fx\n", (float)sw_time / hw_time);
|
printf("Speedup Ratio : %.2fx\n", (float)sw_time / hw_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n--- Verification (Only showing Bins with energy > 10) ---\n");
|
printf("\n--- Verification (%d-bit FFT, only showing bins with energy > 10) ---\n", FFT_SAMPLE_BITS);
|
||||||
|
int max_abs_err_re = 0;
|
||||||
|
int max_abs_err_im = 0;
|
||||||
for (int i = 0; i < FFT_POINT_NUM; i++) {
|
for (int i = 0; i < FFT_POINT_NUM; i++) {
|
||||||
// CPU 通过无缓存指针读取 DMA 搬运回来的结果
|
// CPU 通过无缓存指针读取 DMA 搬运回来的结果
|
||||||
int32_t hw_re = uncached_out_re[i];
|
int32_t hw_re = uncached_out_re[i];
|
||||||
int32_t hw_im = uncached_out_im[i];
|
int32_t hw_im = uncached_out_im[i];
|
||||||
|
int32_t sw_re = (int32_t)sw_in_re[i] / FFT_POINT_NUM;
|
||||||
|
int32_t sw_im = (int32_t)sw_in_im[i] / FFT_POINT_NUM;
|
||||||
|
int err_re = (int)(hw_re - sw_re);
|
||||||
|
int err_im = (int)(hw_im - sw_im);
|
||||||
|
|
||||||
|
if (err_re < 0) err_re = -err_re;
|
||||||
|
if (err_im < 0) err_im = -err_im;
|
||||||
|
if (err_re > max_abs_err_re) max_abs_err_re = err_re;
|
||||||
|
if (err_im > max_abs_err_im) max_abs_err_im = err_im;
|
||||||
|
|
||||||
if (fabs((float)hw_re) > 10 || fabs((float)hw_im) > 10) {
|
if (fabs((float)hw_re) > 10 || fabs((float)hw_im) > 10) {
|
||||||
printf("Bin [%4d] Hz: HW(Re:%6d, Im:%6d) | SW(Re:%6d, Im:%6d)\n",
|
printf("Bin [%4d] Hz: HW(Re:%6d, Im:%6d) | SW(Re:%6d, Im:%6d)\n",
|
||||||
i,
|
i,
|
||||||
hw_re, hw_im,
|
hw_re, hw_im,
|
||||||
(int)sw_in_re[i] / FFT_POINT_NUM, (int)sw_in_im[i] / FFT_POINT_NUM);
|
sw_re, sw_im);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
printf("Max Abs Error : Re=%d, Im=%d\n", max_abs_err_re, max_abs_err_im);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user