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

Subversion Repositories wbddr3

[/] [wbddr3/] [trunk/] [bench/] [cpp/] [ddrsdram_tb.cpp] - Blame information for rev 18

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    ddrsdram_tb.cpp
4
//
5
// Project:     A wishbone controlled DDR3 SDRAM memory controller.
6
//
7
// Purpose:     To determine whether or not the wbddrsdram Verilog module works.
8
//              Run this program with no arguments.  If the last line output
9
//      is "SUCCESS", you will know it works.
10
//
11
// Creator:     Dan Gisselquist, Ph.D.
12
//              Gisselquist Technology, LLC
13
//
14
////////////////////////////////////////////////////////////////////////////////
15
//
16
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
17
//
18
// This program is free software (firmware): you can redistribute it and/or
19
// modify it under the terms of  the GNU General Public License as published
20
// by the Free Software Foundation, either version 3 of the License, or (at
21
// your option) any later version.
22
//
23
// This program is distributed in the hope that it will be useful, but WITHOUT
24
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
25
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
26
// for more details.
27
//
28
// You should have received a copy of the GNU General Public License along
29
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
30
// target there if the PDF file isn't present.)  If not, see
31
// <http://www.gnu.org/licenses/> for a copy.
32
//
33
// License:     GPL, v3, as defined and found on www.gnu.org,
34
//              http://www.gnu.org/licenses/gpl.html
35
//
36
//
37
////////////////////////////////////////////////////////////////////////////////
38
//
39
//
40
#include <stdio.h>
41
 
42
#include "verilated.h"
43
#include "Vwbddrsdram.h"
44 16 dgisselq
#include "pddrsim.h"
45
// #include "ddrsdramsim.h"
46 4 dgisselq
 
47 18 dgisselq
const int       BOMBCOUNT = 512,
48
                SDRAMMASK = 0x0ffffff,
49 4 dgisselq
                LGMEMSIZE = 28;
50
 
51 18 dgisselq
char    cmdchar(int cmd) {
52
        const char cmdstr[] = { 'M', 'R', 'P', 'A', 'W', 'R', 'Z', 'n' };
53
        // Try to decode a six bit bit-mask field into a command
54
        if (cmd&32)
55
                return 'Z';
56
        else if (cmd&16)
57
                return '-';
58
        else if (cmd&8)
59
                return '.';
60
        else
61
                return cmdstr[cmd];
62
}
63
 
