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

Subversion Repositories dblclockfft

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

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

Line No. Rev Author Line
1 36 dgisselq
////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    laststage_tb.cpp
4
//
5
// Project:     A Doubletime Pipelined FFT
6
//
7
// Purpose:     A test-bench for the laststage.v subfile of the general purpose
8
//              pipelined FFT.  This file may be run autonomously.  If so,
9
//      the last line output will either read "SUCCESS" on success, or some
10
//      other failure message otherwise.
11
//
12
//      This file depends upon verilator to both compile, run, and therefore
13
//      test laststage.v
14
//
15
// Creator:     Dan Gisselquist, Ph.D.
16
//              Gisselquist Technology, LLC
17
//
18
///////////////////////////////////////////////////////////////////////////
19
//
20
// Copyright (C) 2015,2018 Gisselquist Technology, LLC
21
//
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
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
34
// 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
///////////////////////////////////////////////////////////////////////////
42
#include <stdio.h>
43
#include <stdint.h>
44
 
45
#include "verilated.h"
46
#include "verilated_vcd_c.h"
47
#include "Vlaststage.h"
48
#include "twoc.h"
49
 
50
#define IWIDTH  16
51
#define OWIDTH  (IWIDTH+1)
52
#define SHIFT   0
53
#define ROUND   1
54
 
55
#define ASIZ    32
56
#define AMSK    (ASIZ-1)
57
 
