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

Subversion Repositories dblclockfft

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

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

Line No. Rev Author Line
1 6 dgisselq
////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    mpy_tb.cpp
4
//
5 36 dgisselq
// Project:     A General Purpose Pipelined FFT Implementation
6 6 dgisselq
//
7
// Purpose:     A test-bench for the shift and add shiftaddmpy.v subfile of
8
//              the double clocked FFT.  This file may be run autonomously. 
9
//              If so, the last line output will either read "SUCCESS" on
10
//              success, or some other failure message otherwise.
11
//
12
//              This file depends upon verilator to both compile, run, and
13
//              therefore test shiftaddmpy.v
14
//
15
// Creator:     Dan Gisselquist, Ph.D.
16 30 dgisselq
//              Gisselquist Technology, LLC
17 6 dgisselq
//
18
///////////////////////////////////////////////////////////////////////////
19
//
20 36 dgisselq
// Copyright (C) 2015-2018, Gisselquist Technology, LLC
21 6 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
// 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 36 dgisselq
#include "verilated.h"
43
#include "verilated_vcd_c.h"
44
 
45 29 dgisselq
#include "fftsize.h"
46 36 dgisselq
 
47 29 dgisselq
#ifdef  USE_OLD_MULTIPLY
48 3 dgisselq
#include "Vshiftaddmpy.h"
49 29 dgisselq
typedef Vshiftaddmpy    Vmpy;
50
#define AW      TST_SHIFTADDMPY_AW
51
#define BW      TST_SHIFTADDMPY_BW
52
#define DELAY   (TST_SHIFTADDMPY_AW+2)
53
#else
54
#include "Vlongbimpy.h"
55
typedef Vlongbimpy      Vmpy;
56
#define AW      TST_LONGBIMPY_AW
57
#define BW      TST_LONGBIMPY_BW
58
#define DELAY   ((AW/2)+(AW&1)+2)
59
#endif
60
 
61
#include "twoc.h"
62 3 dgisselq
 
