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

Subversion Repositories dblclockfft

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

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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