58
class   LASTSTAGE_TB {
59
public:
60
        Vlaststage      *m_last;
61
        VerilatedVcdC   *m_trace;
62
#ifdef  DBLCLKFFT
63
        unsigned long   m_left[ASIZ], m_right[ASIZ];
64
#else
65
        unsigned long   m_data[ASIZ];
66
#endif
67
        bool            m_syncd;
68
        int             m_addr, m_offset;
69
        unsigned long   m_tickcount;
70
 
71
        LASTSTAGE_TB(void) {
72
                Verilated::traceEverOn(true);
73
                m_last = new Vlaststage;
74
                m_tickcount = 0;
75
                m_syncd = false; m_addr = 0, m_offset = 0;
76
        }
77
 
78
        void    opentrace(const char *vcdname) {
79
                if (!m_trace) {
80
                        m_trace = new VerilatedVcdC;
81
                        m_last->trace(m_trace, 99);
82
                        m_trace->open(vcdname);
83
                }
84
        }
85
 
86
        void    closetrace(void) {
87
                if (m_trace) {
88
                        m_trace->close();
89
                        delete m_trace;
90
                        m_trace = NULL;
91
                }
92
        }
93
 
94
        void    tick(void) {
95
                m_tickcount++;
96
 
97
                m_last->i_clk = 0;
98
                m_last->eval();
99
                if (m_trace) m_trace->dump((uint64_t)(10ul * m_tickcount - 2));
100
                m_last->i_clk = 1;
101
                m_last->eval();
102
                if (m_trace) m_trace->dump((uint64_t)(10ul * m_tickcount));
103
                m_last->i_clk = 0;
104
                m_last->eval();
105
                if (m_trace) {
106
                        m_trace->dump((uint64_t)(10ul * m_tickcount + 5));
107
                        m_trace->flush();
108
                }
109
                m_last->i_reset  = 0;
110
                m_last->i_sync = 0;
111
        }
112
 
113
        void    cetick(void) {
114
                int     nkce;
115
 
116
                tick();
117
                nkce = (rand()&1);
118
#ifdef  FFT_CKPCE
119
                nkce += FFT_CKPCE;
120
#endif
121
                if ((m_last->i_ce)&&(nkce > 0)) {
122
                        m_last->i_ce = 0;
123
                        for(int kce = 1; kce < nkce; kce++)
124
                                tick();
125
                        m_last->i_ce = 1;
126
                }
127
        }
128
 
129
        void    reset(void) {
130
                m_last->i_reset = 1;
131
                tick();
132
 
133
                m_syncd = false; m_addr = 0, m_offset = 0;
134
        }
135
 
136
        void    check_results(void) {
137
                bool    failed = false;
138
 
139
                if ((!m_syncd)&&(m_last->o_sync)) {
140
                        m_syncd = true;
141
                        m_offset = m_addr;
142
                        printf("SYNCD at %d\n", m_addr);
143
                }
144
 
145
#ifdef  DBLCLKFFT
146
                int     ir0, ir1, ii0, ii1, or0, oi0, or1, oi1;
147
 
148
                ir0 = sbits(m_left[ (m_addr-m_offset)&AMSK]>>IWIDTH, IWIDTH);
149
                ir1 = sbits(m_right[(m_addr-m_offset)&AMSK]>>IWIDTH, IWIDTH);
150
                ii0 = sbits(m_left[ (m_addr-m_offset)&AMSK], IWIDTH);
151
                ii1 = sbits(m_right[(m_addr-m_offset)&AMSK], IWIDTH);
152
 
153
 
154
                or0 = sbits(m_last->o_left  >> OWIDTH, OWIDTH);
155
                oi0 = sbits(m_last->o_left           , OWIDTH);
156
                or1 = sbits(m_last->o_right >> OWIDTH, OWIDTH);
157
                oi1 = sbits(m_last->o_right          , OWIDTH);
158
 
159
 
160
                // Sign extensions
161
                printf("k=%3d: IN = %08x:%08x, OUT =%09lx:%09lx, S=%d\n",
162
                        m_addr, m_last->i_left, m_last->i_right,
163
                        m_last->o_left, m_last->o_right,
164
                        m_last->o_sync);
165
 
166
                /*
167
                printf("\tI0 = { %x : %x }, I1 = { %x : %x }, O0 = { %x : %x }, O1 = { %x : %x }\n",
168
                        ir0, ii0, ir1, ii1, or0, oi0, or1, oi1);
169
                */
170
 
171
                if (m_syncd) {
172
                        if (or0 != (ir0 + ir1)) {
173
                                printf("FAIL 1: or0 != (ir0+ir1), or %x(exp) != %x(sut)\n", (ir0+ir1), or0);
174
                                failed=true;}
175
                        if (oi0 != (ii0 + ii1)) {printf("FAIL 2\n"); failed=true;}
176
                        if (or1 != (ir0 - ir1)) {printf("FAIL 3\n"); failed=true;}
177
                        if (oi1 != (ii0 - ii1)) {printf("FAIL 4\n"); failed=true;}
178
                } else if (m_addr > 20) {
179
                        printf("NO SYNC!\n");
180
                        failed = true;
181
                }
182
#else
183
                int     or0, oi0;
184
                int     sumr, sumi, difr, difi;
185
                int     ir0, ii0, ir1, ii1, ir2, ii2, ir3, ii3, irn, iin;
186
 
187
                irn = sbits(m_data[(m_addr-m_offset+2)&AMSK]>>IWIDTH, IWIDTH);
188
                iin = sbits(m_data[(m_addr-m_offset+2)&AMSK], IWIDTH);
189
                ir0 = sbits(m_data[(m_addr-m_offset+1)&AMSK]>>IWIDTH, IWIDTH);
190
                ii0 = sbits(m_data[(m_addr-m_offset+1)&AMSK], IWIDTH);
191
                ir1 = sbits(m_data[(m_addr-m_offset  )&AMSK]>>IWIDTH, IWIDTH);
192
                ii1 = sbits(m_data[(m_addr-m_offset  )&AMSK], IWIDTH);
193
                ir2 = sbits(m_data[(m_addr-m_offset-1)&AMSK]>>IWIDTH, IWIDTH);
194
                ii2 = sbits(m_data[(m_addr-m_offset-1)&AMSK], IWIDTH);
195
                ir3 = sbits(m_data[(m_addr-m_offset-2)&AMSK]>>IWIDTH, IWIDTH);
196
                ii3 = sbits(m_data[(m_addr-m_offset-2)&AMSK], IWIDTH);
197
 
198
                sumr = ir1 + ir0;
199
                sumi = ii1 + ii0;
200
 
201
                difr = ir2 - ir1;
202
                difi = ii2 - ii1;
203
 
204
                or0 = sbits(m_last->o_val  >> OWIDTH, OWIDTH);
205
                oi0 = sbits(m_last->o_val           , OWIDTH);
206
 
207
                printf("IR0 = %08x, IR1 = %08x, IR2 = %08x, ",
208
                                ir0, ir1, ir2);
209
                printf("II0 = %08x, II1 = %08x, II2 = %08x, ",
210
                                ii0, ii1, ii2);
211
                // Sign extensions
212
                printf("k=%3d: IN = %08x, %c, OUT =%09lx, S=%d\n",
213
                        m_addr, m_last->i_val,
214
                        m_last->i_sync ? 'S':' ',
215
                        m_last->o_val, m_last->o_sync);
216
 
217
 
218
                if ((m_syncd)&&(0 == ((m_addr-m_offset)&1))) {
219
                        if (or0 != sumr)        {
220
                                printf("FAIL 1: or0 != (ir0+ir1), or %x(exp) != %x(sut)\n", sumr, or0);
221
                                failed=true;
222
                        } if (oi0 != sumi)      {
223
                                printf("FAIL 2\n");
224
                                failed=true;
225
                        }
226
                } else if ((m_syncd)&&(1 == ((m_addr-m_offset)&1))) {
227
                        if (or0 != difr) {
228
                                printf("FAIL 3: or0 != (ir1-ir0), or %x(exp) != %x(sut)\n", difr, or0);
229
                                failed=true;
230
                        } if (oi0 != difi) {
231
                                printf("FAIL 4: oi0 != (ii1-ii0), or %x(exp) != %x(sut)\n", difi, oi0);
232
                                failed=true;
233
                        }
234
                } else if (m_addr > 20) {
235
                        printf("NO SYNC!\n");
236
                        failed = true;
237
                }
238
#endif
239
                if (failed)
240
                        exit(-2);
241
        }
242
 
243
        void    sync(void) {
244
                m_last->i_sync = 1;
245
        }
246
 
247
        void    test(unsigned long left, unsigned long right) {
248
                m_last->i_ce    = 1;
249
                if (m_last->i_sync)
250
                        m_addr = 0;
251
#ifdef  DBLCLKFFT
252
                m_last->i_left  = left;
253
                m_last->i_right = right;
254
 
255
                m_left[ m_addr&AMSK] = m_last->i_left;
256
                m_right[m_addr&AMSK] = m_last->i_right;
257
                m_addr++;
258
 
259
                cetick();
260
#else
261
                m_last->i_val = left;
262
                m_data[ m_addr&AMSK] = m_last->i_val;
263
                m_addr = (m_addr+1);
264
                cetick();
265
 
266
                check_results();
267
 
268
                m_last->i_val = right;
269
                m_data[m_addr&AMSK] = m_last->i_val;
270
                m_addr = (m_addr+1)&AMSK;
271
                cetick();
272
#endif
273
 
274
                check_results();
275
        }
276
 
277
        void    test(int ir0, int ii0, int ir1, int ii1) {
278
                unsigned long   left, right, mask = (1<<IWIDTH)-1;
279
 
280
                left  = ((ir0&mask) << IWIDTH) | (ii0 & mask);
281
                right = ((ir1&mask) << IWIDTH) | (ii1 & mask);
282
                test(left, right);
283
        }
284
};
285
 