64 4 dgisselq
class   DDRSDRAM_TB {
65
        long            m_tickcount;
66
        Vwbddrsdram     *m_core;
67 16 dgisselq
        PDDRSIM         *m_sdram;
68 4 dgisselq
        bool            m_bomb;
69
public:
70
 
71
        DDRSDRAM_TB(void) {
72
                m_core = new Vwbddrsdram;
73 16 dgisselq
                m_sdram= new PDDRSIM(LGMEMSIZE);
74 4 dgisselq
        }
75
 
76 18 dgisselq
        unsigned operator[](const int index) { return (*m_sdram)[index]; }
77
        void    set(unsigned addr, unsigned v) { m_sdram->set(addr, v); }
78 4 dgisselq
 
79
        void    tick(void) {
80
                m_core->i_clk = 1;
81
 
82 18 dgisselq
                (*m_sdram)(
83 4 dgisselq
                        m_core->o_ddr_reset_n,
84
                        m_core->o_ddr_cke,
85
                        m_core->o_ddr_bus_oe,
86 16 dgisselq
                        m_core->o_ddr_cmd_a,
87
                        m_core->o_ddr_cmd_b,
88 18 dgisselq
                        m_core->o_ddr_cmd_c,
89
                        m_core->o_ddr_cmd_d,
90
                        m_core->o_ddr_data,
91
                        m_core->i_ddr_data);
92 4 dgisselq
 
93 6 dgisselq
                bool    writeout = (!m_core->v__DOT__reset_override);
94 4 dgisselq
 
95 18 dgisselq
                int cmda, cmdb, cmdc, cmdd;
96 16 dgisselq
                cmda = (m_core->o_ddr_reset_n?0:32)
97 14 dgisselq
                        |(m_core->o_ddr_cke?0:16)
98 16 dgisselq
                        |((m_core->o_ddr_cmd_a&(1<<26))?8:0)
99
                        |((m_core->o_ddr_cmd_a&(1<<25))?4:0)
100
                        |((m_core->o_ddr_cmd_a&(1<<24))?2:0)
101
                        |((m_core->o_ddr_cmd_a&(1<<23))?1:0);
102
                cmdb = (m_core->o_ddr_reset_n?0:32)
103
                        |(m_core->o_ddr_cke?0:16)
104
                        |((m_core->o_ddr_cmd_b&(1<<26))?8:0)
105
                        |((m_core->o_ddr_cmd_b&(1<<25))?4:0)
106
                        |((m_core->o_ddr_cmd_b&(1<<24))?2:0)
107
                        |((m_core->o_ddr_cmd_b&(1<<23))?1:0);
108 18 dgisselq
                cmdc = (m_core->o_ddr_reset_n?0:32)
109
                        |(m_core->o_ddr_cke?0:16)
110
                        |((m_core->o_ddr_cmd_c&(1<<26))?8:0)
111
                        |((m_core->o_ddr_cmd_c&(1<<25))?4:0)
112
                        |((m_core->o_ddr_cmd_c&(1<<24))?2:0)
113
                        |((m_core->o_ddr_cmd_c&(1<<23))?1:0);
114
                cmdd = (m_core->o_ddr_reset_n?0:32)
115
                        |(m_core->o_ddr_cke?0:16)
116
                        |((m_core->o_ddr_cmd_d&(1<<26))?8:0)
117
                        |((m_core->o_ddr_cmd_d&(1<<25))?4:0)
118
                        |((m_core->o_ddr_cmd_d&(1<<24))?2:0)
119
                        |((m_core->o_ddr_cmd_d&(1<<23))?1:0);
120 14 dgisselq
 
121 6 dgisselq
                if (writeout) {
122 18 dgisselq
                        printf("%08lx-WB: %s/%s %s%s%s %s@0x%08x[",
123 6 dgisselq
                                m_tickcount,
124
                                (m_core->i_wb_cyc)?"CYC":"   ",
125
                                (m_core->i_wb_stb)?"STB":"   ",
126
                                (m_core->o_wb_stall)?"STALL":"     ",
127
                                (m_core->o_wb_ack)?"ACK":"   ",
128 18 dgisselq
                                (m_core->o_bus)?"BUS":"   ",
129 6 dgisselq
                                (m_core->i_wb_we)?"W":"R",
130 18 dgisselq
                                (m_core->i_wb_addr));
131
                        printf(".%02x:.%02x:.%04x:%08x/.%02x:.%02x:.%04x:%08x] -- ",
132
                                (m_core->i_wb_data[3]&0x000ff), (m_core->i_wb_data[2]&0x0ff),
133
                                (m_core->i_wb_data[1]&0x0ffff), (m_core->i_wb_data[0]),
134
                                (m_core->o_wb_data[3]&0x000ff), (m_core->o_wb_data[2]&0x0ff),
135
                                (m_core->o_wb_data[1]&0x0ffff), (m_core->o_wb_data[0]));
136 4 dgisselq
 
137 18 dgisselq
                        printf("%s%s %c%c%c%c %s%s%s%s[%x%x%x%x]%s ",
138 6 dgisselq
                                (m_core->o_ddr_reset_n)?" ":"R",
139
                                (m_core->o_ddr_cke)?"CK":"  ",
140 18 dgisselq
                                cmdchar(cmda), cmdchar(cmdb),
141
                                cmdchar(cmdc), cmdchar(cmdd),
142 6 dgisselq
                                //
143 18 dgisselq
                                // Drive DQS?
144 16 dgisselq
                                ((m_core->o_ddr_cmd_a>>5)&1)?"D":"-",
145
                                ((m_core->o_ddr_cmd_b>>5)&1)?"D":"-",
146 18 dgisselq
                                ((m_core->o_ddr_cmd_c>>5)&1)?"D":"-",
147
                                ((m_core->o_ddr_cmd_d>>5)&1)?"D":"-",
148
                                //
149
                                // The data mask
150 16 dgisselq
                                ((m_core->o_ddr_cmd_a>>1)&0x0f),
151
                                ((m_core->o_ddr_cmd_b>>1)&0x0f),
152 18 dgisselq
                                ((m_core->o_ddr_cmd_c>>1)&0x0f),
153
                                ((m_core->o_ddr_cmd_d>>1)&0x0f),
154 6 dgisselq
                                //
155 18 dgisselq
                                // Drive ODT?
156
                                (m_core->o_ddr_cmd_a&1)?"O":" ");
157
 
158
                        printf(" C%xA%x", m_core->v__DOT__cmd_pipe, m_core->v__DOT__nxt_pipe);
159
                                //
160
                        // Now the 4 bank addresses
161
                        printf("  B[%d,%d,%d,%d]@%04x ",
162 16 dgisselq
                                (m_core->o_ddr_cmd_a>>(6+14))&0x07, // Get the bank address
163
                                (m_core->o_ddr_cmd_b>>(6+14))&0x07, // Get the bank address
164 18 dgisselq
                                (m_core->o_ddr_cmd_c>>(6+14))&0x07, // Get the bank address
165
                                (m_core->o_ddr_cmd_d>>(6+14))&0x07, // Get the bank address
166
                                ((m_core->o_ddr_cmd_d>>6)&0x03fff));// The command address
167
                        printf(".%02x:.%02x:.%04x:%08x .%02x:.%02x:.%04x:%08x",
168
                                (m_core->i_ddr_data[3]&0x0ff),(m_core->i_ddr_data[2]&0x0ff),
169
                                (m_core->i_ddr_data[1]&0x0ffff),(m_core->i_ddr_data[0]),
170
                                (m_core->o_ddr_data[3]&0x0ff),(m_core->o_ddr_data[2]&0x0ff),
171
                                (m_core->o_ddr_data[1]&0x0ffff),
172
                                (m_core->o_ddr_data[0]));
173 4 dgisselq
 
174 18 dgisselq
                        printf(" FIFO[%x,%x](%02x:%02x:%04x:%08x)",
175 7 dgisselq
                                m_core->v__DOT__bus_fifo_head,
176
                                m_core->v__DOT__bus_fifo_tail,
177 18 dgisselq
                                m_core->v__DOT__bus_fifo_data[m_core->v__DOT__bus_fifo_tail][3]&0x0ff,
178
                                m_core->v__DOT__bus_fifo_data[m_core->v__DOT__bus_fifo_tail][2]&0x0ff,
179
                                m_core->v__DOT__bus_fifo_data[m_core->v__DOT__bus_fifo_tail][1]&0x0ffff,
180
                                m_core->v__DOT__bus_fifo_data[m_core->v__DOT__bus_fifo_tail][0]);
181 7 dgisselq
 
182 18 dgisselq
                        printf(" BUS[A%03x/R%03x/K%03x]",
183 7 dgisselq
                                (m_core->v__DOT__bus_active),
184
                                (m_core->v__DOT__bus_read),
185 18 dgisselq
                                (m_core->v__DOT__bus_ack));
186 7 dgisselq
 
187 8 dgisselq
                        /*
188 6 dgisselq
                        // Reset logic
189 16 dgisselq
                        printf(" RST(%06x%s[%2d] - %08x->%08x)",
190 6 dgisselq
                                m_core->v__DOT__reset_timer,
191
                                (m_core->v__DOT__reset_ztimer)?"Z":" ",
192
                                (m_core->v__DOT__reset_address),
193
                                (m_core->v__DOT__reset_instruction),
194
                                (m_core->v__DOT__reset_cmd));
195 8 dgisselq
                        */
196 4 dgisselq
 
197 18 dgisselq
                        printf(" R_%s%03x[%d]%04x//.:%08x",
198 9 dgisselq
                                (!m_core->v__DOT__r_pending)?"_"
199
                                        :(m_core->v__DOT__r_we)?"W":"R",
200 6 dgisselq
                                (m_core->v__DOT__r_row),
201
                                (m_core->v__DOT__r_bank),
202 9 dgisselq
                                (m_core->v__DOT__r_col),
203 18 dgisselq
                                (m_core->v__DOT__r_data[3]));
204 9 dgisselq
 
205 18 dgisselq
                        printf(" S_%s%03x[%d]%04x//.:%08x%s%s",
206 9 dgisselq
                                (!m_core->v__DOT__s_pending)?"_"
207
                                        :(m_core->v__DOT__s_we)?"W":"R",
208
                                (m_core->v__DOT__s_row),
209
                                (m_core->v__DOT__s_bank),
210
                                (m_core->v__DOT__s_col),
211 18 dgisselq
                                (m_core->v__DOT__s_data[3]),
212 9 dgisselq
                                (m_core->v__DOT__pipe_stall)?"P":" ",
213
                                "-"
214
                                //(m_core->v__DOT__s_stall)?"S":" "
215
                                );
216
 
217
 
218 6 dgisselq
                        printf(" %s%s%s",
219 7 dgisselq
                                "B",
220
                                // (m_core->v__DOT__all_banks_closed)?"b":"B",
221 18 dgisselq
                                (m_core->v__DOT__cmd_pipe&1)?"C":"N",
222 6 dgisselq
                                //:(m_core->v__DOT__maybe_close_next_bank)?"c":"N",
223 18 dgisselq
                                (m_core->v__DOT__cmd_pipe&2)?"O":"K");
224 6 dgisselq
                                // :(m_core->v__DOT__maybe_open_next_bank)?"o":"K");
225 16 dgisselq
 
226 6 dgisselq
                        for(int i=0; i<8; i++) {
227 18 dgisselq
                                printf("%s%x|%02x@%x%s",
228 6 dgisselq
                                        (m_core->v__DOT__r_bank==i)?"R":"[",
229
                                        m_core->v__DOT__bank_status[i],
230 16 dgisselq
                                        m_sdram->bank_state(i),
231 6 dgisselq
                                        m_core->v__DOT__bank_address[i],
232
                                        (m_core->v__DOT__r_nxt_bank==i)?"N":"]");
233
                        }
234
 
235 18 dgisselq
                        printf(" %s%s%s%s%s%s%s",
236 6 dgisselq
                                (m_core->v__DOT__reset_override)?"R":" ",
237
                                (m_core->v__DOT__need_refresh)?"N":" ",
238 18 dgisselq
                                (m_core->v__DOT__cmd_pipe&1)?"C":" ",
239
                                (m_core->v__DOT__cmd_pipe&2)?"O":" ",
240
                                (m_core->v__DOT__cmd_pipe&4)?"v":" ",
241
                                (m_core->v__DOT__nxt_pipe&1)?"c":" ",
242
                                (m_core->v__DOT__nxt_pipe&2)?"o":" ");
243 6 dgisselq
 
244 18 dgisselq
                        /*
245 14 dgisselq
                        // Refresh logic
246 7 dgisselq
                        printf(" F%s%05x:%x/%s",
247
                                (m_core->v__DOT__refresh_ztimer)?"Z":" ",
248
                                m_core->v__DOT__refresh_counter,
249
                                m_core->v__DOT__refresh_addr,
250
                                (m_core->v__DOT__need_refresh)?"N":" ");
251 18 dgisselq
                        */
252 6 dgisselq
 
253
                        printf("\n");
254
                }
255
 
256 14 dgisselq
                // A consistency check ...
257
                /*
258
                if (m_core->v__DOT__bus_fifo_head != m_core->v__DOT__bus_fifo_tail) {
259
                        fflush(stdout);
260
                        if (cmd == DDR_REFRESH)
261
                                printf("FAIL: CMD=REFRESH, but head != tail\n");
262
                        assert(cmd != DDR_REFRESH);
263
                } */
264
 
265 4 dgisselq
                m_core->eval();
266
                m_core->i_clk = 0;
267
                m_core->eval();
268
 
269
                m_tickcount++;
270
 
271
                /*
272
                if ((m_core->o_wb_ack)&&(!m_core->i_wb_cyc)) {
273
                        printf("SETTING ERR TO TRUE!!!!!  ACK w/ no CYC\n");
274
                        // m_bomb = true;
275
                }
276
                */
277
        }
278
 
279
        void reset(void) {
280
                m_core->i_reset  = 1;
281
                m_core->i_wb_cyc = 0;
282
                m_core->i_wb_stb = 0;
283
                tick();
284
                m_core->i_reset  = 0;
285
        }
286
 
287
        void wb_tick(void) {
288
                m_core->i_wb_cyc   = 0;
289
                m_core->i_wb_stb = 0;
290
                tick();
291 14 dgisselq
                assert(!m_core->o_wb_ack);
292 4 dgisselq
        }
293
 
294 18 dgisselq
        void wb_read(unsigned a, unsigned *buf) {
295 4 dgisselq
                int             errcount = 0;
296
 
297
                printf("WB-READ(%08x)\n", a);
298
 
299
                m_core->i_wb_cyc = 1;
300
                m_core->i_wb_stb = 1;
301
                m_core->i_wb_we  = 0;
302 18 dgisselq
                m_core->i_wb_sel = 0x0ffff;
303
                assert((a & 3)==0);
304
                m_core->i_wb_addr= (a>>2) & SDRAMMASK;
305 4 dgisselq
 
306
                if (m_core->o_wb_stall) {
307
                        while((errcount++ < BOMBCOUNT)&&(m_core->o_wb_stall))
308
                                tick();
309 9 dgisselq
                } tick();
310 4 dgisselq
 
311
                m_core->i_wb_stb = 0;
312
 
313
                while((errcount++ <  BOMBCOUNT)&&(!m_core->o_wb_ack))
314
                        tick();
315
 
316
 
317 18 dgisselq
                for(int j=0; j<4; j++) {
318
                        buf[j] = m_core->o_wb_data[j];
319
                        if (buf[j] != (*this)[a+j]) {
320
                                printf("READ-FAIL\n");
321
                                assert(buf[j] == (*this)[a]);
322
                        }
323 14 dgisselq
                }
324 4 dgisselq
 
325
                // Release the bus?
326
                m_core->i_wb_cyc = 0;
327
                m_core->i_wb_stb = 0;
328
 
329
                if(errcount >= BOMBCOUNT) {
330
                        printf("SETTING ERR TO TRUE!!!!!\n");
331
                        m_bomb = true;
332
                } else if (!m_core->o_wb_ack) {
333
                        printf("SETTING ERR TO TRUE--NO ACK, NO TIMEOUT\n");
334
                        m_bomb = true;
335
                }
336
                tick();
337
 
338 14 dgisselq
                assert(m_core->v__DOT__bus_fifo_head == m_core->v__DOT__bus_fifo_tail);
339
 
340
                assert(!m_core->o_wb_ack);
341 4 dgisselq
        }
342
 
343 18 dgisselq
        void    wb_read(unsigned a, int len, unsigned *buf) {
344 4 dgisselq
                int             errcount = 0;
345
                int             THISBOMBCOUNT = BOMBCOUNT * len;
346
                int             cnt, rdidx, inc;
347
 
348
                printf("WB-READ(%08x, %d)\n", a, len);
349
 
350
                while((errcount++ < BOMBCOUNT)&&(m_core->o_wb_stall))
351
                        wb_tick();
352
 
353
                if (errcount >= BOMBCOUNT) {
354 18 dgisselq
                        printf("WB-READ(%d): Setting bomb to true (errcount = %d)\n", __LINE__, errcount);
355 4 dgisselq
                        m_bomb = true;
356
                        return;
357
                }
358
 
359
                errcount = 0;
360
 
361
                m_core->i_wb_cyc = 1;
362
                m_core->i_wb_stb = 1;
363
                m_core->i_wb_we  = 0;
364 18 dgisselq
                m_core->i_wb_sel = 0x0ffff;
365
                assert((a&3)==0);
366
                m_core->i_wb_addr= (a>>2) & SDRAMMASK;
367 4 dgisselq
 
368
                rdidx =0; cnt = 0;
369
                inc = 1;
370
 
371
                do {
372
                        int     s;
373
                        s = (m_core->o_wb_stall==0)?0:1;
374
                        tick();
375
                        if (!s)
376
                                m_core->i_wb_addr += inc;
377
                        cnt += (s==0)?1:0;
378 14 dgisselq
                        if (m_core->o_wb_ack) {
379 18 dgisselq
                                for(int j=0; j<4; j++) {
380
                                        buf[rdidx+j] = m_core->o_wb_data[j];
381
                                        printf("WB-READ[%08x] = %08x\n",
382
                                                a+rdidx+j, m_core->o_wb_data[j]);
383
                                        if (buf[rdidx+j] != (*this)[a+rdidx+j]){
384 14 dgisselq
                                        printf("READ-FAIL\n");
385 18 dgisselq
                                        assert(buf[rdidx+j] == (*this)[a+rdidx+j]);
386
                                        }
387 14 dgisselq
                                }
388 18 dgisselq
                                rdidx+=4;
389 14 dgisselq
                        }
390 4 dgisselq
                } while((cnt < len)&&(errcount++ < THISBOMBCOUNT));
391
 
392
                m_core->i_wb_stb = 0;
393
 
394 18 dgisselq
                while((rdidx < (len<<2))&&(errcount++ < THISBOMBCOUNT)) {
395 4 dgisselq
                        tick();
396 14 dgisselq
                        if (m_core->o_wb_ack) {
397 18 dgisselq
                                for(int j=0; j<4; j++) {
398
                                        buf[rdidx+j] = m_core->o_wb_data[j];
399
                                        printf("WB-READ[%08x] = %08x\n",
400
                                                a+rdidx+j, m_core->o_wb_data[j]);
401
                                        if (buf[rdidx+j] != (*this)[a+rdidx+j]){
402 14 dgisselq
                                        printf("READ-FAIL\n");
403 18 dgisselq
                                        assert(buf[rdidx+j] == (*this)[a+rdidx+j]);
404
                                        }
405 14 dgisselq
                                }
406 18 dgisselq
                                rdidx+=4;
407 14 dgisselq
                        }
408 4 dgisselq
                }
409
 
410
                // Release the bus?
411
                m_core->i_wb_cyc = 0;
412
 
413
                if(errcount >= THISBOMBCOUNT) {
414
                        printf("SETTING ERR TO TRUE!!!!! (errcount=%08x, THISBOMBCOUNT=%08x)\n", errcount, THISBOMBCOUNT);
415
                        m_bomb = true;
416
                } else if (!m_core->o_wb_ack) {
417
                        printf("SETTING ERR TO TRUE--NO ACK, NO TIMEOUT\n");
418
                        m_bomb = true;
419
                }
420
                tick();
421 14 dgisselq
                assert(m_core->v__DOT__bus_fifo_head == m_core->v__DOT__bus_fifo_tail);
422
                assert(!m_core->o_wb_ack);
423 4 dgisselq
        }
424
 
425 18 dgisselq
        void    wb_write(unsigned a, unsigned *v) {
426 4 dgisselq
                int errcount = 0;
427
 
428 18 dgisselq
                printf("WB-WRITE(%08x) = %08x:%08x:%08x:%08x\n", a, v[0], v[1], v[2], v[3]);
429 4 dgisselq
                m_core->i_wb_cyc = 1;
430
                m_core->i_wb_stb = 1;
431
                m_core->i_wb_we  = 1;
432 18 dgisselq
                assert((a&3)==0);
433
                m_core->i_wb_addr= (a>>2) & SDRAMMASK;
434
                m_core->i_wb_sel = 0x0ffff;
435
                m_core->i_wb_data[0]= v[0];
436
                m_core->i_wb_data[1]= v[1];
437
                m_core->i_wb_data[2]= v[2];
438
                m_core->i_wb_data[3]= v[3];
439 4 dgisselq
 
440
                if (m_core->o_wb_stall)
441
                        while((errcount++ < BOMBCOUNT)&&(m_core->o_wb_stall))
442
                                tick();
443
                tick();
444
 
445
                m_core->i_wb_stb = 0;
446
 
447
                while((errcount++ <  BOMBCOUNT)&&(!m_core->o_wb_ack))
448
                        tick();
449
 
450
                // Release the bus?
451
                m_core->i_wb_cyc = 0;
452
                m_core->i_wb_stb = 0;
453
 
454
                if(errcount >= BOMBCOUNT) {
455
                        printf("SETTING ERR TO TRUE!!!!!\n");
456
                        m_bomb = true;
457
                } tick();
458 14 dgisselq
                assert(m_core->v__DOT__bus_fifo_head == m_core->v__DOT__bus_fifo_tail);
459
                assert(!m_core->o_wb_ack);
460 4 dgisselq
        }
461
 
462 18 dgisselq
        void    wb_write(unsigned a, unsigned int ln, unsigned *buf) {
463 4 dgisselq
                unsigned errcount = 0, nacks = 0;
464
 
465
                m_core->i_wb_cyc = 1;
466
                m_core->i_wb_stb = 1;
467 18 dgisselq
                assert((a&3)==0);
468
                for(unsigned stbcnt=0; stbcnt<(ln<<2); stbcnt+=4) {
469 4 dgisselq
                        m_core->i_wb_we  = 1;
470 18 dgisselq
                        m_core->i_wb_addr= ((a+stbcnt)>>2) & SDRAMMASK;
471
                        m_core->i_wb_sel = 0x0ffff;
472
                        m_core->i_wb_data[0]= buf[stbcnt+0];
473
                        m_core->i_wb_data[1]= buf[stbcnt+1];
474
                        m_core->i_wb_data[2]= buf[stbcnt+2];
475
                        m_core->i_wb_data[3]= buf[stbcnt+3];
476 4 dgisselq
                        errcount = 0;
477
 
478
                        while((errcount++ < BOMBCOUNT)&&(m_core->o_wb_stall)) {
479
                                tick(); if (m_core->o_wb_ack) nacks++;
480
                        }
481
                        // Tick, now that we're not stalled.  This is the tick
482
                        // that gets accepted.
483
                        tick(); if (m_core->o_wb_ack) nacks++;
484
                }
485
 
486
                m_core->i_wb_stb = 0;
487
 
488
                errcount = 0;
489
                while((nacks < ln)&&(errcount++ < BOMBCOUNT)) {
490
                        tick();
491
                        if (m_core->o_wb_ack) {
492
                                nacks++;
493
                                errcount = 0;
494
                        }
495
                }
496
 
497
                // Release the bus
498
                m_core->i_wb_cyc = 0;
499
                m_core->i_wb_stb = 0;
500
 
501
                if(errcount >= BOMBCOUNT) {
502
                        printf("SETTING ERR TO TRUE!!!!!\n");
503
                        m_bomb = true;
504
                } tick();
505 14 dgisselq
                assert(m_core->v__DOT__bus_fifo_head == m_core->v__DOT__bus_fifo_tail);
506
                assert(!m_core->o_wb_ack);
507 4 dgisselq
        }
508
 
509
        bool    bombed(void) const { return m_bomb; }
510
 
511
};
512
 
