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

Subversion Repositories qspiflash

[/] [qspiflash/] [trunk/] [bench/] [cpp/] [qspiflash_tb.cpp] - Blame information for rev 17

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 16 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    qspiflash_tb.cpp
4
//
5
// Project:     Wishbone Controlled Quad SPI Flash Controller
6
//
7
// Purpose:     To determine whether or not the qspiflash module works.  Run
8
//              this with no arguments, and check whether or not the last line
9
//      contains "SUCCESS" or not.  If it does contain "SUCCESS", then the
10
//      module passes all tests found within here.
11
//
12
// Creator:     Dan Gisselquist, Ph.D.
13
//              Gisselquist Technology, LLC
14
//
15
////////////////////////////////////////////////////////////////////////////////
16
//
17
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
18
//
19
// This program is free software (firmware): you can redistribute it and/or
20
// modify it under the terms of  the GNU General Public License as published
21
// by the Free Software Foundation, either version 3 of the License, or (at
22
// your option) any later version.
23
//
24
// This program is distributed in the hope that it will be useful, but WITHOUT
25
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
26
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
27
// for more details.
28
//
29
// You should have received a copy of the GNU General Public License along
30
// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no
31
// target there if the PDF file isn't present.)  If not, see
32
// <http://www.gnu.org/licenses/> for a copy.
33
//
34
// License:     GPL, v3, as defined and found on www.gnu.org,
35
//              http://www.gnu.org/licenses/gpl.html
36
//
37
//
38
////////////////////////////////////////////////////////////////////////////////
39
//
40
//
41
#include "verilated.h"
42
#include "Vwbqspiflash.h"
43
#include "qspiflashsim.h"
44
#include "wbflash_tb.h"
45
 
46
#define QSPIFLASH       0x0400000
47
#define PARENT  WBFLASH_TB<Vwbqspiflash>
48
 
49
class   QSPIFLASH_TB : public PARENT {
50
        QSPIFLASHSIM    *m_flash;
51
        bool            m_bomb;
52
public:
53
 
54
        QSPIFLASH_TB(void) {
55
                m_core = new Vwbqspiflash;
56
                m_flash= new QSPIFLASHSIM;
57
                m_flash->debug(true);
58
        }
59
 
60
        unsigned operator[](const int index) { return (*m_flash)[index]; }
61
        void    setflash(unsigned addr, unsigned v) {
62
                m_flash->set(addr, v);
63
        }
64
        void    load(const char *fname) {
65
                m_flash->load(0,fname);
66
        }
67
 
68
        void    set(const unsigned addr, const unsigned val) {
69
                m_flash->set(addr, val);
70
        }
71
 
72
        void    tick(void) {
73 17 dgisselq
                bool    writeout = false;
74 16 dgisselq
                m_core->i_qspi_dat = (*m_flash)(m_core->o_qspi_cs_n,
75
                        m_core->o_qspi_sck, m_core->o_qspi_dat);
76
 
77
 
78 17 dgisselq
                if (writeout) {
79
                        printf("%08lx-WB: %s %s/%s %s %s",
80
                                m_tickcount,
81
                                (m_core->i_wb_cyc)?"CYC":"   ",
82
                                (m_core->i_wb_data_stb)?"DSTB":"    ",
83
                                (m_core->i_wb_ctrl_stb)?"CSTB":"    ",
84
                                (m_core->o_wb_stall)?"STALL":"     ",
85
                                (m_core->o_wb_ack)?"ACK":"   ");
86
                        printf(" %s@0x%08x[%08x/%08x]",
87
                                (m_core->i_wb_we)?"W":"R",
88
                                (m_core->i_wb_addr), (m_core->i_wb_data),
89
                                (m_core->o_wb_data));
90
                        printf(" QSPI:%x:%x/%02x/%02x/%2d",
91
                                m_core->i_qspi_dat, m_core->o_qspi_mod,
92
                                m_core->v__DOT__state,
93
                                m_core->v__DOT__lldriver__DOT__state,
94
                                m_core->v__DOT__lldriver__DOT__spi_len);
95
                        printf(" %08x/%08x", m_core->v__DOT__spi_in,
96
                                m_core->v__DOT__lldriver__DOT__r_input);
97
                        printf(" %d,%d,%d/%d,%08x%c",
98
                                m_core->v__DOT__spi_busy,
99
                                m_core->v__DOT__spi_valid,
100
                                m_core->v__DOT__spi_wr,
101
                                m_core->v__DOT__spi_len,
102
                                m_core->v__DOT__spi_out,
103
                                (m_core->v__DOT__write_in_progress)?'W':' ');
104
 
105
                        printf("\n");
106
                }
107 16 dgisselq
 
108
                PARENT::tick();
109
        }
110
 
111
        bool    bombed(void) const { return m_bomb; }
112
 
113
};
114
 
