Use uncached ExtRAM access (0xBC400000) to bypass CPU data cache
The open-la500 core has USE_CACHE enabled. Writes to 0x1c400000 go to the write-back data cache and never reach the SRAM model before the testbench checks ExtRAM. Use the 0xA0000000 uncached segment (same pattern as fft_dma/main.c).
This commit is contained in:
11
sdk/software/examples/fft/Makefile
Normal file
11
sdk/software/examples/fft/Makefile
Normal file
@@ -0,0 +1,11 @@
|
||||
TARGET = fft
|
||||
|
||||
CFLAGS += -O3 -g
|
||||
|
||||
C_SRCS := $(wildcard ./*.c )
|
||||
|
||||
OBJDIR = obj
|
||||
COMMON_DIR = ../../bsp
|
||||
GCC_DIR=../../../toolchains/loongson-gnu-toolchain-8.3-x86_64-loongarch32r-linux-gnusf-v2.0
|
||||
PICOLIBC_DIR=../../../toolchains/picolibc
|
||||
include ../../bsp/common.mk
|
||||
156
sdk/software/examples/fft/main.c
Normal file
156
sdk/software/examples/fft/main.c
Normal file
@@ -0,0 +1,156 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <common_func.h>
|
||||
#include <confreg_time.h>
|
||||
#include <fft.h>
|
||||
|
||||
// BSP板级支持包所需全局变量
|
||||
unsigned long UART_BASE = 0xbf000000;
|
||||
unsigned long CONFREG_TIMER_BASE = 0xbf20f100;
|
||||
unsigned long CONFREG_CLOCKS_PER_SEC = 50000000L;
|
||||
unsigned long CORE_CLOCKS_PER_SEC = 33000000L;
|
||||
|
||||
const float PI = 3.14159265358979323846;
|
||||
|
||||
// 读取定时器的当前Tick
|
||||
unsigned int get_timer_ticks() {
|
||||
return RegRead(CONFREG_TIMER_BASE);
|
||||
}
|
||||
|
||||
// 软件FFT实现 (基2 DIT-FFT 算法)
|
||||
void sw_fft(float re[], float im[], int n) {
|
||||
int i, j, k, l;
|
||||
float tr, ti, ur, ui, wr, wi;
|
||||
|
||||
// 比特翻转 (Bit Reversal)
|
||||
j = 0;
|
||||
for (i = 0; i < n - 1; i++) {
|
||||
if (i < j) {
|
||||
tr = re[i]; ti = im[i];
|
||||
re[i] = re[j]; im[i] = im[j];
|
||||
re[j] = tr; im[j] = ti;
|
||||
}
|
||||
k = n / 2;
|
||||
while (k <= j) {
|
||||
j -= k;
|
||||
k /= 2;
|
||||
}
|
||||
j += k;
|
||||
}
|
||||
|
||||
// 蝶形运算 (Butterfly Computation)
|
||||
for (l = 1; l < n; l *= 2) {
|
||||
ur = 1.0;
|
||||
ui = 0.0;
|
||||
wr = cos(PI / l);
|
||||
wi = -sin(PI / l);
|
||||
|
||||
for (i = 0; i < n; i += 2 * l) {
|
||||
ur = 1.0;
|
||||
ui = 0.0;
|
||||
for (j = 0; j < l; j++) {
|
||||
int p = i + j;
|
||||
int q = p + l;
|
||||
|
||||
tr = re[q] * ur - im[q] * ui;
|
||||
ti = re[q] * ui + im[q] * ur;
|
||||
|
||||
re[q] = re[p] - tr;
|
||||
im[q] = im[p] - ti;
|
||||
re[p] += tr;
|
||||
im[p] += ti;
|
||||
|
||||
float next_ur = ur * wr - ui * wi;
|
||||
ui = ur * wi + ui * wr;
|
||||
ur = next_ur;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
unsigned int fft_csr = RegRead(FFT_CSR_REG);
|
||||
printf("fft_csr = %x\n", fft_csr);
|
||||
|
||||
// 准备测试数据
|
||||
float sw_in_re[FFT_POINT_NUM];
|
||||
float sw_in_im[FFT_POINT_NUM];
|
||||
|
||||
for (int i = 0; i < FFT_POINT_NUM; i++) {
|
||||
float dc_part = 4000.0f;
|
||||
float f10_part = 8000.0f * cos(2 * PI * 10.0 * i / FFT_POINT_NUM);
|
||||
float f200_part = 6000.0f * sin(2 * PI * 200.0 * i / FFT_POINT_NUM);
|
||||
float f400_part = 3000.0f * sin(2 * PI * 400.0 * i / FFT_POINT_NUM);
|
||||
|
||||
sw_in_re[i] = dc_part + f10_part + f200_part + f400_part;
|
||||
sw_in_im[i] = 0.0f;
|
||||
}
|
||||
|
||||
unsigned int tick_start, tick_end;
|
||||
unsigned int hw_time, sw_time;
|
||||
|
||||
// 硬件加速 FFT 测试
|
||||
printf("\n--- Starting Hardware FFT ---\n");
|
||||
tick_start = get_ns();
|
||||
|
||||
for (int i = 0; i < FFT_POINT_NUM; i++) {
|
||||
RegWrite(FFT_IN_RE_BASE + (i * 4), (unsigned int)((int)sw_in_re[i]));
|
||||
RegWrite(FFT_IN_IM_BASE + (i * 4), 0);
|
||||
}
|
||||
|
||||
|
||||
fft_start();
|
||||
fft_wait();
|
||||
|
||||
tick_end = get_ns();
|
||||
|
||||
// 如果定时器是递减的,这里可能是 tick_start - tick_end
|
||||
// 假设定时器是向上递增的:
|
||||
hw_time = tick_end - tick_start;
|
||||
|
||||
int hw_out_re[FFT_POINT_NUM];
|
||||
int hw_out_im[FFT_POINT_NUM];
|
||||
for (int i = 0; i < FFT_POINT_NUM; i++) {
|
||||
hw_out_re[i] = (int)RegRead(FFT_OUT_RE_BASE + (i * 4));
|
||||
hw_out_im[i] = (int)RegRead(FFT_OUT_IM_BASE + (i * 4));
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// 2. 纯软件 FFT 测试
|
||||
// ==========================================
|
||||
printf("--- Starting Software FFT ---\n");
|
||||
tick_start = get_ns();
|
||||
|
||||
sw_fft(sw_in_re, sw_in_im, FFT_POINT_NUM);
|
||||
|
||||
tick_end = get_ns();
|
||||
sw_time = tick_end - tick_start;
|
||||
|
||||
|
||||
// ==========================================
|
||||
// 3. 打印对比结果
|
||||
// ==========================================
|
||||
printf("\n--- Performance Comparison ---\n");
|
||||
printf("Timer Clock Freq : %lu Hz\n", CONFREG_CLOCKS_PER_SEC);
|
||||
printf("Hardware FFT Time: %u ns (%.3f ms)\n", hw_time, (float)hw_time / 1000000.0);
|
||||
printf("Software FFT Time: %u ns (%.3f ms)\n", sw_time, (float)sw_time / 1000000.0);
|
||||
|
||||
if (hw_time > 0) {
|
||||
printf("Speedup Ratio : %.2fx\n", (float)sw_time / hw_time);
|
||||
}
|
||||
|
||||
printf("\n--- Verification (Only showing Bins with energy > 10) ---\n");
|
||||
for (int i = 0; i < FFT_POINT_NUM; i++) {
|
||||
if (fabs(hw_out_re[i]) > 10 || fabs(hw_out_im[i]) > 10) {
|
||||
printf("Bin [%4d] Hz: HW(Re:%6d, Im:%6d) | SW(Re:%6d, Im:%6d)\n",
|
||||
i,
|
||||
hw_out_re[i], hw_out_im[i],
|
||||
(int)sw_in_re[i] / FFT_POINT_NUM, (int)sw_in_im[i] / FFT_POINT_NUM);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
19
sdk/software/examples/fft/result.txt
Normal file
19
sdk/software/examples/fft/result.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
fft_csr = 0
|
||||
|
||||
--- Starting Hardware FFT ---
|
||||
--- Starting Software FFT ---
|
||||
|
||||
--- Performance Comparison ---
|
||||
Timer Clock Freq : 50000000 Hz
|
||||
Hardware FFT Time: 1695360 ns (1.695 ms)
|
||||
Software FFT Time: 274547190 ns (274.547 ms)
|
||||
Speedup Ratio : 161.94x
|
||||
|
||||
--- Verification (Only showing Bins with energy > 10) ---
|
||||
Bin [ 0] Hz: HW(Re: 4007, Im: 0) | SW(Re: 4000, Im: 0)
|
||||
Bin [ 10] Hz: HW(Re: 4006, Im: -1) | SW(Re: 3999, Im: 0)
|
||||
Bin [ 200] Hz: HW(Re: 2, Im: -2994) | SW(Re: 0, Im: -3000)
|
||||
Bin [ 400] Hz: HW(Re: -5, Im: -1496) | SW(Re: 0, Im: -1499)
|
||||
Bin [ 624] Hz: HW(Re: -5, Im: 1497) | SW(Re: 0, Im: 1500)
|
||||
Bin [ 824] Hz: HW(Re: 3, Im: 2994) | SW(Re: 0, Im: 2999)
|
||||
Bin [1014] Hz: HW(Re: 4007, Im: 0) | SW(Re: 3999, Im: 0)
|
||||
Reference in New Issue
Block a user