513 18 dgisselq
void    uload(unsigned len, unsigned *buf) {
514 4 dgisselq
        FILE    *fp = fopen("/dev/urandom", "r");
515
 
516 18 dgisselq
        if ((NULL == fp)||(len != fread(buf, sizeof(unsigned), len, fp))) {
517 4 dgisselq
                for(int i=0; i<(int)len; i++)
518 18 dgisselq
                        buf[i] = ((unsigned)rand());
519 4 dgisselq
        } if (NULL == fp)
520
                fclose(fp);
521
}
522
 
523
int main(int  argc, char **argv) {
524
        Verilated::commandArgs(argc, argv);
525
        DDRSDRAM_TB     *tb = new DDRSDRAM_TB;
526 18 dgisselq
        unsigned        *rdbuf, *mbuf;
527 16 dgisselq
        unsigned        mlen = (1<<(LGMEMSIZE-3));
528 4 dgisselq
 
529
        printf("Giving the core 140k cycles to start up\n");
530
        // Before testing, let's give the unit time enough to warm up
531
        tb->reset();
532 18 dgisselq
        for(int i=0; i<40000+16000+40000+14+6+129+3+13+50; i++)
533 4 dgisselq
                tb->wb_tick();
534
 
535 8 dgisselq
        // Let's short circuit the test, and only test *some* of the memory
536
        // space.  It'll probably be good enough, and it'll finish while I'm
537
        // waiting ...
538
        mlen = 1<<16;
539
 
540 4 dgisselq
        printf("Getting some memory ...\n");
541 18 dgisselq
        rdbuf = new unsigned[mlen];
542
        mbuf  = new unsigned[mlen]; // Match buffer
543 4 dgisselq
        printf("Charging my memory with random values\n");
544
        uload(mlen, rdbuf);
545
 
546 12 dgisselq
#define CASE_TESTS
547 9 dgisselq
#define SINGULAR_WRITE
548
#define SINGULAR_READ
549
#define BIGPIPELINE_WRITE
550
#define BIGPIPELINE_READ
551
#define PRIMEVEC_WRITE
552
#define PRIMEVEC_READ
553
#define SKIP_WRITE
554
#define SKIP_READ
555
 
556 12 dgisselq
#ifdef  CASE_TESTS
557
        {
558 18 dgisselq
                printf("CASE-TEST(WRITE,READ)x8\n");
559
                unsigned v[4];
560
                bool    casefail = false;
561
                for(int i=0; i<8*4; i+=4) {
562
                        tb->wb_write(i, &rdbuf[i]);
563
                        tb->wb_read(i, v);
564
                        for(int j=0; j<4; j++) {
565
                                if (v[j] != rdbuf[i+j])
566
                                        casefail = true;
567
                        } if (casefail) {
568
                                printf("CASE-1, %08x:%08x:%08x:%08x "
569
                                        "-> MEM[%08x] -> "
570
                                        "%08x:%08x:%08x:%08x "
571
                                        "FAILED (R/W not equal)\n",
572
                                        rdbuf[i+0], rdbuf[i+1],
573
                                        rdbuf[i+2], rdbuf[i+3], i,
574
                                        v[0], v[1], v[2], v[3]);
575 12 dgisselq
                                goto test_failure;
576 18 dgisselq
                        } else printf("MATCH[%d] = %08x:%08x:%08x:%08x\n",
577
                                i,rdbuf[i], rdbuf[i+1], rdbuf[i+2], rdbuf[i+3]);
578 12 dgisselq
                }
579
        }
580
 
581
        // Now repeat, hitting a different bank with each command
582
        {
583 18 dgisselq
                printf("CASE-TEST(WRITE,READ)[RND]x8\n");
584
                unsigned a, v[4];
585
                bool    casefail = false;
586
                for(int i=0; i<8*4; i+=4) {
587
                        a = (1087 + i*1031)<<2;
588
                        if (a >= mlen)
589
                                a &= (mlen-4);
590
                        tb->wb_write(a, &rdbuf[a]);
591
                        tb->wb_read(a, v);
592
                        for(int j=0; j<4; j++) {
593
                                if (v[j] != rdbuf[a+j])
594
                                        casefail = true;
595
                        } if (casefail) {
596
                                printf("CASE-2, %08x:%08x:%08x:%08x -> "
597
                                        "MEM[%08x] -> %08x:%08x:%08x:%08x "
598
                                        "FAILED (R/W not equal)\n",
599
                                        rdbuf[a+0], rdbuf[a+1],
600
                                        rdbuf[a+2], rdbuf[a+3], a,
601
                                        v[0], v[1], v[2], v[3]);
602 12 dgisselq
                                goto test_failure;
603
                        }
604
                }
605
        }
606
 
607
        // And again, hitting the same bank with each command
608
        {
609 18 dgisselq
                printf("CASE-TEST(WRITE,READ)[rnd]x8\n");
610
                unsigned a, v[4];
611
                bool    casefail = false;
612
                for(int i=0; i<8*4; i+=4) {
613
                        a = (1109 + i*256)<<2;
614
                        tb->wb_write(a, &rdbuf[a]);
615
                        tb->wb_read(a, v);
616
                        for(int j=0; j<4; j++) {
617
                                if (v[j] != rdbuf[a+j])
618
                                        casefail = true;
619
                        } if (casefail) {
620
                                printf("CASE-3, %08x:%08x:%08x:%08x -> "
621
                                        "MEM[%08x] -> %08x:%08x:%08x:%08x "
622
                                        "FAILED (R/W not equal)\n",
623
                                        rdbuf[a+0], rdbuf[a+1],
624
                                        rdbuf[a+2], rdbuf[a+3], a,
625
                                        v[0], v[1], v[2], v[3]);
626 12 dgisselq
                                goto test_failure;
627
                        }
628
                }
629
        }
630 13 dgisselq
 
631
        // Same thing, but writing all first before reading
632
        {
633 18 dgisselq
                printf("CASE-TEST(WRITE[Rnd]x8,READ[Rnd]x8)\n");
634
                unsigned a, v[4];
635
                bool    casefail = false;
636
                for(int i=0; i<8*4; i+=4) {
637
                        a = (1109 + i*256)<<2;
638
                        tb->wb_write(a, &rdbuf[a]);
639
                } for(int i=0; i<8*4; i+=4) {
640
                        a = (1109 + i*256)<<2;
641
                        tb->wb_read(a, v);
642
                        for(int j=0; j<4; j++) {
643
                                if(v[j] != rdbuf[a+j])
644
                                        casefail = true;
645
                        } if (casefail) {
646
                                printf("CASE-4, %08x:%08x:%08x:%08x -> "
647
                                        "MEM[%08x] -> %08x:%08x:%08x:%08x "
648
                                        "FAILED (R/W not equal)\n",
649
                                        rdbuf[a+0], rdbuf[a+1],
650
                                        rdbuf[a+2], rdbuf[a+3], a,
651
                                        v[0], v[1], v[2], v[3]);
652 13 dgisselq
                                goto test_failure;
653
                        }
654
                }
655
        }
656 14 dgisselq
 
657
        // And a quick pipeline test
658
        {
659 18 dgisselq
                printf("CASE-TEST(WRITEx8P,READx8P)\n");
660
                unsigned v, mbuf[8*4], a = (379)<<2;
661
                tb->wb_write(0, 8, &rdbuf[a]);
662
                for(int i=0; i<8*4; i++) {
663
                        a = (379<<2)+i;
664 14 dgisselq
                        if ((v=(*tb)[i]) != rdbuf[a]) {
665 18 dgisselq
                                printf("CASE-5, %08x -> MEM[%08x] -> %08x "
666
                                        "FAILED (R/W not equal)\n",
667
                                        rdbuf[a], i, v);
668 14 dgisselq
                                goto test_failure;
669
                        }
670
                } tb->wb_read(0, 8, mbuf);
671 18 dgisselq
                for(int i=0; i<8*4; i++) {
672
                        a = (379<<2)+i;
673 14 dgisselq
                        if (mbuf[i] != rdbuf[a]) {
674 18 dgisselq
                                printf("CASE-6, %08x -> MEM[%08x] -> %08x "
675
                                        "FAILED (R/W not equal)\n",
676
                                        rdbuf[a], i, mbuf[i]);
677 14 dgisselq
                                goto test_failure;
678
                        }
679
                }
680
        }
681 12 dgisselq
#endif
682
 
683 9 dgisselq
#ifdef  SINGULAR_WRITE
684 4 dgisselq
        // First test: singular reads through the memory, followed by
685
        // singular  writes
686 18 dgisselq
        {
687
                printf("SINGULAR(WRITE)::Starting the single-write test\n");
688
                for(int i=0; i<(int)mlen; i+=4) {
689
                        tb->wb_write(i, &rdbuf[i]);
690
                        tb->wb_tick();
691
                        for(int j=0; j<4; j++) {
692
                                if ((*tb)[i+j] != rdbuf[i+j]) {
693
                                        printf("WRITE[%06x] = %08x (Expecting %08x) "
694
                                                "FAILED\n",
695
                                        i, (*tb)[i+j], rdbuf[i+j]);
696
                                        goto test_failure;
697
                                } if (tb->bombed())
698
                                        goto test_failure;
699
                        }
700
                }
701 9 dgisselq
        }
702
#else
703
#ifdef  SINGULAR_READ
704
        // If we aren't doing the write test, we still need to charge
705
        // the memory for the read test.  Here we do it manually.
706 18 dgisselq
                for(int i=0; i<(int)mlen; i++)
707
                        tb->set(i, rdbuf[i]);
708 9 dgisselq
#endif // !SINGULAR_WRITE && SINGULAR_READ
709
#endif // SINGULAR_WRITE
710
#ifdef  SINGULAR_READ
711 18 dgisselq
        {
712
                printf("SINGULAR(READ)::Starting the single-read test\n");
713
                for(int i=0; i<(int)mlen; i+=4) {
714
                        unsigned v[4];
715
                        bool    casefail = false;
716
 
717
                        tb->wb_read(i, v);
718
                        for(int j=0; j<4; j++) {
719
                                if (rdbuf[i+j] != v[j])
720
                                        casefail = true;
721
                        } if (casefail) {
722
                                printf("READ[%06x] = %08x:%08x:%08x:%08x "
723
                                        "(Expecting %08x:%08x:%08x:%08x)\n",
724
                                                i, v[0], v[1], v[2], v[3],
725
                                                rdbuf[i+0], rdbuf[i+1],
726
                                                rdbuf[i+2], rdbuf[i+3]);
727
                                goto test_failure;
728
                        } if (tb->bombed())
729
                                goto test_failure;
730
                        tb->wb_tick();
731
                }
732 4 dgisselq
        }
733 9 dgisselq
#endif
734 4 dgisselq
 
735 9 dgisselq
#ifdef  BIGPIPELINE_WRITE
736 18 dgisselq
        {
737
                // Second test: Vector writes going through all memory, followed a
738
                // massive vector read
739
                printf("BIGPIPELINE_WRITE::Starting the big-pipeline write test\n");
740
                uload(mlen, rdbuf); // Get some new values
741
                tb->wb_write(0, mlen/4, rdbuf);
742
                if (tb->bombed())
743 4 dgisselq
                        goto test_failure;
744 18 dgisselq
                for(int i=0; i<(int)mlen; i++) {
745
                        unsigned v;
746
                        if (rdbuf[i] != (v=(*tb)[i])) {
747
                                printf("V-WRITE[%06x] = %08x (Expecting %08x)\n",
748
                                        i, v, rdbuf[i]);
749
                                goto test_failure;
750
                        }
751 4 dgisselq
                }
752
        }
753 9 dgisselq
#else
754
#ifdef  BIGPIPELINE_READ
755
        uload(mlen, rdbuf); // Get some new values
756
        // If we aren't doing the write test, we still need to charge
757
        // the memory for the read test.  Here we do it manually.
758
        for(int i=0; i<(int)mlen; i++)
759
                (*tb)[i] = rdbuf[i];
760
#endif // BIGPIPELINE_WRITE && BIGPIPELINE_READ
761
#endif
762
#ifdef  BIGPIPELINE_READ
763 18 dgisselq
        {
764
                printf("BIGPIPELINE_READ::Starting the big-pipeline read test\n");
765
                tb->wb_read( 0, mlen/4, mbuf);
766
                if (tb->bombed())
767 4 dgisselq
                        goto test_failure;
768 18 dgisselq
                for(int i=0; i<(int)mlen; i++) {
769
                        if (rdbuf[i] != mbuf[i]) {
770
                                printf("V-READ[%06x] = %08x (Expecting %08x)\n",
771
                                        i, mbuf[i], rdbuf[i]);
772
                                goto test_failure;
773
                        }
774 4 dgisselq
                }
775
        }
776 9 dgisselq
#endif
777 4 dgisselq
 
778 9 dgisselq
#ifdef  PRIMEVEC_WRITE
779 18 dgisselq
        printf("PRIMEVEC(WRITE)::Starting the prime-vector write test\n");
780 8 dgisselq
        // Third test: Vector writes going through all memory, in prime numbers
781 4 dgisselq
        // of values at a time, followed by reads via a different prime number
782 8 dgisselq
        uload(mlen, rdbuf); // Get some new values
783 9 dgisselq
        {
784
                int     nw = 3;
785 18 dgisselq
                for(int i=0; i<(int)mlen; i+=nw*4) {
786
                        int     ln = ((int)mlen-i>nw*4)?(nw*4):mlen-i;
787
                        tb->wb_write(i, ln/4, &rdbuf[i]);
788 9 dgisselq
                        for(int j=0; j<ln; j++) {
789
                                if ((*tb)[i+j] != rdbuf[i+j]) {
790 18 dgisselq
                                        printf("P-WRITE[%06x] = %08x (Expecting %08x) FAILED\n",
791 9 dgisselq
                                                i, (*tb)[i], rdbuf[i]);
792
                                        goto test_failure;
793
                                }
794
                        } if (tb->bombed())
795 4 dgisselq
                                goto test_failure;
796 9 dgisselq
                }
797
        }
798
#else
799
#ifdef  PRIMEVEC_READ
800
        uload(mlen, rdbuf); // Get some new values
801
        // If we aren't doing the write test, we still need to charge
802
        // the memory for the read test.  Here we do it manually.
803
        for(int i=0; i<(int)mlen; i++)
804 16 dgisselq
                tb->set(i, rdbuf[i]);
805 9 dgisselq
#endif
806
#endif
807
#ifdef  PRIMEVEC_READ
808 18 dgisselq
        printf("PRIMEVEC(READ)::Starting the prime-vector read test\n");
809 9 dgisselq
        {
810
                int     nr = 13;
811 18 dgisselq
                for(int i=0; i<(int)mlen; i+=nr*4) {
812
                        int     ln = ((int)mlen-i>nr*4)?(nr*4):(mlen-i);
813
                        tb->wb_read(i, ln/4, &mbuf[i]);
814 9 dgisselq
                        for(int j=0; j<ln; j++) {
815
                                if (mbuf[i+j] != rdbuf[i+j]) {
816 18 dgisselq
                                        printf("P-READ[%06x] = %08x (Expecting %08x) FAILED\n",
817 9 dgisselq
                                                i, mbuf[i], rdbuf[i]);
818
                                        goto test_failure;
819
                                }
820
                        } if (tb->bombed())
821 4 dgisselq
                                goto test_failure;
822 9 dgisselq
                }
823 4 dgisselq
        }
824 9 dgisselq
#endif
825 4 dgisselq
 
826 9 dgisselq
#ifdef  SKIP_WRITE
827 18 dgisselq
        {
828
                // Fourth test: Singular writes though all of memory, skipping by some
829
                // prime address increment each time, followed by reads via a different
830
                // prime numbered increment.
831
                printf("SKIP(WRITE)::Starting the skip write test\n");
832
                uload(mlen, rdbuf); // Get some new values
833
                for(int i=0; i<(int)mlen; i++) {
834
                        int     loc = (i*3889)&(mlen-4);
835
                        bool    casefail = false;
836
                        tb->wb_write(loc, &rdbuf[loc]);
837
                        for(int j=0; j<4; j++) {
838
                                if ((*tb)[loc+j] != rdbuf[loc+j]) {
839
                                        printf("R-WRITE[%06x] = %08x (Expecting %08x) FAILED\n",
840
                                                i, (*tb)[loc+j], rdbuf[loc+j]);
841
                                        casefail = true;
842
                                }
843
                        }
844
                        if ((casefail)||(tb->bombed()))
845
                                goto test_failure;
846
                }
847 9 dgisselq
        }
848
#else
849
#ifdef  SKIP_READ
850
        uload(mlen, rdbuf); // Get some new values
851
        for(int i=0; i<(int)mlen; i++)
852 16 dgisselq
                tb->set(i, rdbuf[i]);
853 9 dgisselq
#endif // !SKIP_WRITE && SKIP_READ
854
#endif
855
#ifdef  SKIP_READ
856 18 dgisselq
        printf("SKIP(READ)::Starting the skip read/validate/verify test\n");
857 9 dgisselq
        for(int i=0; i<(int)mlen; i++) {
858 18 dgisselq
                int     loc = (i*7477)&(mlen-4);
859
                bool    casefail = false;
860
                tb->wb_read(loc, &mbuf[loc]);
861
                for(int j=0; j<4; j++) {
862
                        if (mbuf[loc] != rdbuf[loc]) {
863
                                printf("R-READ[%06x] = %08x (Expecting %08x) FAILED\n",
864
                                        loc, mbuf[loc+j], rdbuf[loc+j]);
865
                                casefail = true;
866
                        }
867
                } if ((tb->bombed())||(casefail))
868 8 dgisselq
                        goto test_failure;
869
        }
870 9 dgisselq
#endif
871 4 dgisselq
 
872 8 dgisselq
 
873 4 dgisselq
        printf("SUCCESS!!\n");
874
        exit(0);
875
test_failure:
876
        printf("FAIL-HERE\n");
877
        for(int i=0; i<64; i++)
878
                tb->tick();
879
        printf("TEST FAILED\n");
880
        exit(-1);
881
}

powered by: WebSVN 2.1.0

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