OpenCores
URL https://opencores.org/ocsvn/dblclockfft/dblclockfft/trunk

Subversion Repositories dblclockfft

[/] [dblclockfft/] [trunk/] [bench/] [cpp/] [fft_tb.cpp] - Blame information for rev 41

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 41 dgisselq
////////////////////////////////////////////////////////////////////////////////
2 7 dgisselq
//
3 9 dgisselq
// Filename:    fft_tb.cpp
4 7 dgisselq
//
5 41 dgisselq
// Project:     A General Purpose Pipelined FFT Implementation
6 7 dgisselq
//
7 14 dgisselq
// Purpose:     A test-bench for the main program, fftmain.v, of the double
8 9 dgisselq
//              clocked FFT.  This file may be run autonomously  (when
9 36 dgisselq
//      fully functional).  If so, the last line output will either read
10
//      "SUCCESS" on success, or some other failure message otherwise.
11 7 dgisselq
//
12 36 dgisselq
//      This file depends upon verilator to both compile, run, and therefore
13
//      test fftmain.v
14 7 dgisselq
//
15
// Creator:     Dan Gisselquist, Ph.D.
16 30 dgisselq
//              Gisselquist Technology, LLC
17 7 dgisselq
//
18 41 dgisselq
////////////////////////////////////////////////////////////////////////////////
19 7 dgisselq
//
20 36 dgisselq
// Copyright (C) 2015,2018, Gisselquist Technology, LLC
21 7 dgisselq
//
22
// This program is free software (firmware): you can redistribute it and/or
23
// modify it under the terms of  the GNU General Public License as published
24
// by the Free Software Foundation, either version 3 of the License, or (at
25
// your option) any later version.
26
//
27
// This program is distributed in the hope that it will be useful, but WITHOUT
28
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
29
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
30
// for more details.
31
//
32
// You should have received a copy of the GNU General Public License along
33 41 dgisselq
// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no
34 7 dgisselq
// target there if the PDF file isn't present.)  If not, see
35
// <http://www.gnu.org/licenses/> for a copy.
36
//
37
// License:     GPL, v3, as defined and found on www.gnu.org,
38
//              http://www.gnu.org/licenses/gpl.html
39
//
40
//
41 41 dgisselq
////////////////////////////////////////////////////////////////////////////////
42 7 dgisselq
#include <stdio.h>
43 36 dgisselq
#include <stdlib.h>
44 9 dgisselq
#include <math.h>
45
#include <fftw3.h>
46 7 dgisselq
 
47
#include "verilated.h"
48 36 dgisselq
#include "verilated_vcd_c.h"
49 7 dgisselq
#include "Vfftmain.h"
50 23 dgisselq
#include "twoc.h"
51 7 dgisselq
 
52 28 dgisselq
#include "fftsize.h"
53 7 dgisselq
 
54 35 dgisselq
 
55
#ifdef  NEW_VERILATOR
56
#define VVAR(A) fftmain__DOT_ ## A
57
#else
58
#define VVAR(A) v__DOT_ ## A
59
#endif
60
 
61 36 dgisselq
#ifdef  DBLCLKFFT
62 35 dgisselq
#define revstage_iaddr  VVAR(_revstage__DOT__iaddr)
63 36 dgisselq
#else
64
#define revstage_iaddr  VVAR(_revstage__DOT__wraddr)
65
#endif
66 35 dgisselq
#define br_sync         VVAR(_br_sync)
67
#define br_started      VVAR(_r_br_started)
68
#define w_s2048         VVAR(_w_s2048)
69
#define w_s1024         VVAR(_w_s1024)
70
#define w_s512          VVAR(_w_s512)
71
#define w_s256          VVAR(_w_s256)
72
#define w_s128          VVAR(_w_s128)
73
#define w_s64           VVAR(_w_s64)
74
#define w_s32           VVAR(_w_s32)
75
#define w_s16           VVAR(_w_s16)
76
#define w_s8            VVAR(_w_s8)
77
#define w_s4            VVAR(_w_s4)
78
 
79
 
80 28 dgisselq
#define IWIDTH  FFT_IWIDTH
81
#define OWIDTH  FFT_OWIDTH
82
#define LGWIDTH FFT_LGWIDTH
83
 
84
#if (IWIDTH > 16)
85
typedef unsigned long   ITYP;
86
#else
87
typedef unsigned int    ITYP;
88
#endif
89
 
90
#if (OWIDTH > 16)
91
typedef unsigned long   OTYP;
92
#else
93
typedef unsigned int    OTYP;
94
#endif
95
 
96
#define NFTLOG  16
97 7 dgisselq
#define FFTLEN  (1<<LGWIDTH)
98
 
99 28 dgisselq
#ifdef  FFT_SKIPS_BIT_REVERSE
100
#define APPLY_BITREVERSE_LOCALLY
101
#endif
102
 
103 26 dgisselq
unsigned long bitrev(const int nbits, const unsigned long vl) {
104
        unsigned long   r = 0;
105
        unsigned long   val = vl;
106
 
107
        for(int k=0; k<nbits; k++) {
108
                r<<= 1;
109
                r |= (val & 1);
110
                val >>= 1;
111
        }
112
 
113
        return r;
114
}
115
 