286
int     main(int argc, char **argv, char **envp) {
287
        Verilated::commandArgs(argc, argv);
288
        LASTSTAGE_TB    *tb = new LASTSTAGE_TB;
289
 
290
        tb->opentrace("laststage.vcd");
291
        tb->reset();
292
 
293
        tb->sync();
294
 
295
        tb->test( 1, 0,0,0);
296
        tb->test( 0, 2,0,0);
297
        tb->test( 0, 0,4,0);
298
        tb->test( 0, 0,0,8);
299
 
300
        tb->test( 0, 0,0,0);
301
 
302
        tb->test(16,16,0,0);
303
        tb->test(0,0,16,16);
304
        tb->test(16,-16,0,0);
305
        tb->test(0,0,16,-16);
306
        tb->test(16,16,0,0);
307
        tb->test(0,0,16,16);
308
 
309
        for(int k=0; k<64; k++) {
310
                int16_t ir0, ii0, ir1, ii1;
311
 
312
                // Let's pick some random values, ...
313
                ir0 = rand(); if (ir0&4) ir0 = -ir0;
314
                ii0 = rand(); if (ii0&2) ii0 = -ii0;
315
                ir1 = rand(); if (ir1&1) ir1 = -ir1;
316
                ii1 = rand(); if (ii1&8) ii1 = -ii1;
317
 
318
                tb->test(ir0, ii0, ir1, ii1);
319
 
320
        }
321
 
322
        delete  tb;
323
 
324
        printf("SUCCESS!\n");
325
        exit(0);
326
}
327
 
328
 
329
 
330
 
331
 
332
 

powered by: WebSVN 2.1.0

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