63
class   MPYTB {
64
public:
65 36 dgisselq
        Vmpy            *m_mpy;
66
        VerilatedVcdC   *m_trace;
67
        long            vals[32];
68
        int             m_addr;
69
        uint64_t        m_tickcount;
70 3 dgisselq
 
71
        MPYTB(void) {
72 36 dgisselq
                Verilated::traceEverOn(true);
73
                m_mpy = new Vmpy;
74
                m_tickcount = 0;
75 3 dgisselq
 
76
                for(int i=0; i<32; i++)
77
                        vals[i] = 0;
78
                m_addr = 0;
79
        }
80
        ~MPYTB(void) {
81 36 dgisselq
                closetrace();
82
                delete m_mpy;
83 3 dgisselq
        }
84
 
85 36 dgisselq
        void    opentrace(const char *vcdname) {
86
                if (!m_trace) {
87
                        m_trace = new VerilatedVcdC;
88
                        m_mpy->trace(m_trace, 99);
89
                        m_trace->open(vcdname);
90
                }
91 3 dgisselq
        }
92
 
93 36 dgisselq
        void    closetrace(void) {
94
                if (m_trace) {
95
                        m_trace->close();
96
                        delete  m_trace;
97
                        m_trace = NULL;
98
                }
99
        }
100
 
101
        void    tick(void) {
102
                m_tickcount++;
103
 
104
                m_mpy->i_clk = 0;
105
                m_mpy->eval();
106
                if (m_trace)    m_trace->dump((uint64_t)(10ul*m_tickcount-2));
107
                m_mpy->i_clk = 1;
108
                m_mpy->eval();
109
                if (m_trace)    m_trace->dump((uint64_t)(10ul*m_tickcount));
110
                m_mpy->i_clk = 0;
111
                m_mpy->eval();
112
                if (m_trace)    {
113
                        m_trace->dump((uint64_t)(10ul*m_tickcount+5));
114
                        m_trace->flush();
115
                }
116
        }
117
 
118
        void    cetick(void) {
119
                int     ce = m_mpy->i_ce, nkce;
120
 
121
                tick();
122
                nkce = (rand()&1);
123
#ifdef  FFT_CKPCE
124
                nkce += FFT_CKPCE;
125
#endif
126
                if ((ce)&&(nkce>0)) {
127
                        m_mpy->i_ce = 0;
128
                        for(int kce=1; kce<nkce; kce++)
129
                                tick();
130
                }
131
 
132
                m_mpy->i_ce = ce;
133
        }
134
 
135 3 dgisselq
        void    reset(void) {
136 36 dgisselq
                m_mpy->i_clk = 0;
137
                m_mpy->i_ce = 1;
138
                m_mpy->i_a_unsorted = 0;
139
                m_mpy->i_b_unsorted = 0;
140 3 dgisselq
 
141
                for(int k=0; k<20; k++)
142 36 dgisselq
                        cetick();
143 3 dgisselq
        }
144
 
145
        bool    test(const int ia, const int ib) {
146
                bool    success;
147 29 dgisselq
                long    a, b, out;
148 3 dgisselq
 
149 29 dgisselq
                a = sbits(ia, AW);
150
                b = sbits(ib, BW);
151 36 dgisselq
                m_mpy->i_ce = 1;
152
                m_mpy->i_a_unsorted = ubits(a, AW);
153
                m_mpy->i_b_unsorted = ubits(b, BW);
154 3 dgisselq
 
155 29 dgisselq
                vals[m_addr&31] = a * b;
156 3 dgisselq
 
157 36 dgisselq
                cetick();
158 3 dgisselq
 
159 36 dgisselq
                printf("k=%3d: A =%0*x, B =%0*x -> O = %*lx (ANS=%*lx)\n",
160
                        m_addr, (AW+3)/4, (int)ubits(a,AW),
161
                        (BW+3)/4, (int)ubits(b,BW),
162
                        (AW+BW+3)/4, (long)m_mpy->o_r,
163
                        (AW+BW+7)/4, ubits(vals[m_addr&31], AW+BW+4));
164 3 dgisselq
 
165 36 dgisselq
                out = sbits(m_mpy->o_r, AW+BW);
166 3 dgisselq
 
167
                m_addr++;
168
 
169 29 dgisselq
                success = (m_addr < (DELAY+2))||(out == vals[(m_addr-DELAY)&31]);
170 3 dgisselq
                if (!success) {
171 29 dgisselq
                        printf("WRONG ANSWER: %8lx (exp) != %8lx (sut)\n", vals[(m_addr-DELAY)&0x01f], out);
172 3 dgisselq
                        exit(-1);
173
                }
174
 
175
                return success;
176
        }
177
};
178
 
179
int     main(int argc, char **argv, char **envp) {
180
        Verilated::commandArgs(argc, argv);
181
        MPYTB           *tb = new MPYTB;
182
 
183 36 dgisselq
        tb->opentrace("mpy.vcd");
184 3 dgisselq
        tb->reset();
185
 
186
        for(int k=0; k<15; k++) {
187
                int     a, b;
188
 
189
                a = (1<<k);
190
                b = 1;
191
                tb->test(a, b);
192
        }
193
 
194
        for(int k=0; k<15; k++) {
195
                int     a, b, out;
196
 
197
                a = (1<<15);
198
                b = (1<<k);
199
                tb->test(a, b);
200
        }
201
 
202 36 dgisselq
        if (AW+BW <= 20) {
203
                // Exhaustive test
204
                for(int a=0; a< (1<<AW); a++)
205
                for(int b=0; b< (1<<BW); b++)
206
                        tb->test(a, b);
207
                printf("Exhaust complete\n");
208
        } else {
209
                // Pseudorandom test
210
                for(int k=0; k<2048; k++)
211
                        tb->test(rand(), rand());
212 3 dgisselq
        }
213
 
214
        delete  tb;
215
 
216 4 dgisselq
        printf("SUCCESS!\n");
217 3 dgisselq
        exit(0);
218
}

powered by: WebSVN 2.1.0

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