116 7 dgisselq
class   FFT_TB {
117
public:
118
        Vfftmain        *m_fft;
119 28 dgisselq
        OTYP            m_data[FFTLEN];
120
        ITYP            m_log[NFTLOG*FFTLEN];
121 26 dgisselq
        int             m_iaddr, m_oaddr, m_ntest, m_logbase;
122 7 dgisselq
        FILE            *m_dumpfp;
123 9 dgisselq
        fftw_plan       m_plan;
124
        double          *m_fft_buf;
125
        bool            m_syncd;
126 28 dgisselq
        unsigned long   m_tickcount;
127 36 dgisselq
        VerilatedVcdC*  m_trace;
128 7 dgisselq
 
129
        FFT_TB(void) {
130
                m_fft = new Vfftmain;
131 36 dgisselq
                Verilated::traceEverOn(true);
132 9 dgisselq
                m_iaddr = m_oaddr = 0;
133 7 dgisselq
                m_dumpfp = NULL;
134 9 dgisselq
 
135
                m_fft_buf = (double *)fftw_malloc(sizeof(fftw_complex)*(FFTLEN));
136
                m_plan = fftw_plan_dft_1d(FFTLEN, (fftw_complex *)m_fft_buf,
137
                                (fftw_complex *)m_fft_buf,
138
                                FFTW_FORWARD, FFTW_MEASURE);
139
                m_syncd = false;
140
                m_ntest = 0;
141 36 dgisselq
        }
142 28 dgisselq
 
143 36 dgisselq
        ~FFT_TB(void) {
144
                closetrace();
145
                delete m_fft;
146
                m_fft = NULL;
147 7 dgisselq
        }
148
 
149 36 dgisselq
        virtual void opentrace(const char *vcdname) {
150
                if (!m_trace) {
151
                        m_trace = new VerilatedVcdC;
152
                        m_fft->trace(m_trace, 99);
153
                        m_trace->open(vcdname);
154
                }
155
        }
156
 
157
        virtual void closetrace(void) {
158
                if (m_trace) {
159
                        m_trace->close();
160
                        delete m_trace;
161
                        m_trace = NULL;
162
                }
163
        }
164
 
165 7 dgisselq
        void    tick(void) {
166 36 dgisselq
                m_tickcount++;
167
                if (m_fft->i_reset)
168 28 dgisselq
                        printf("TICK(%s,%s)\n",
169 36 dgisselq
                                (m_fft->i_reset)?"RST":"   ",
170 28 dgisselq
                                (m_fft->i_ce)?"CE":"  ");
171 36 dgisselq
 
172 7 dgisselq
                m_fft->i_clk = 0;
173
                m_fft->eval();
174 36 dgisselq
                if (m_trace)
175
                        m_trace->dump((vluint64_t)(10*m_tickcount-2));
176 7 dgisselq
                m_fft->i_clk = 1;
177
                m_fft->eval();
178 36 dgisselq
                if (m_trace)
179
                        m_trace->dump((vluint64_t)(10*m_tickcount));
180
                m_fft->i_clk = 0;
181
                m_fft->eval();
182
                if (m_trace) {
183
                        m_trace->dump((vluint64_t)(10*m_tickcount+5));
184
                        m_trace->flush();
185
                }
186
        }
187 26 dgisselq
 
188 36 dgisselq
        void    cetick(void) {
189
                int     ce = m_fft->i_ce, nkce;
190
                tick();
191 28 dgisselq
 
192 36 dgisselq
                nkce = (rand()&1);
193
#ifdef  FFT_CKPCE
194
                nkce += FFT_CKPCE;
195
#endif
196
                if ((ce)&&(nkce>0)) {
197
                        m_fft->i_ce = 0;
198
                        for(int kce=1; kce < nkce; kce++)
199
                                tick();
200 26 dgisselq
                }
201 36 dgisselq
 
202
                m_fft->i_ce = ce;
203 7 dgisselq
        }
204
 
205
        void    reset(void) {
206
                m_fft->i_ce  = 0;
207 36 dgisselq
                m_fft->i_reset = 1;
208 7 dgisselq
                tick();
209 36 dgisselq
                m_fft->i_reset = 0;
210 7 dgisselq
                tick();
211 9 dgisselq
 
212 26 dgisselq
                m_iaddr = m_oaddr = m_logbase = 0;
213 9 dgisselq
                m_syncd = false;
214 28 dgisselq
                m_tickcount = 0l;
215 7 dgisselq
        }
216
 
217 9 dgisselq
        long    twos_complement(const long val, const int bits) {
218 23 dgisselq
                return sbits(val, bits);
219 9 dgisselq
        }
220
 
221
        void    checkresults(void) {
222
                double  *dp, *sp; // Complex array
223
                double  vout[FFTLEN*2];
224
                double  isq=0.0, osq = 0.0;
225 28 dgisselq
                ITYP    *lp;
226 9 dgisselq
 
227
                // Fill up our test array from the log array
228 26 dgisselq
                printf("%3d : CHECK: %8d %5x m_log[-%x=%x]\n", m_ntest, m_iaddr, m_iaddr,
229
                        m_logbase, (m_iaddr-m_logbase)&((NFTLOG*FFTLEN-1)&(-FFTLEN)));
230 28 dgisselq
 
231
                // Convert our logged data into doubles, in an FFT buffer
232 26 dgisselq
                dp = m_fft_buf; lp = &m_log[(m_iaddr-m_logbase)&((NFTLOG*FFTLEN-1)&(-FFTLEN))];
233 9 dgisselq
                for(int i=0; i<FFTLEN; i++) {
234 28 dgisselq
                        ITYP    tv = *lp++;
235 9 dgisselq
 
236 28 dgisselq
                        dp[0] = sbits((long)tv >> IWIDTH, IWIDTH);
237
                        dp[1] = sbits((long)tv, IWIDTH);
238 9 dgisselq
 
239 16 dgisselq
                        // printf("IN[%4d = %4x] = %9.1f %9.1f\n",
240
                                // i+((m_iaddr-FFTLEN*3)&((4*FFTLEN-1)&(-FFTLEN))),
241
                                // i+((m_iaddr-FFTLEN*3)&((4*FFTLEN-1)&(-FFTLEN))),
242
                                // dp[0], dp[1]);
243 9 dgisselq
                        dp += 2;
244
                }
245
 
246
                // Let's measure ... are we the zero vector?  If not, how close?
247
                dp = m_fft_buf;
248 26 dgisselq
                for(int i=0; i<FFTLEN*2; i++) {
249
                        isq += (*dp) * (*dp); dp++;
250
                }
251 9 dgisselq
 
252
                fftw_execute(m_plan);
253
 
254 28 dgisselq
                // Let's load up the output we received into double valued
255
                // array vout
256 9 dgisselq
                dp = vout;
257
                for(int i=0; i<FFTLEN; i++) {
258 26 dgisselq
                        *dp = rdata(i);
259 9 dgisselq
                        osq += (*dp) * (*dp); dp++;
260 26 dgisselq
                        *dp = idata(i);
261 9 dgisselq
                        osq += (*dp) * (*dp); dp++;
262
                }
263
 
264
 
265
                // Let's figure out if there's a scale factor difference ...
266
                double  scale = 0.0, wt = 0.0;
267
                sp = m_fft_buf;  dp = vout;
268
                for(int i=0; i<FFTLEN*2; i++) {
269
                        scale += (*sp) * (*dp++);
270
                        wt += (*sp) * (*sp); sp++;
271
                } scale = scale / wt;
272
 
273 28 dgisselq
                if (fabs(scale) <= 1./4./FFTLEN)
274
                        scale = 2./(FFTLEN);
275
                else if (wt == 0.0) scale = 1.0;
276 9 dgisselq
 
277
                double xisq = 0.0;
278
                sp = m_fft_buf;  dp = vout;
279 26 dgisselq
 
280
                if ((true)&&(m_dumpfp)) {
281
                        double  tmp[FFTLEN*2], nscl;
282
 
283
                        if (fabs(scale) < 1e-4)
284
                                nscl = 1.0;
285
                        else
286
                                nscl = scale;
287
                        for(int i=0; i<FFTLEN*2; i++)
288
                                tmp[i] = m_fft_buf[i] * nscl;
289
                        fwrite(tmp, sizeof(double), FFTLEN*2, m_dumpfp);
290
                }
291
 
292 9 dgisselq
                for(int i=0; i<FFTLEN*2; i++) {
293
                        double vl = (*sp++) * scale - (*dp++);
294
                        xisq += vl * vl;
295
                }
296
 
297
                printf("%3d : SCALE = %12.6f, WT = %18.1f, ISQ = %15.1f, ",
298
                        m_ntest, scale, wt, isq);
299
                printf("OSQ = %18.1f, ", osq);
300 36 dgisselq
                printf("XISQ = %18.1f, sqrt = %9.2f\n", xisq, sqrt(xisq));
301 19 dgisselq
                if (xisq > 1.4 * FFTLEN/2) {
302 16 dgisselq
                        printf("TEST FAIL!!  Result is out of bounds from ");
303
                        printf("expected result with FFTW3.\n");
304 36 dgisselq
                        // exit(EXIT_FAILURE);
305 16 dgisselq
                }
306 9 dgisselq
                m_ntest++;
307
        }
308
 
309 36 dgisselq
#ifdef  DBLCLKFFT
310 28 dgisselq
        bool    test(ITYP lft, ITYP rht) {
311 7 dgisselq
                m_fft->i_ce    = 1;
312 36 dgisselq
                m_fft->i_reset = 0;
313 7 dgisselq
                m_fft->i_left  = lft;
314
                m_fft->i_right = rht;
315
 
316 28 dgisselq
                m_log[(m_iaddr++)&(NFTLOG*FFTLEN-1)] = lft;
317
                m_log[(m_iaddr++)&(NFTLOG*FFTLEN-1)] = rht;
318 9 dgisselq
 
319 36 dgisselq
                cetick();
320 7 dgisselq
 
321
                if (m_fft->o_sync) {
322 26 dgisselq
                        if (!m_syncd) {
323 28 dgisselq
                                m_syncd = true;
324
                                printf("ORIGINAL SYNC AT 0x%lx, m_oaddr set to 0x%x\n", m_tickcount, m_oaddr);
325 26 dgisselq
                                m_logbase = m_iaddr;
326 28 dgisselq
                        } else printf("RESYNC AT %lx\n", m_tickcount);
327 9 dgisselq
                        m_oaddr &= (-1<<LGWIDTH);
328
                } else m_oaddr += 2;
329 7 dgisselq
 
330 28 dgisselq
                printf("%8x,%5d: %08x,%08x -> %011lx,%011lx\t",
331 26 dgisselq
                        m_iaddr, m_oaddr,
332
                        lft, rht, m_fft->o_left, m_fft->o_right);
333 28 dgisselq
 
334
#ifndef APPLY_BITREVERSE_LOCALLY
335 35 dgisselq
                printf(" [%3x]%s", m_fft->revstage_iaddr,
336
                        (m_fft->br_sync)?"S"
337
                                :((m_fft->br_started)?".":"x"));
338 28 dgisselq
#endif
339
 
340
                printf(" ");
341
#if (FFT_SIZE>=2048)
342 35 dgisselq
                printf("%s", (m_fft->w_s2048)?"S":"-");
343 28 dgisselq
#endif
344
#if (FFT_SIZE>1024)
345 35 dgisselq
                printf("%s", (m_fft->w_s1024)?"S":"-");
346 28 dgisselq
#endif
347
#if (FFT_SIZE>512)
348 35 dgisselq
                printf("%s", (m_fft->w_s512)?"S":"-");
349 28 dgisselq
#endif
350
#if (FFT_SIZE>256)
351 35 dgisselq
                printf("%s", (m_fft->w_s256)?"S":"-");
352 28 dgisselq
#endif
353
#if (FFT_SIZE>128)
354 35 dgisselq
                printf("%s", (m_fft->w_s128)?"S":"-");
355 28 dgisselq
#endif
356
#if (FFT_SIZE>64)
357 35 dgisselq
                printf("%s", (m_fft->w_s64)?"S":"-");
358 28 dgisselq
#endif
359
#if (FFT_SIZE>32)
360 35 dgisselq
                printf("%s", (m_fft->w_s32)?"S":"-");
361 28 dgisselq
#endif
362
#if (FFT_SIZE>16)
363 35 dgisselq
                printf("%s", (m_fft->w_s16)?"S":"-");
364 28 dgisselq
#endif
365
#if (FFT_SIZE>8)
366 35 dgisselq
                printf("%s", (m_fft->w_s8)?"S":"-");
367 28 dgisselq
#endif
368
#if (FFT_SIZE>4)
369 35 dgisselq
                printf("%s", (m_fft->w_s4)?"S":"-");
370 28 dgisselq
#endif
371
 
372
                printf(" %s%s\n",
373 9 dgisselq
                        (m_fft->o_sync)?"\t(SYNC!)":"",
374
                        (m_fft->o_left | m_fft->o_right)?"  (NZ)":"");
375 7 dgisselq
 
376 9 dgisselq
                m_data[(m_oaddr  )&(FFTLEN-1)] = m_fft->o_left;
377
                m_data[(m_oaddr+1)&(FFTLEN-1)] = m_fft->o_right;
378 7 dgisselq
 
379 9 dgisselq
                if ((m_syncd)&&((m_oaddr&(FFTLEN-1)) == FFTLEN-2)) {
380 7 dgisselq
                        dumpwrite();
381 9 dgisselq
                        checkresults();
382
                }
383 7 dgisselq
 
384
                return (m_fft->o_sync);
385
        }
386 36 dgisselq
#else
387
        bool    test(ITYP data) {
388
                m_fft->i_ce    = 1;
389
                m_fft->i_reset = 0;
390
                m_fft->i_sample  = data;
391 7 dgisselq
 
392 36 dgisselq
                m_log[(m_iaddr++)&(NFTLOG*FFTLEN-1)] = data;
393
 
394
                cetick();
395
 
396
                if (m_fft->o_sync) {
397
                        if (!m_syncd) {
398
                                m_syncd = true;
399
                                printf("ORIGINAL SYNC AT 0x%lx, m_oaddr set to 0x%x\n", m_tickcount, m_oaddr);
400
                                m_logbase = m_iaddr;
401
                        } else printf("RESYNC AT %lx\n", m_tickcount);
402
                        m_oaddr &= (-1<<LGWIDTH);
403
                } else m_oaddr += 1;
404
 
405
                printf("%8x,%5d: %08x -> %011lx\t",
406
                        m_iaddr, m_oaddr, data, m_fft->o_result);
407
 
408
#ifndef APPLY_BITREVERSE_LOCALLY
409
                printf(" [%3x]%s", m_fft->revstage_iaddr,
410
                        (m_fft->br_sync)?"S"
411
                                :((m_fft->br_started)?".":"x"));
412
#endif
413
 
414
                printf(" ");
415
#if (FFT_SIZE>=2048)
416
                printf("%s", (m_fft->w_s2048)?"S":"-");
417
#endif
418
#if (FFT_SIZE>1024)
419
                printf("%s", (m_fft->w_s1024)?"S":"-");
420
#endif
421
#if (FFT_SIZE>512)
422
                printf("%s", (m_fft->w_s512)?"S":"-");
423
#endif
424
#if (FFT_SIZE>256)
425
                printf("%s", (m_fft->w_s256)?"S":"-");
426
#endif
427
#if (FFT_SIZE>128)
428
                printf("%s", (m_fft->w_s128)?"S":"-");
429
#endif
430
#if (FFT_SIZE>64)
431
                printf("%s", (m_fft->w_s64)?"S":"-");
432
#endif
433
#if (FFT_SIZE>32)
434
                printf("%s", (m_fft->w_s32)?"S":"-");
435
#endif
436
#if (FFT_SIZE>16)
437
                printf("%s", (m_fft->w_s16)?"S":"-");
438
#endif
439
#if (FFT_SIZE>8)
440
                printf("%s", (m_fft->w_s8)?"S":"-");
441
#endif
442
#if (FFT_SIZE>4)
443
                printf("%s", (m_fft->w_s4)?"S":"-");
444
#endif
445
 
446
                printf(" %s%s\n",
447
                        (m_fft->o_sync)?"\t(SYNC!)":"",
448
                        (m_fft->o_result)?"  (NZ)":"");
449
 
450
                m_data[(m_oaddr  )&(FFTLEN-1)] = m_fft->o_result;
451
 
452
                if ((m_syncd)&&((m_oaddr&(FFTLEN-1)) == FFTLEN-1)) {
453
                        dumpwrite();
454
                        checkresults();
455
                }
456
 
457
                return (m_fft->o_sync);
458
        }
459
#endif
460
 
461 7 dgisselq
        bool    test(double lft_r, double lft_i, double rht_r, double rht_i) {
462 28 dgisselq
                ITYP    ilft, irht, ilft_r, ilft_i, irht_r, irht_i;
463 7 dgisselq
 
464 28 dgisselq
                ilft_r = (ITYP)(lft_r) & ((1<<IWIDTH)-1);
465
                ilft_i = (ITYP)(lft_i) & ((1<<IWIDTH)-1);
466
                irht_r = (ITYP)(rht_r) & ((1<<IWIDTH)-1);
467
                irht_i = (ITYP)(rht_i) & ((1<<IWIDTH)-1);
468 7 dgisselq
 
469
                ilft = (ilft_r << IWIDTH) | ilft_i;
470
                irht = (irht_r << IWIDTH) | irht_i;
471
 
472 36 dgisselq
#ifdef  DBLCLKFFT
473 7 dgisselq
                return test(ilft, irht);
474 36 dgisselq
#else
475
                test(ilft);
476
                return test(irht);
477
#endif
478 7 dgisselq
        }
479
 
480
        double  rdata(int addr) {
481 26 dgisselq
                int     index = addr & (FFTLEN-1);
482
 
483 28 dgisselq
#ifdef  APPLY_BITREVERSE_LOCALLY
484
                index = bitrev(LGWIDTH, index);
485
#endif
486 26 dgisselq
                return (double)sbits(m_data[index]>>OWIDTH, OWIDTH);
487 7 dgisselq
        }
488
 
489
        double  idata(int addr) {
490 26 dgisselq
                int     index = addr & (FFTLEN-1);
491
 
492 28 dgisselq
#ifdef  APPLY_BITREVERSE_LOCALLY
493
                index = bitrev(LGWIDTH, index);
494
#endif
495 26 dgisselq
                return (double)sbits(m_data[index], OWIDTH);
496 7 dgisselq
        }
497
 
498
        void    dump(FILE *fp) {
499
                m_dumpfp = fp;
500
        }
501
 
502
        void    dumpwrite(void) {
503
                if (!m_dumpfp)
504
                        return;
505
 
506
                double  *buf;
507
 
508
                buf = new double[FFTLEN * 2];
509
                for(int i=0; i<FFTLEN; i++) {
510
                        buf[i*2] = rdata(i);
511
                        buf[i*2+1] = idata(i);
512
                }
513
 
514
                fwrite(buf, sizeof(double), FFTLEN*2, m_dumpfp);
515
                delete[] buf;
516
        }
517
};
518
 
