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

Subversion Repositories qspiflash

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

Go to most recent revision | 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
                m_core->i_qspi_dat = (*m_flash)(m_core->o_qspi_cs_n,
74
                        m_core->o_qspi_sck, m_core->o_qspi_dat);
75
 
76
 
77
                printf("%08lx-WB: %s %s/%s %s %s",
78
                        m_tickcount,
79
                        (m_core->i_wb_cyc)?"CYC":"   ",
80
                        (m_core->i_wb_data_stb)?"DSTB":"    ",
81
                        (m_core->i_wb_ctrl_stb)?"CSTB":"    ",
82
                        (m_core->o_wb_stall)?"STALL":"     ",
83
                        (m_core->o_wb_ack)?"ACK":"   ");
84
                printf(" %s@0x%08x[%08x/%08x]",
85
                        (m_core->i_wb_we)?"W":"R",
86
                        (m_core->i_wb_addr), (m_core->i_wb_data),
87
                        (m_core->o_wb_data));
88
                printf(" QSPI:%x:%x/%02x/%02x/%2d",
89
                        m_core->i_qspi_dat, m_core->o_qspi_mod,
90
                        m_core->v__DOT__state,
91
                        m_core->v__DOT__lldriver__DOT__state,
92
                        m_core->v__DOT__lldriver__DOT__spi_len);
93
                printf(" %08x/%08x", m_core->v__DOT__spi_in,
94
                        m_core->v__DOT__lldriver__DOT__r_input);
95
                printf(" %d,%d,%d/%d,%08x%c",
96
                        m_core->v__DOT__spi_busy,
97
                        m_core->v__DOT__spi_valid,
98
                        m_core->v__DOT__spi_wr,
99
                        m_core->v__DOT__spi_len,
100
                        m_core->v__DOT__spi_out,
101
                        (m_core->v__DOT__write_in_progress)?'W':' ');
102
 
103
                printf("\n");
104
 
105
                PARENT::tick();
106
        }
107
 
108
        bool    bombed(void) const { return m_bomb; }
109
 
110
};
111
 
112
#define ERASEFLAG       0x80000000
113
#define DISABLEWP       0x10000000
114
#define ENABLEWP        0x00000000
115
#define NPAGES          256
116
#define SZPAGEB         256
117
#define SZPAGEW         (SZPAGEB>>2)
118
#define SECTORSZW       (NPAGES * SZPAGEW)
119
#define SECTORSZB       (NPAGES * SZPAGEB)
120
#define RDBUFSZ         (NPAGES * SZPAGEW)
121
 
