URL
https://opencores.org/ocsvn/dblclockfft/dblclockfft/trunk
Subversion Repositories dblclockfft
Compare Revisions
- This comparison shows the changes necessary to convert path
/dblclockfft/trunk/bench/cpp
- from Rev 23 to Rev 26
- ↔ Reverse comparison
Rev 23 → Rev 26
/fft_tb.m
8,8 → 8,12
% Reshape the matrix into one line per FFT |
% Assume an FFT length of 2048 |
ftlen = 2048; |
ndat = reshape(datc, ftlen, length(datc)/ftlen); |
% ftlen = 128; |
ndat = reshape(datc, ftlen*2, length(datc)/(ftlen*2)); |
|
truth = ndat((ftlen+1):(2*ftlen), :); |
output = ndat(1:ftlen,:); |
|
% Create a time axis, for use in plotting if desired |
tm = 0:(ftlen-1); |
|
/hwbfly_tb.cpp
109,6 → 109,7
m_bfly->i_right = rht; |
m_bfly->i_aux = aux & 1; |
|
m_bfly->i_ce = 1; |
tick(); |
|
if ((m_bfly->o_aux)&&(!m_lastaux)) |
/dblrev_tb.cpp
42,8 → 42,12
#include "Vdblreverse.h" |
#include "verilated.h" |
|
#define FFTBITS 4 |
#define FFTMASK ((1<<(FFTBITS))-1) |
#define FFTBITS 5 |
#define FFTSIZE (1<<(FFTBITS)) |
#define FFTMASK (FFTSIZE-1) |
#define DATALEN (1<<(FFTBITS+1)) |
#define DATAMSK (DATALEN-1) |
#define PAGEMSK (FFTSIZE) |
|
void tick(Vdblreverse *dblrev) { |
dblrev->i_clk = 0; |
50,6 → 54,8
dblrev->eval(); |
dblrev->i_clk = 1; |
dblrev->eval(); |
|
dblrev->i_ce = 0; |
} |
|
void reset(Vdblreverse *dblrev) { |
61,8 → 67,9
tick(dblrev); |
} |
|
unsigned long bitrev(int nbits, unsigned long val) { |
int r = 0; |
unsigned long bitrev(const int nbits, const unsigned long vl) { |
unsigned long r = 0; |
unsigned long val = vl; |
|
for(int k=0; k<nbits; k++) { |
r <<= 1; |
77,35 → 84,84
Verilated::commandArgs(argc, argv); |
Vdblreverse *dblrev = new Vdblreverse; |
int syncd = 0; |
unsigned long datastore[DATALEN], dataidx=0; |
|
reset(dblrev); |
|
for(int k=0; k<64; k++) { |
printf("FFTSIZE = %08x\n", FFTSIZE); |
printf("FFTMASK = %08x\n", FFTMASK); |
printf("DATALEN = %08x\n", DATALEN); |
printf("DATAMSK = %08x\n", DATAMSK); |
|
for(int k=0; k<4*(FFTSIZE); k++) { |
dblrev->i_ce = 1; |
dblrev->i_in_0 = 2*k; |
dblrev->i_in_1 = 2*k+1; |
datastore[(dataidx++)&(DATAMSK)] = dblrev->i_in_0; |
datastore[(dataidx++)&(DATAMSK)] = dblrev->i_in_1; |
tick(dblrev); |
|
printf("k=%3d: IN = %6lx : %6lx, OUT = %6lx : %6lx, SYNC = %d\n", |
printf("k=%3d: IN = %6lx : %6lx, OUT = %6lx : %6lx, SYNC = %d\t(%x)\n", |
k, dblrev->i_in_0, dblrev->i_in_1, |
dblrev->o_out_0, dblrev->o_out_1, dblrev->o_sync); |
dblrev->o_out_0, dblrev->o_out_1, dblrev->o_sync, |
dblrev->v__DOT__iaddr); |
|
if ((k>0)&&(((0==(k&(FFTMASK>>1)))?1:0) != dblrev->o_sync)) { |
fprintf(stderr, "FAIL, BAD SYNC\n"); |
fprintf(stdout, "FAIL, BAD SYNC\n"); |
exit(-1); |
} else if (dblrev->o_sync) |
} else if (dblrev->o_sync) { |
syncd = 1; |
} |
if ((syncd)&&((dblrev->o_out_0&FFTMASK) != bitrev(FFTBITS, 2*k))) { |
fprintf(stderr, "FAIL: BITREV of k (%2x) = %2lx, not %2lx\n", |
fprintf(stdout, "FAIL: BITREV.0 of k (%2x) = %2lx, not %2lx\n", |
k, dblrev->o_out_0, bitrev(FFTBITS, 2*k)); |
exit(-1); |
// exit(-1); |
} |
|
if ((syncd)&&((dblrev->o_out_1&FFTMASK) != bitrev(FFTBITS, 2*k+1))) { |
fprintf(stderr, "FAIL: BITREV of k (%2x) = %2lx, not %2lx\n", |
fprintf(stdout, "FAIL: BITREV.1 of k (%2x) = %2lx, not %2lx\n", |
k, dblrev->o_out_1, bitrev(FFTBITS, 2*k+1)); |
// exit(-1); |
} |
} |
|
for(int k=0; k<4*(FFTSIZE); k++) { |
dblrev->i_ce = 1; |
dblrev->i_in_0 = rand() & 0x0ffffff; |
dblrev->i_in_1 = rand() & 0x0ffffff; |
datastore[(dataidx++)&(DATAMSK)] = dblrev->i_in_0; |
datastore[(dataidx++)&(DATAMSK)] = dblrev->i_in_1; |
tick(dblrev); |
|
printf("k=%3d: IN = %6lx : %6lx, OUT = %6lx : %6lx, SYNC = %d\n", |
k, dblrev->i_in_0, dblrev->i_in_1, |
dblrev->o_out_0, dblrev->o_out_1, dblrev->o_sync); |
|
if ((k>0)&&(((0==(k&(FFTMASK>>1)))?1:0) != dblrev->o_sync)) { |
fprintf(stdout, "FAIL, BAD SYNC\n"); |
exit(-1); |
} else if (dblrev->o_sync) |
syncd = 1; |
if ((syncd)&&(dblrev->o_out_0 != datastore[(((dataidx-2-FFTSIZE)&PAGEMSK) + bitrev(FFTBITS, (dataidx-FFTSIZE-2)&FFTMASK))])) { |
fprintf(stdout, "FAIL: BITREV.0 of k (%2x) = %2lx, not %2lx (expected %lx -> %lx)\n", |
k, dblrev->o_out_0, |
datastore[(((dataidx-2-FFTSIZE)&PAGEMSK) |
+ bitrev(FFTBITS, (dataidx-FFTSIZE-2)&FFTMASK))], |
(dataidx-2)&DATAMSK, |
(((dataidx-2)&PAGEMSK) |
+ bitrev(FFTBITS, (dataidx-FFTSIZE-2)&FFTMASK))); |
// exit(-1); |
} |
|
if ((syncd)&&(dblrev->o_out_1 != datastore[(((dataidx-2-FFTSIZE)&PAGEMSK) + bitrev(FFTBITS, (dataidx-FFTSIZE-1)&FFTMASK))])) { |
fprintf(stdout, "FAIL: BITREV.1 of k (%2x) = %2lx, not %2lx (expected %lx)\n", |
k, dblrev->o_out_1, |
datastore[(((dataidx-2-FFTSIZE)&PAGEMSK) |
+ bitrev(FFTBITS, (dataidx-FFTSIZE-1)&FFTMASK))], |
(((dataidx-1)&PAGEMSK) |
+ bitrev(FFTBITS, (dataidx-FFTSIZE-1)&FFTMASK))); |
// exit(-1); |
} |
} |
|
delete dblrev; |
/fft_tb.cpp
49,16 → 49,30
|
#define LGWIDTH 11 |
#define IWIDTH 16 |
// #define OWIDTH 16 |
#define OWIDTH 22 |
|
#define NFTLOG 8 |
#define FFTLEN (1<<LGWIDTH) |
|
unsigned long bitrev(const int nbits, const unsigned long vl) { |
unsigned long r = 0; |
unsigned long val = vl; |
|
for(int k=0; k<nbits; k++) { |
r<<= 1; |
r |= (val & 1); |
val >>= 1; |
} |
|
return r; |
} |
|
class FFT_TB { |
public: |
Vfftmain *m_fft; |
long m_data[FFTLEN], m_log[NFTLOG*FFTLEN]; |
int m_iaddr, m_oaddr, m_ntest; |
int m_iaddr, m_oaddr, m_ntest, m_logbase; |
FILE *m_dumpfp; |
fftw_plan m_plan; |
double *m_fft_buf; |
82,6 → 96,17
m_fft->eval(); |
m_fft->i_clk = 1; |
m_fft->eval(); |
|
/* |
int nrpt = (rand()&0x01f) + 1; |
m_fft->i_ce = 0; |
for(int i=0; i<nrpt; i++) { |
m_fft->i_clk = 0; |
m_fft->eval(); |
m_fft->i_clk = 1; |
m_fft->eval(); |
} |
*/ |
} |
|
void reset(void) { |
91,7 → 116,7
m_fft->i_rst = 0; |
tick(); |
|
m_iaddr = m_oaddr = 0; |
m_iaddr = m_oaddr = m_logbase = 0; |
m_syncd = false; |
} |
|
106,8 → 131,9
long *lp; |
|
// Fill up our test array from the log array |
// printf("%3d : CHECK: %8d %5x\n", m_ntest, m_iaddr, m_iaddr); |
dp = m_fft_buf; lp = &m_log[(m_iaddr-FFTLEN*3)&((NFTLOG*FFTLEN-1)&(-FFTLEN))]; |
printf("%3d : CHECK: %8d %5x m_log[-%x=%x]\n", m_ntest, m_iaddr, m_iaddr, |
m_logbase, (m_iaddr-m_logbase)&((NFTLOG*FFTLEN-1)&(-FFTLEN))); |
dp = m_fft_buf; lp = &m_log[(m_iaddr-m_logbase)&((NFTLOG*FFTLEN-1)&(-FFTLEN))]; |
for(int i=0; i<FFTLEN; i++) { |
long tv = *lp++; |
|
123,8 → 149,9
|
// Let's measure ... are we the zero vector? If not, how close? |
dp = m_fft_buf; |
for(int i=0; i<FFTLEN; i++) |
isq += (*dp) * (*dp); |
for(int i=0; i<FFTLEN*2; i++) { |
isq += (*dp) * (*dp); dp++; |
} |
|
fftw_execute(m_plan); |
|
131,17 → 158,10
// Let's load up the output we received into vout |
dp = vout; |
for(int i=0; i<FFTLEN; i++) { |
long tv = m_data[i]; |
|
// printf("OUT[%4d = %4x] = ", i, i); |
// printf("%12lx = ", tv); |
*dp = sbits(tv >> OWIDTH, OWIDTH); |
// printf("%10.1f + ", *dp); |
*dp = rdata(i); |
osq += (*dp) * (*dp); dp++; |
*dp = sbits(tv, OWIDTH); |
// printf("%10.1f j", *dp); |
*dp = idata(i); |
osq += (*dp) * (*dp); dp++; |
// printf(" <-> %12.1f %12.1f\n", m_fft_buf[2*i], m_fft_buf[2*i+1]); |
} |
|
|
157,6 → 177,19
|
double xisq = 0.0; |
sp = m_fft_buf; dp = vout; |
|
if ((true)&&(m_dumpfp)) { |
double tmp[FFTLEN*2], nscl; |
|
if (fabs(scale) < 1e-4) |
nscl = 1.0; |
else |
nscl = scale; |
for(int i=0; i<FFTLEN*2; i++) |
tmp[i] = m_fft_buf[i] * nscl; |
fwrite(tmp, sizeof(double), FFTLEN*2, m_dumpfp); |
} |
|
for(int i=0; i<FFTLEN*2; i++) { |
double vl = (*sp++) * scale - (*dp++); |
xisq += vl * vl; |
186,24 → 219,31
tick(); |
|
if (m_fft->o_sync) { |
if (!m_syncd) { |
m_logbase = m_iaddr; |
} // else printf("RESYNC AT %lx\n", m_fft->m_tickcount); |
m_oaddr &= (-1<<LGWIDTH); |
m_syncd = true; |
} else m_oaddr += 2; |
|
printf("%8x,%5d: %08x,%08x -> %011lx,%011lx" |
// "\t%011lx,%011lx" |
"\t%011lx,%011lx" |
printf("%8x,%5d: %08x,%08x -> %011lx,%011lx", |
m_iaddr, m_oaddr, |
lft, rht, m_fft->o_left, m_fft->o_right); |
printf( // "\t%011lx,%011lx" |
"\t%3x" |
"\t%011lx,%011lx" // w_e128, w_o128 |
// "\t%011lx,%011lx" // w_e4, w_o4 |
// "\t%06x,%06x" |
// "\t%06x,%06x" |
// "\t%011lx,%06x,%06x" |
"\t%011lx,%06x,%06x" |
"\t%06x,%06x,%06x,%06x" |
"\t%011lx,%011lx" |
" %s%s%s%s%s%s%s%s%s%s%s %s%s\n", |
m_iaddr, m_oaddr, |
lft, rht, m_fft->o_left, m_fft->o_right, |
m_fft->v__DOT__w_e4, |
m_fft->v__DOT__w_o4, |
"\t%011lx,%06x,%06x" // ob_a, ob_b_r, ob_b_i |
"\t%06x,%06x,%06x,%06x", // o_out_xx |
// "\t%011lx,%011lx" |
m_fft->v__DOT__revstage__DOT__iaddr, |
m_fft->v__DOT__w_e128, |
m_fft->v__DOT__w_o128, |
// m_fft->v__DOT__w_e4, |
// m_fft->v__DOT__w_o4, |
// m_fft->v__DOT__stage_e512__DOT__ib_a, |
// m_fft->v__DOT__stage_e512__DOT__ib_b, |
// m_fft->v__DOT__stage_e256__DOT__ib_a, |
233,13 → 273,23
m_fft->v__DOT__stage_2__DOT__o_out_0r, |
m_fft->v__DOT__stage_2__DOT__o_out_0i, |
m_fft->v__DOT__stage_2__DOT__o_out_1r, |
m_fft->v__DOT__stage_2__DOT__o_out_1i, |
m_fft->v__DOT__br_o_left, |
m_fft->v__DOT__br_o_right, |
(m_fft->v__DOT__w_s2048)?"S":"-", |
(m_fft->v__DOT__w_s1024)?"S":"-", |
(m_fft->v__DOT__w_s512)?"S":"-", |
(m_fft->v__DOT__w_s256)?"S":"-", |
m_fft->v__DOT__stage_2__DOT__o_out_1i); |
/* |
printf(" DBG:%c%c:%08x [%6d,%6d]", |
(m_fft->o_dbg&(1l<<33))?'T':' ', |
(m_fft->o_dbg&(1l<<32))?'C':' ', |
(unsigned)(m_fft->o_dbg&((-1l<<32)-1)), |
((int)(m_fft->o_dbg))>>16, |
(((unsigned)(m_fft->o_dbg&0x0ffff)) |
|((m_fft->o_dbg&0x08000)?(-1<<16):0))); |
*/ |
printf(" %s%s%s%s%s%s%s %s%s\n", |
// m_fft->v__DOT__br_o_left, |
// m_fft->v__DOT__br_o_right, |
// (m_fft->v__DOT__w_s2048)?"S":"-", |
// (m_fft->v__DOT__w_s1024)?"S":"-", |
// (m_fft->v__DOT__w_s512)?"S":"-", |
// (m_fft->v__DOT__w_s256)?"S":"-", |
(m_fft->v__DOT__w_s128)?"S":"-", |
(m_fft->v__DOT__w_s64)?"S":"-", |
(m_fft->v__DOT__w_s32)?"S":"-", |
276,11 → 326,17
} |
|
double rdata(int addr) { |
return (double)sbits(m_data[addr&(FFTLEN-1)]>>OWIDTH, OWIDTH); |
int index = addr & (FFTLEN-1); |
|
// index = bitrev(LGWIDTH, index); |
return (double)sbits(m_data[index]>>OWIDTH, OWIDTH); |
} |
|
double idata(int addr) { |
return (double)sbits(m_data[addr&(FFTLEN-1)], OWIDTH); |
int index = addr & (FFTLEN-1); |
|
// index = bitrev(LGWIDTH, index); |
return (double)sbits(m_data[index], OWIDTH); |
} |
|
void dump(FILE *fp) { |
319,6 → 375,96
fft->reset(); |
fft->dump(fpout); |
|
// 1. |
fft->test(0.0, 0.0, 32767.0, 0.0); |
for(int k=0; k<FFTLEN/2-1; k++) |
fft->test(0.0,0.0,0.0,0.0); |
|
// 2. |
fft->test(32767.0, 0.0, 32767.0, 0.0); |
for(int k=0; k<FFTLEN/2-1; k++) |
fft->test(0.0,0.0,0.0,0.0); |
|
// 3. |
fft->test(0.0,0.0,0.0,0.0); |
fft->test(32767.0, 0.0, 0.0, 0.0); |
for(int k=0; k<FFTLEN/2-1; k++) |
fft->test(0.0,0.0,0.0,0.0); |
|
// 4. |
for(int k=0; k<8; k++) |
fft->test(32767.0, 0.0, 32767.0, 0.0); |
for(int k=8; k<FFTLEN/2; k++) |
fft->test(0.0,0.0,0.0,0.0); |
|
// 5. |
if (FFTLEN/2 >= 16) { |
for(int k=0; k<16; k++) |
fft->test(32767.0, 0.0, 32767.0, 0.0); |
for(int k=16; k<FFTLEN/2; k++) |
fft->test(0.0,0.0,0.0,0.0); |
} |
|
// 6. |
if (FFTLEN/2 >= 32) { |
for(int k=0; k<32; k++) |
fft->test(32767.0, 0.0, 32767.0, 0.0); |
for(int k=32; k<FFTLEN/2; k++) |
fft->test(0.0,0.0,0.0,0.0); |
} |
|
// 7. |
if (FFTLEN/2 >= 64) { |
for(int k=0; k<64; k++) |
fft->test(32767.0, 0.0, 32767.0, 0.0); |
for(int k=64; k<FFTLEN/2; k++) |
fft->test(0.0,0.0,0.0,0.0); |
} |
|
if (FFTLEN/2 >= 128) { |
for(int k=0; k<128; k++) |
fft->test(32767.0, 0.0, 32767.0, 0.0); |
for(int k=128; k<FFTLEN/2; k++) |
fft->test(0.0,0.0,0.0,0.0); |
} |
|
if (FFTLEN/2 >= 256) { |
for(int k=0; k<256; k++) |
fft->test(32767.0, 0.0, 32767.0, 0.0); |
for(int k=256; k<FFTLEN/2; k++) |
fft->test(0.0,0.0,0.0,0.0); |
} |
|
if (FFTLEN/2 >= 512) { |
for(int k=0; k<256+128; k++) |
fft->test(32767.0, 0.0, 32767.0, 0.0); |
for(int k=256+128; k<FFTLEN/2; k++) |
fft->test(0.0,0.0,0.0,0.0); |
} |
|
/* |
for(int k=0; k<FFTLEN/2; k++) |
fft->test(0.0,0.0,0.0,0.0); |
|
for(int k=0; k<FFTLEN/2; k++) |
fft->test(0.0,0.0,0.0,0.0); |
|
for(int k=0; k<FFTLEN/2; k++) |
fft->test(0.0,0.0,0.0,0.0); |
|
for(int k=0; k<FFTLEN/2; k++) |
fft->test(0.0,0.0,0.0,0.0); |
|
for(int k=0; k<FFTLEN/2; k++) |
fft->test(0.0,0.0,0.0,0.0); |
|
for(int k=0; k<FFTLEN/2; k++) |
fft->test(0.0,0.0,0.0,0.0); |
*/ |
|
#ifndef NO_JUNK |
// 7. |
|
// 1 -> 0x0001 |
// 2 -> 0x0002 |
// 4 -> 0x0004 |
352,6 → 498,10
// 8192 -> 0xe000 |
// 16384 -> 0xc000 |
// 32768 -> 0x8000 |
fft->test(0.0,0.0,16384.0,0.0); |
for(int k=0; k<FFTLEN/2-1; k++) |
fft->test(0.0,0.0,0.0,0.0); |
|
for(int v=1; v<=32768; v<<=1) for(int k=0; k<FFTLEN/2; k++) |
fft->test(-(double)v,0.0,-(double)v,0.0); |
// 1 -> 0x000040 CORRECT!! |
431,6 → 581,16
for(int k=0; k<FFTLEN/2-1; k++) |
fft->test(0.0,0.0,0.0,0.0); |
|
// 72. And another one on the next clock (FAILS, ugly) |
fft->test(0.0, 0.0, 8192.0, 0.0); |
for(int k=0; k<FFTLEN/2-1; k++) |
fft->test(0.0,0.0,0.0,0.0); |
|
// 72. And another one on the next clock (FAILS, ugly) |
fft->test(0.0, 0.0, 512.0, 0.0); |
for(int k=0; k<FFTLEN/2-1; k++) |
fft->test(0.0,0.0,0.0,0.0); |
|
// 73. And an imaginary one on the second clock |
fft->test(0.0, 0.0, 0.0, 16384.0); |
for(int k=0; k<FFTLEN/2-1; k++) |
504,7 → 664,7
sr = sin(W * (2*k+1)) * 4.0; |
fft->test(cl, sl, cr, sr); |
} |
|
#endif |
// 19.--24. And finally, let's clear out our results / buffer |
for(int k=0; k<(FFTLEN/2) * 5; k++) |
fft->test(0.0,0.0,0.0,0.0); |
/fftstage_o2048_tb.cpp
282,6 → 282,18
// Largest negative imaginary value |
for(int k=1; k<FFTSIZE; k+=2) |
ftstage->test((k==1), 0x000010000l); |
// Let's try an impulse |
for(int k=0; k<FFTSIZE; k+=2) |
ftstage->test((k==0), (k==0)?0x020000000l:0l); |
// Now, let's clear out the result |
for(int k=0; k<FFTSIZE; k+=2) |
ftstage->test((k==0), 0x000000000l); |
for(int k=0; k<FFTSIZE; k+=2) |
ftstage->test((k==0), 0x000000000l); |
for(int k=0; k<FFTSIZE; k+=2) |
ftstage->test((k==0), 0x000000000l); |
for(int k=0; k<FFTSIZE; k+=2) |
ftstage->test((k==0), 0x000000000l); |
|
printf("SUCCESS! (Offset = %d)\n", ftstage->m_offset); |
delete ftstage; |
/butterfly_tb.cpp
89,10 → 89,11
// we'll never get an aux=1 output. |
// |
m_bfly->i_rst = 1; |
m_bfly->i_ce = 1; |
m_bfly->i_aux = 1; |
for(int i=0; i<200; i++) |
for(int i=0; i<200; i++) { |
m_bfly->i_ce = 1; |
tick(); |
} |
|
// Now here's the RESET line, so let's see what the test does |
m_bfly->i_rst = 1; |
117,6 → 118,7
m_addr = 0; |
} |
|
m_bfly->i_ce = 1; |
tick(); |
|
if ((m_bfly->o_aux)&&(!m_lastaux)) |