519 9 dgisselq
 
520 7 dgisselq
int     main(int argc, char **argv, char **envp) {
521
        Verilated::commandArgs(argc, argv);
522
        FFT_TB *fft = new FFT_TB;
523
        FILE    *fpout;
524
 
525
        fpout = fopen("fft_tb.dbl", "w");
526
        if (NULL == fpout) {
527
                fprintf(stderr, "Cannot write output file, fft_tb.dbl\n");
528
                exit(-1);
529
        }
530
 
531 36 dgisselq
        fft->opentrace("fft.vcd");
532 7 dgisselq
        fft->reset();
533 28 dgisselq
 
534
        {
535
                int     ftlen = FFTLEN;
536
                fwrite(&ftlen, 1, sizeof(int), fpout);
537
        }
538 7 dgisselq
        fft->dump(fpout);
539
 
540 26 dgisselq
        // 1.
541 36 dgisselq
        double  maxv = ((1l<<(IWIDTH-1))-1l);
542
        fft->test(0.0, 0.0, maxv, 0.0);
543 26 dgisselq
        for(int k=0; k<FFTLEN/2-1; k++)
544
                fft->test(0.0,0.0,0.0,0.0);
545
 
546 28 dgisselq
        // 2. Try placing a pulse at the very end location
547
        for(int k=0; k<FFTLEN/2; k++) {
548
                double cl, cr, sl, sr, W;
549
                W = - 2.0 * M_PI / FFTLEN * (1);
550 36 dgisselq
                cl = cos(W * (2*k  )) * (double)((1l<<(IWIDTH-2))-1l);
551
                sl = sin(W * (2*k  )) * (double)((1l<<(IWIDTH-2))-1l);
552
                cr = cos(W * (2*k+1)) * (double)((1l<<(IWIDTH-2))-1l);
553
                sr = sin(W * (2*k+1)) * (double)((1l<<(IWIDTH-2))-1l);
554 28 dgisselq
                fft->test(cl, sl, cr, sr);
555
        }
556
 
557 26 dgisselq
        // 2. 
558 36 dgisselq
        fft->test(maxv, 0.0, maxv, 0.0);
559 26 dgisselq
        for(int k=0; k<FFTLEN/2-1; k++)
560
                fft->test(0.0,0.0,0.0,0.0);
561
 
562
        // 3. 
563
        fft->test(0.0,0.0,0.0,0.0);
564 36 dgisselq
        fft->test(maxv, 0.0, 0.0, 0.0);
565 26 dgisselq
        for(int k=0; k<FFTLEN/2-1; k++)
566
                fft->test(0.0,0.0,0.0,0.0);
567
 
568
        // 4.
569
        for(int k=0; k<8; k++)
570 36 dgisselq
                fft->test(maxv, 0.0, maxv, 0.0);
571 26 dgisselq
        for(int k=8; k<FFTLEN/2; k++)
572
                fft->test(0.0,0.0,0.0,0.0);
573
 
574
        // 5.
575
        if (FFTLEN/2 >= 16) {
576
                for(int k=0; k<16; k++)
577 36 dgisselq
                        fft->test(maxv, 0.0, maxv, 0.0);
578 26 dgisselq
                for(int k=16; k<FFTLEN/2; k++)
579
                        fft->test(0.0,0.0,0.0,0.0);
580
        }
581
 
582
        // 6.
583
        if (FFTLEN/2 >= 32) {
584
                for(int k=0; k<32; k++)
585 36 dgisselq
                        fft->test(maxv, 0.0, maxv, 0.0);
586 26 dgisselq
                for(int k=32; k<FFTLEN/2; k++)
587
                        fft->test(0.0,0.0,0.0,0.0);
588
        }
589
 
590
        // 7.
591
        if (FFTLEN/2 >= 64) {
592
                for(int k=0; k<64; k++)
593 36 dgisselq
                        fft->test(maxv, 0.0, maxv, 0.0);
594 26 dgisselq
                for(int k=64; k<FFTLEN/2; k++)
595
                        fft->test(0.0,0.0,0.0,0.0);
596
        }
597
 
598
        if (FFTLEN/2 >= 128) {
599
                for(int k=0; k<128; k++)
600 36 dgisselq
                        fft->test(maxv, 0.0, maxv, 0.0);
601 26 dgisselq
                for(int k=128; k<FFTLEN/2; k++)
602
                        fft->test(0.0,0.0,0.0,0.0);
603
        }
604
 
605
        if (FFTLEN/2 >= 256) {
606
                for(int k=0; k<256; k++)
607 36 dgisselq
                        fft->test(maxv, 0.0, maxv, 0.0);
608 26 dgisselq
                for(int k=256; k<FFTLEN/2; k++)
609
                        fft->test(0.0,0.0,0.0,0.0);
610
        }
611
 
612
        if (FFTLEN/2 >= 512) {
613
                for(int k=0; k<256+128; k++)
614 36 dgisselq
                        fft->test(maxv, 0.0, maxv, 0.0);
615 26 dgisselq
                for(int k=256+128; k<FFTLEN/2; k++)
616
                        fft->test(0.0,0.0,0.0,0.0);
617
        }
618
 
619
        /*
620
        for(int k=0; k<FFTLEN/2; k++)
621
                fft->test(0.0,0.0,0.0,0.0);
622
 
623
        for(int k=0; k<FFTLEN/2; k++)
624
                fft->test(0.0,0.0,0.0,0.0);
625
 
626
        for(int k=0; k<FFTLEN/2; k++)
627
                fft->test(0.0,0.0,0.0,0.0);
628
 
629
        for(int k=0; k<FFTLEN/2; k++)
630
                fft->test(0.0,0.0,0.0,0.0);
631
 
632
        for(int k=0; k<FFTLEN/2; k++)
633
                fft->test(0.0,0.0,0.0,0.0);
634
 
635
        for(int k=0; k<FFTLEN/2; k++)
636
                fft->test(0.0,0.0,0.0,0.0);
637
        */
638
 
639
#ifndef NO_JUNK
640
        // 7.
641
 
642 9 dgisselq
        //     1 -> 0x0001 
643
        //     2 -> 0x0002 
644
        //     4 -> 0x0004 
645
        //     8 -> 0x0008 
646
        //    16 -> 0x0010 
647
        //    32 -> 0x0020 
648
        //    64 -> 0x0040 
649
        //   128 -> 0x0080 
650
        //   256 -> 0x0100 
651
        //   512 -> 0x0200 
652
        //  1024 -> 0x0400 
653
        //  2048 -> 0x0800
654
        //  4096 -> 0x1000
655
        //  8192 -> 0x2000
656
        // 16384 -> 0x4000
657
        for(int v=1; v<32768; v<<=1) for(int k=0; k<FFTLEN/2; k++)
658
                fft->test((double)v,0.0,(double)v,0.0);
659
        //     1 -> 0xffff      
660
        //     2 -> 0xfffe
661
        //     4 -> 0xfffc
662
        //     8 -> 0xfff8
663
        //    16 -> 0xfff0
664
        //    32 -> 0xffe0
665
        //    64 -> 0xffc0
666
        //   128 -> 0xff80
667
        //   256 -> 0xff00
668
        //   512 -> 0xfe00
669
        //  1024 -> 0xfc00
670
        //  2048 -> 0xf800
671
        //  4096 -> 0xf000
672
        //  8192 -> 0xe000
673
        // 16384 -> 0xc000
674
        // 32768 -> 0x8000
675 26 dgisselq
        fft->test(0.0,0.0,16384.0,0.0);
676
        for(int k=0; k<FFTLEN/2-1; k++)
677
                fft->test(0.0,0.0,0.0,0.0);
678
 
679 9 dgisselq
        for(int v=1; v<=32768; v<<=1) for(int k=0; k<FFTLEN/2; k++)
680
                fft->test(-(double)v,0.0,-(double)v,0.0);
681
        //     1 -> 0x000040    CORRECT!!
682
        //     2 -> 0x000080 
683
        //     4 -> 0x000100 
684
        //     8 -> 0x000200
685
        //    16 -> 0x000400
686
        //    32 -> 0x000800
687
        //    64 -> 0x001000
688
        //   128 -> 0x002000
689
        //   256 -> 0x004000
690
        //   512 -> 0x008000
691
        //  1024 -> 0x010000
692
        //  2048 -> 0x020000
693
        //  4096 -> 0x040000
694
        //  8192 -> 0x080000
695
        // 16384 -> 0x100000
696
        for(int v=1; v<32768; v<<=1) for(int k=0; k<FFTLEN/2; k++)
697
                fft->test(0.0,(double)v,0.0,(double)v);
698
        //     1 -> 0x3fffc0
699
        //     2 -> 0x3fff80
700
        //     4 -> 0x3fff00
701
        //     8 -> 0x3ffe00
702
        //    16 -> 0x3ffc00
703
        //    32 -> 0x3ff800
704
        //    64 -> 0x3ff000
705
        //   128 -> 0x3fe000
706
        //   256 -> 0x3fc000
707
        //   512 -> 0x3f8000
708
        //  1024 -> 0x3f0000
709
        //  2048 -> 0x3e0000
710
        //  4096 -> 0x3c0000
711
        //  8192 -> 0x380000
712
        // 16384 -> 0x300000
713
        for(int v=1; v<32768; v<<=1) for(int k=0; k<FFTLEN/2; k++)
714
                fft->test(0.0,-(double)v,0.0,-(double)v);
715
 
716
        // 61. Now, how about the smallest alternating real signal
717 7 dgisselq
        for(int k=0; k<FFTLEN/2; k++)
718 9 dgisselq
                fft->test(2.0,0.0,0.0,0.0); // Don't forget to expect a bias!
719
        // 62. Now, how about the smallest alternating imaginary signal
720 7 dgisselq
        for(int k=0; k<FFTLEN/2; k++)
721 9 dgisselq
                fft->test(0.0,2.0,0.0,0.0); // Don't forget to expect a bias!
722
        // 63. Now, how about the smallest alternating real signal,2nd phase
723 7 dgisselq
        for(int k=0; k<FFTLEN/2; k++)
724 9 dgisselq
                fft->test(0.0,0.0,2.0,0.0); // Don't forget to expect a bias!
725
        // 64.Now, how about the smallest alternating imaginary signal,2nd phase
726 7 dgisselq
        for(int k=0; k<FFTLEN/2; k++)
727 9 dgisselq
                fft->test(0.0,0.0,0.0,2.0); // Don't forget to expect a bias!
728
 
729
        // 65.
730 7 dgisselq
        for(int k=0; k<FFTLEN/2; k++)
731 36 dgisselq
                fft->test(maxv,0.0,-maxv,0.0);
732 9 dgisselq
        // 66.
733 7 dgisselq
        for(int k=0; k<FFTLEN/2; k++)
734 36 dgisselq
                fft->test(0.0,-maxv,0.0,maxv);
735 9 dgisselq
        // 67.
736 7 dgisselq
        for(int k=0; k<FFTLEN/2; k++)
737 36 dgisselq
                fft->test(-maxv,-maxv,-maxv,-maxv);
738 9 dgisselq
        // 68.
739 7 dgisselq
        for(int k=0; k<FFTLEN/2; k++)
740 36 dgisselq
                fft->test(0.0,-maxv,0.0,maxv);
741 9 dgisselq
        // 69.
742 7 dgisselq
        for(int k=0; k<FFTLEN/2; k++)
743 36 dgisselq
                fft->test(0.0,maxv,0.0,-maxv);
744 9 dgisselq
        // 70. 
745
        for(int k=0; k<FFTLEN/2; k++)
746 36 dgisselq
                fft->test(-maxv,-maxv,-maxv,-maxv);
747 7 dgisselq
 
748 9 dgisselq
        // 71. Now let's go for an impulse (SUCCESS)
749
        fft->test(16384.0, 0.0, 0.0, 0.0);
750
        for(int k=0; k<FFTLEN/2-1; k++)
751 7 dgisselq
                fft->test(0.0,0.0,0.0,0.0);
752
 
753 9 dgisselq
        // 72. And another one on the next clock (FAILS, ugly)
754
        fft->test(0.0, 0.0, 16384.0, 0.0);
755
        for(int k=0; k<FFTLEN/2-1; k++)
756
                fft->test(0.0,0.0,0.0,0.0);
757 7 dgisselq
 
758 26 dgisselq
        // 72. And another one on the next clock (FAILS, ugly)
759
        fft->test(0.0, 0.0,  8192.0, 0.0);
760
        for(int k=0; k<FFTLEN/2-1; k++)
761
                fft->test(0.0,0.0,0.0,0.0);
762
 
763
        // 72. And another one on the next clock (FAILS, ugly)
764
        fft->test(0.0, 0.0,   512.0, 0.0);
765
        for(int k=0; k<FFTLEN/2-1; k++)
766
                fft->test(0.0,0.0,0.0,0.0);
767
 
768 9 dgisselq
        // 73. And an imaginary one on the second clock
769
        fft->test(0.0, 0.0, 0.0, 16384.0);
770
        for(int k=0; k<FFTLEN/2-1; k++)
771
                fft->test(0.0,0.0,0.0,0.0);
772 7 dgisselq
 
773 9 dgisselq
        // 74. Likewise the next clock
774
        fft->test(0.0,0.0,0.0,0.0);
775
        fft->test(16384.0, 0.0, 0.0, 0.0);
776
        for(int k=0; k<FFTLEN/2-2; k++)
777
                fft->test(0.0,0.0,0.0,0.0);
778 7 dgisselq
 
779 9 dgisselq
        // 75. And it's imaginary counterpart
780
        fft->test(0.0,0.0,0.0,0.0);
781
        fft->test(0.0, 16384.0, 0.0, 0.0);
782
        for(int k=0; k<FFTLEN/2-2; k++)
783
                fft->test(0.0,0.0,0.0,0.0);
784
 
785
        // 76. Likewise the next clock
786
        fft->test(0.0,0.0,0.0,0.0);
787
        fft->test(0.0, 0.0, 16384.0, 0.0);
788
        for(int k=0; k<FFTLEN/2-2; k++)
789
                fft->test(0.0,0.0,0.0,0.0);
790
 
791
        // 77. And it's imaginary counterpart
792
        fft->test(0.0,0.0,0.0,0.0);
793
        fft->test(0.0, 0.0, 0.0, 16384.0);
794
        for(int k=0; k<FFTLEN/2-2; k++)
795
                fft->test(0.0,0.0,0.0,0.0);
796
 
797
 
798
        // 78. Now let's try some exponentials
799
        for(int k=0; k<FFTLEN/2; k++) {
800
                double cl, cr, sl, sr, W;
801
                W = - 2.0 * M_PI / FFTLEN;
802
                cl = cos(W * (2*k  )) * 16383.0;
803
                sl = sin(W * (2*k  )) * 16383.0;
804
                cr = cos(W * (2*k+1)) * 16383.0;
805
                sr = sin(W * (2*k+1)) * 16383.0;
806
                fft->test(cl, sl, cr, sr);
807
        }
808
 
809
        // 72.
810
        for(int k=0; k<FFTLEN/2; k++) {
811
                double cl, cr, sl, sr, W;
812
                W = - 2.0 * M_PI / FFTLEN * 5;
813
                cl = cos(W * (2*k  )) * 16383.0;
814
                sl = sin(W * (2*k  )) * 16383.0;
815
                cr = cos(W * (2*k+1)) * 16383.0;
816
                sr = sin(W * (2*k+1)) * 16383.0;
817
                fft->test(cl, sl, cr, sr);
818
        }
819
 
820
        // 73.
821
        for(int k=0; k<FFTLEN/2; k++) {
822
                double cl, cr, sl, sr, W;
823
                W = - 2.0 * M_PI / FFTLEN * 8;
824
                cl = cos(W * (2*k  )) * 8190.0;
825
                sl = sin(W * (2*k  )) * 8190.0;
826
                cr = cos(W * (2*k+1)) * 8190.0;
827
                sr = sin(W * (2*k+1)) * 8190.0;
828
                fft->test(cl, sl, cr, sr);
829
        }
830
 
831
        // 74.
832
        for(int k=0; k<FFTLEN/2; k++) {
833
                double cl, cr, sl, sr, W;
834
                W = - 2.0 * M_PI / FFTLEN * 25;
835
                cl = cos(W * (2*k  )) * 4.0;
836
                sl = sin(W * (2*k  )) * 4.0;
837
                cr = cos(W * (2*k+1)) * 4.0;
838
                sr = sin(W * (2*k+1)) * 4.0;
839
                fft->test(cl, sl, cr, sr);
840
        }
841 26 dgisselq
#endif
842 9 dgisselq
        // 19.--24. And finally, let's clear out our results / buffer
843
        for(int k=0; k<(FFTLEN/2) * 5; k++)
844
                fft->test(0.0,0.0,0.0,0.0);
845
 
846
 
847
 
848 7 dgisselq
        fclose(fpout);
849 16 dgisselq
 
850 36 dgisselq
        if (!fft->m_syncd) {
851
                printf("FAIL -- NO SYNC\n");
852
                goto test_failure;
853
        }
854
 
855 16 dgisselq
        printf("SUCCESS!!\n");
856
        exit(0);
857 36 dgisselq
test_failure:
858
        printf("TEST FAILED!!\n");
859
        exit(0);
860 7 dgisselq
}
861
 
862 9 dgisselq
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.