122
int main(int  argc, char **argv) {
123
        Verilated::commandArgs(argc, argv);
124
        QSPIFLASH_TB    *tb = new QSPIFLASH_TB;
125
        const char      *DEV_RANDOM = "/dev/urandom";
126
        unsigned        rdv;
127
        unsigned        *rdbuf;
128
 
129
        tb->opentrace("qspi.vcd");
130
 
131
        tb->load(DEV_RANDOM);
132
        rdbuf = new unsigned[RDBUFSZ];
133
        tb->setflash(0,0);
134
 
135
        tb->tick();
136
        rdv = tb->wb_read(0);
137
        printf("READ[0] = %04x\n", rdv);
138
        if (rdv != 0)
139
                goto test_failure;
140
 
141
        tb->tick();
142
        if (tb->bombed())
143
                goto test_failure;
144
 
145
        for(int i=0; (i<1000)&&(!tb->bombed()); i++) {
146
                unsigned        tblv;
147
                tblv = (*tb)[(i<<2)];
148
                rdv = tb->wb_read(i<<2);
149
 
150
                if(tblv != rdv) {
151
                        printf("BOMB(INITIAL/SINGLE-READ): READ[%08x] %08x, EXPECTED %08x\n",
152
                                (i<<2), rdv, tblv);
153
                        goto test_failure;
154
                        break;
155
                } else printf("MATCH: %08x == %08x\n", rdv, tblv);
156
        }
157
 
158
        printf("SINGLE-READ TEST PASSES\n");
159
 
160
        for(int i=0; i<1000; i++)
161
                rdbuf[i] = -1;
162
        tb->wb_read(1000, 1000, rdbuf);
163
        if (tb->bombed())
164
                goto    test_failure;
165
        for(int i=0; i<1000; i++) {
166
                if ((*tb)[(i<<2)+1000] != rdbuf[i]) {
167
                        printf("BOMB: V-READ[%08x] %08x, EXPECTED %08x\n", 1000+i, rdv, (*tb)[i+1000]);
168
                        goto    test_failure;
169
                }
170
        } if (tb->bombed())
171
                goto test_failure;
172
        printf("VECTOR TEST PASSES!\n");
173
 
174
        // Read the status register
175
/*
176
        printf("ID[%2d]-RG = %08x\n", 0, rdv = tb->wb_read(8+0));
177
        if (rdv != 0x20ba1810) {
178
                printf("BOMB: ID[%2d]-RG = %08x != %08x\n", 0, rdv,
179
                        0x20ba1810);
180
                goto test_failure;
181
        }
182
 
183
        for(int i=1; i<5; i++)
184
                printf("ID[%2d]-RG = %02x\n", i, tb->wb_read(8+i));
185
        if (tb->bombed())
186
                goto test_failure;
187
*/
188
 
189
 
190
        printf("Attempting to switch in Quad mode\n");
191
        // tb->wb_write(4, (tb->wb_read(4)&0x07f)); // Adjust EVconfig
192
 
193
        for(int i=0; (i<1000)&&(!tb->bombed()); i++) {
194
                unsigned        tblv;
195
                tblv = (*tb)[(i<<2)];
196
                rdv = tb->wb_read((i<<2));
197
 
198
                if(tblv != rdv) {
199
                        printf("BOMB: Q-READ/SINGLE %08x, EXPECTED %08x\n", rdv, tblv);
200
                        goto test_failure;
201
                        break;
202
                } else printf("MATCH: %08x == %08x\n", rdv, tblv);
203
        } tb->wb_read(1000, 1000, rdbuf);
204
        if (tb->bombed())
205
                goto    test_failure;
206
        for(int i=0; i<1000; i++) {
207
                if ((*tb)[(i<<2)+1000] != rdbuf[i]) {
208
                        printf("BOMB: Q-READ/VECTOR %08x, EXPECTED %08x\n", rdv, (*tb)[i+1000]);
209
                        goto    test_failure;
210
                }
211
        } printf("VECTOR TEST PASSES! (QUAD)\n");
212
 
213
        printf("Attempting to switch to Quad mode with XIP\n");
214
        tb->wb_write(3, tb->wb_read(3)|0x08);
215
        // tb->wb_write(0, 0x22000000);
216
 
217
        printf("Attempting to read in Quad mode, using XIP mode\n");
218
        for(int i=0; (i<1000)&&(!tb->bombed()); i++) {
219
                unsigned        tblv;
220
                tblv = (*tb)[(i<<2)];
221
                rdv = tb->wb_read((i<<2));
222
 
223
                if(tblv != rdv) {
224
                        printf("BOMB: Q-READ/XIP %08x, EXPECTED %08x\n", rdv, tblv);
225
                        goto test_failure;
226
                        break;
227
                } else printf("MATCH: %08x == %08x\n", rdv, tblv);
228
        }
229
 
230
        // Try a vector read
231
        tb->wb_read(1000, 1000, rdbuf);
232
        if (tb->bombed())
233
                goto    test_failure;
234
        for(int i=0; i<1000; i++) {
235
                if ((*tb)[(i<<2)+1000] != rdbuf[i]) {
236
                        printf("BOMB: Q-READ/XIP/VECTOR %08x, EXPECTED %08x\n", rdv, (*tb)[i+1000]);
237
                        goto    test_failure;
238
                }
239
        } printf("VECTOR TEST PASSES! (QUAD+XIP)\n");
240
 
241
        rdbuf[0] = tb->wb_read(1023);
242
        rdbuf[1] = tb->wb_read(2048);
243
 
244
 
245
        // Make sure, for testing purposes, that the words preceeding the
246
        // sector we are going to erase and following it don't look like they've
247
        // already been erased.
248
        if ((*tb)[SECTORSZW-1] == 0xffffffff)
249
                tb->set(SECTORSZW, 0);
250
        if ((*tb)[2*SECTORSZW] == 0xffffffff)
251
                tb->set(2*SECTORSZW, 0);
252
 
253
        printf("Turning off write-protect, calling WEL\n");
254
        tb->wb_ctrl_write(0, DISABLEWP);
255
 
256
        /*
257
        if (tb->write_protect()) {
258
                printf("WRITE PROTECT ISN\'T OFF YET, EVEN THOUGH WEL ISSUED\n");
259
                goto test_failure;
260
        } */
261
 
262
        printf("Attempting to erase subsector 1\n");
263
        tb->wb_ctrl_write(0, ERASEFLAG | (1*SECTORSZW));
264
 
265
        /*
266
        if (!tb->write_in_progress()) {
267
                printf("BOMB: Write in progress is false!\n");
268
                goto test_failure;
269
        }
270
        */
271
 
272
        while (tb->wb_ctrl_read(0)&ERASEFLAG)
273
                ;
274
 
275
        /*
276
        if (tb->write_in_progress()) {
277
                printf("BOMB: No write in progress\n");
278
                goto test_failure;
279
        }
280
        */
281
 
282
        printf("Checking that the erase was successful\n");
283
        for(int i=SECTORSZB; i<SECTORSZB*2; i+=4) {
284
                if ((*tb)[i] != 0xffffffff) {
285
                        printf("BOMB: Erase of [%08x] was unsuccessful, FLASH[%08x] = %08x\n", i, i, (*tb)[i]);
286
                        goto test_failure;
287
                }
288
        }
289
 
290
        // Make sure we didn't erase anything else
291
        if ((*tb)[SECTORSZB-4] == 0xffffffff) {
292
                printf("BOMB: Post write check #2, the prior address changed\n");
293
                goto test_failure;
294
        } if ((*tb)[2*SECTORSZB] == 0xffffffff) {
295
                printf("BOMB: Post write check #2, the next address changed\n");
296
                goto test_failure;
297
        }
298
 
299
        if (tb->wb_read(SECTORSZB-4) != (*tb)[SECTORSZB-4]) {
300
                printf("BOMB: Post write check #2, the prior address changed\n");
301
                goto test_failure;
302
        } if (tb->wb_read(2*SECTORSZB) != (*tb)[2*SECTORSZB]) {
303
                printf("BOMB: Post write check #2, the next address changed\n");
304
                goto test_failure;
305
        }
306
 
307
 
308
 
309
        printf("Test: Trying a single word write\n");
310
 
311
        // Try to execute a single write
312
        tb->wb_ctrl_write(0,DISABLEWP);
313
        tb->wb_write(SECTORSZB, 0x12345678);
314
 
315
        while (tb->wb_ctrl_read(0)&ERASEFLAG)
316
                ;
317
 
318
        if (tb->wb_read(SECTORSZB) != 0x12345678) {
319
                printf("BOMB: Single (not page) write result incorrect: %08x != 0x12345678\n", tb->wb_read(SECTORSZB));
320
                goto test_failure;
321
        }
322
 
323
 
324
        // Let's load up a sectors worth of random data into our buffer
325
        {
326
                FILE    *fp;
327
                fp = fopen(DEV_RANDOM, "r");
328
                assert(RDBUFSZ == fread(rdbuf, sizeof(unsigned), RDBUFSZ, fp));
329
                fclose(fp);
330
                rdbuf[0] = 0x12345678;
331
        }
332
 
333
        // Now, let's try writing this sector ... one page at a time.
334
        for(int p=0; p<NPAGES; p++) {
335
 
336
                printf("Writing page %d\n", p);
337
                tb->wb_ctrl_write(0, DISABLEWP);
338
                // if (tb->write_protect()) goto        test_failure;
339
                tb->wb_write(SECTORSZB+p*SZPAGEB, SZPAGEW, &rdbuf[p*SZPAGEW]);
340
 
341
                while (tb->wb_ctrl_read(0)&ERASEFLAG)
342
                        ;
343
 
344
                printf("Checking page %d\n", p);
345
                for(int i=0; i<SZPAGEW; i++) {
346
                        if (rdbuf[p*SZPAGEW+i] != (*tb)[SECTORSZB+p*SZPAGEB+(i<<2)]) {
347
                                printf("BOMB: Write check, Addr[%08x]\n", SECTORSZB+p*SZPAGEB+(i<<2));
348
                                goto test_failure;
349
                        }
350
                }
351
        }
352
 
353
        printf("SUCCESS!!\n");
354
        exit(EXIT_SUCCESS);
355
test_failure:
356
        printf("FAIL-HERE\n");
357
        for(int i=0; i<8; i++)
358
                tb->tick();
359
        printf("TEST FAILED\n");
360
        exit(EXIT_FAILURE);
361
}

powered by: WebSVN 2.1.0

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