115
#define ERASEFLAG       0x80000000
116
#define DISABLEWP       0x10000000
117
#define ENABLEWP        0x00000000
118
#define NPAGES          256
119
#define SZPAGEB         256
120
#define SZPAGEW         (SZPAGEB>>2)
121
#define SECTORSZW       (NPAGES * SZPAGEW)
122
#define SECTORSZB       (NPAGES * SZPAGEB)
123
#define RDBUFSZ         (NPAGES * SZPAGEW)
124
 
125
int main(int  argc, char **argv) {
126
        Verilated::commandArgs(argc, argv);
127
        QSPIFLASH_TB    *tb = new QSPIFLASH_TB;
128
        const char      *DEV_RANDOM = "/dev/urandom";
129
        unsigned        rdv;
130
        unsigned        *rdbuf;
131
 
132 17 dgisselq
        // tb->opentrace("qspi.vcd");
133 16 dgisselq
 
134
        tb->load(DEV_RANDOM);
135
        rdbuf = new unsigned[RDBUFSZ];
136
        tb->setflash(0,0);
137
 
138
        tb->tick();
139
        rdv = tb->wb_read(0);
140
        printf("READ[0] = %04x\n", rdv);
141
        if (rdv != 0)
142
                goto test_failure;
143
 
144
        tb->tick();
145
        if (tb->bombed())
146
                goto test_failure;
147
 
148
        for(int i=0; (i<1000)&&(!tb->bombed()); i++) {
149
                unsigned        tblv;
150
                tblv = (*tb)[(i<<2)];
151
                rdv = tb->wb_read(i<<2);
152
 
153
                if(tblv != rdv) {
154
                        printf("BOMB(INITIAL/SINGLE-READ): READ[%08x] %08x, EXPECTED %08x\n",
155
                                (i<<2), rdv, tblv);
156
                        goto test_failure;
157
                        break;
158
                } else printf("MATCH: %08x == %08x\n", rdv, tblv);
159
        }
160
 
161
        printf("SINGLE-READ TEST PASSES\n");
162
 
163
        for(int i=0; i<1000; i++)
164
                rdbuf[i] = -1;
165
        tb->wb_read(1000, 1000, rdbuf);
166
        if (tb->bombed())
167
                goto    test_failure;
168
        for(int i=0; i<1000; i++) {
169
                if ((*tb)[(i<<2)+1000] != rdbuf[i]) {
170
                        printf("BOMB: V-READ[%08x] %08x, EXPECTED %08x\n", 1000+i, rdv, (*tb)[i+1000]);
171
                        goto    test_failure;
172
                }
173
        } if (tb->bombed())
174
                goto test_failure;
175
        printf("VECTOR TEST PASSES!\n");
176
 
177
        // Read the status register
178
/*
179
        printf("ID[%2d]-RG = %08x\n", 0, rdv = tb->wb_read(8+0));
180
        if (rdv != 0x20ba1810) {
181
                printf("BOMB: ID[%2d]-RG = %08x != %08x\n", 0, rdv,
182
                        0x20ba1810);
183
                goto test_failure;
184
        }
185
 
186
        for(int i=1; i<5; i++)
187
                printf("ID[%2d]-RG = %02x\n", i, tb->wb_read(8+i));
188
        if (tb->bombed())
189
                goto test_failure;
190
*/
191
 
192
 
193
        printf("Attempting to switch in Quad mode\n");
194
        // tb->wb_write(4, (tb->wb_read(4)&0x07f)); // Adjust EVconfig
195
 
196
        for(int i=0; (i<1000)&&(!tb->bombed()); i++) {
197
                unsigned        tblv;
198
                tblv = (*tb)[(i<<2)];
199
                rdv = tb->wb_read((i<<2));
200
 
201
                if(tblv != rdv) {
202
                        printf("BOMB: Q-READ/SINGLE %08x, EXPECTED %08x\n", rdv, tblv);
203
                        goto test_failure;
204
                        break;
205
                } else printf("MATCH: %08x == %08x\n", rdv, tblv);
206
        } tb->wb_read(1000, 1000, rdbuf);
207
        if (tb->bombed())
208
                goto    test_failure;
209
        for(int i=0; i<1000; i++) {
210
                if ((*tb)[(i<<2)+1000] != rdbuf[i]) {
211
                        printf("BOMB: Q-READ/VECTOR %08x, EXPECTED %08x\n", rdv, (*tb)[i+1000]);
212
                        goto    test_failure;
213
                }
214
        } printf("VECTOR TEST PASSES! (QUAD)\n");
215
 
216
        printf("Attempting to switch to Quad mode with XIP\n");
217
        tb->wb_write(3, tb->wb_read(3)|0x08);
218
        // tb->wb_write(0, 0x22000000);
219
 
220
        printf("Attempting to read in Quad mode, using XIP mode\n");
221
        for(int i=0; (i<1000)&&(!tb->bombed()); i++) {
222
                unsigned        tblv;
223
                tblv = (*tb)[(i<<2)];
224
                rdv = tb->wb_read((i<<2));
225
 
226
                if(tblv != rdv) {
227
                        printf("BOMB: Q-READ/XIP %08x, EXPECTED %08x\n", rdv, tblv);
228
                        goto test_failure;
229
                        break;
230
                } else printf("MATCH: %08x == %08x\n", rdv, tblv);
231
        }
232
 
233
        // Try a vector read
234
        tb->wb_read(1000, 1000, rdbuf);
235
        if (tb->bombed())
236
                goto    test_failure;
237
        for(int i=0; i<1000; i++) {
238
                if ((*tb)[(i<<2)+1000] != rdbuf[i]) {
239
                        printf("BOMB: Q-READ/XIP/VECTOR %08x, EXPECTED %08x\n", rdv, (*tb)[i+1000]);
240
                        goto    test_failure;
241
                }
242
        } printf("VECTOR TEST PASSES! (QUAD+XIP)\n");
243
 
244
        rdbuf[0] = tb->wb_read(1023);
245
        rdbuf[1] = tb->wb_read(2048);
246
 
247
 
248
        // Make sure, for testing purposes, that the words preceeding the
249
        // sector we are going to erase and following it don't look like they've
250
        // already been erased.
251
        if ((*tb)[SECTORSZW-1] == 0xffffffff)
252
                tb->set(SECTORSZW, 0);
253
        if ((*tb)[2*SECTORSZW] == 0xffffffff)
254
                tb->set(2*SECTORSZW, 0);
255
 
256
        printf("Turning off write-protect, calling WEL\n");
257
        tb->wb_ctrl_write(0, DISABLEWP);
258
 
259
        /*
260
        if (tb->write_protect()) {
261
                printf("WRITE PROTECT ISN\'T OFF YET, EVEN THOUGH WEL ISSUED\n");
262
                goto test_failure;
263
        } */
264
 
265
        printf("Attempting to erase subsector 1\n");
266
        tb->wb_ctrl_write(0, ERASEFLAG | (1*SECTORSZW));
267
 
268
        /*
269
        if (!tb->write_in_progress()) {
270
                printf("BOMB: Write in progress is false!\n");
271
                goto test_failure;
272
        }
273
        */
274
 
275
        while (tb->wb_ctrl_read(0)&ERASEFLAG)
276
                ;
277
 
278
        /*
279
        if (tb->write_in_progress()) {
280
                printf("BOMB: No write in progress\n");
281
                goto test_failure;
282
        }
283
        */
284
 
285
        printf("Checking that the erase was successful\n");
286
        for(int i=SECTORSZB; i<SECTORSZB*2; i+=4) {
287
                if ((*tb)[i] != 0xffffffff) {
288
                        printf("BOMB: Erase of [%08x] was unsuccessful, FLASH[%08x] = %08x\n", i, i, (*tb)[i]);
289
                        goto test_failure;
290
                }
291
        }
292
 
293
        // Make sure we didn't erase anything else
294
        if ((*tb)[SECTORSZB-4] == 0xffffffff) {
295
                printf("BOMB: Post write check #2, the prior address changed\n");
296
                goto test_failure;
297
        } if ((*tb)[2*SECTORSZB] == 0xffffffff) {
298
                printf("BOMB: Post write check #2, the next address changed\n");
299
                goto test_failure;
300
        }
301
 
302
        if (tb->wb_read(SECTORSZB-4) != (*tb)[SECTORSZB-4]) {
303
                printf("BOMB: Post write check #2, the prior address changed\n");
304
                goto test_failure;
305
        } if (tb->wb_read(2*SECTORSZB) != (*tb)[2*SECTORSZB]) {
306
                printf("BOMB: Post write check #2, the next address changed\n");
307
                goto test_failure;
308
        }
309
 
310
 
311
 
312
        printf("Test: Trying a single word write\n");
313
 
314
        // Try to execute a single write
315
        tb->wb_ctrl_write(0,DISABLEWP);
316
        tb->wb_write(SECTORSZB, 0x12345678);
317
 
318
        while (tb->wb_ctrl_read(0)&ERASEFLAG)
319
                ;
320
 
321
        if (tb->wb_read(SECTORSZB) != 0x12345678) {
322
                printf("BOMB: Single (not page) write result incorrect: %08x != 0x12345678\n", tb->wb_read(SECTORSZB));
323
                goto test_failure;
324
        }
325
 
326
 
327
        // Let's load up a sectors worth of random data into our buffer
328
        {
329
                FILE    *fp;
330
                fp = fopen(DEV_RANDOM, "r");
331
                assert(RDBUFSZ == fread(rdbuf, sizeof(unsigned), RDBUFSZ, fp));
332
                fclose(fp);
333
                rdbuf[0] = 0x12345678;
334
        }
335
 
336
        // Now, let's try writing this sector ... one page at a time.
337
        for(int p=0; p<NPAGES; p++) {
338
 
339
                printf("Writing page %d\n", p);
340
                tb->wb_ctrl_write(0, DISABLEWP);
341
                // if (tb->write_protect()) goto        test_failure;
342
                tb->wb_write(SECTORSZB+p*SZPAGEB, SZPAGEW, &rdbuf[p*SZPAGEW]);
343
 
344
                while (tb->wb_ctrl_read(0)&ERASEFLAG)
345
                        ;
346
 
347
                printf("Checking page %d\n", p);
348
                for(int i=0; i<SZPAGEW; i++) {
349
                        if (rdbuf[p*SZPAGEW+i] != (*tb)[SECTORSZB+p*SZPAGEB+(i<<2)]) {
350
                                printf("BOMB: Write check, Addr[%08x]\n", SECTORSZB+p*SZPAGEB+(i<<2));
351
                                goto test_failure;
352
                        }
353
                }
354
        }
355
 
356
        printf("SUCCESS!!\n");
357
        exit(EXIT_SUCCESS);
358
test_failure:
359
        printf("FAIL-HERE\n");
360
        for(int i=0; i<8; i++)
361
                tb->tick();
362
        printf("TEST FAILED\n");
363
        exit(EXIT_FAILURE);
364
}

powered by: WebSVN 2.1.0

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