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

Subversion Repositories wbscope

[/] [wbscope/] [trunk/] [bench/] [cpp/] [wb_tb.h] - Blame information for rev 13

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 13 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    wb_tb.cpp
4
//
5
// Project:     WBScope, a wishbone hosted scope
6
//
7
// Purpose:     To provide a fairly generic interface wrapper to a wishbone bus,
8
//              that can then be used to create a test-bench class.
9
//
10
// Creator:     Dan Gisselquist, Ph.D.
11
//              Gisselquist Technology, LLC
12
//
13
////////////////////////////////////////////////////////////////////////////////
14
//
15
// Copyright (C) 2015-2017, Gisselquist Technology, LLC
16
//
17
// This program is free software (firmware): you can redistribute it and/or
18
// modify it under the terms of  the GNU General Public License as published
19
// by the Free Software Foundation, either version 3 of the License, or (at
20
// your option) any later version.
21
//
22
// This program is distributed in the hope that it will be useful, but WITHOUT
23
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
24
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
25
// for more details.
26
//
27
// You should have received a copy of the GNU General Public License along
28
// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no
29
// target there if the PDF file isn't present.)  If not, see
30
// <http://www.gnu.org/licenses/> for a copy.
31
//
32
// License:     GPL, v3, as defined and found on www.gnu.org,
33
//              http://www.gnu.org/licenses/gpl.html
34
//
35
//
36
////////////////////////////////////////////////////////////////////////////////
37
//
38
//
39
#include <stdio.h>
40
#include <stdlib.h>
41
 
42
#include <verilated.h>
43
#include <verilated_vcd_c.h>
44
#include "testb.h"
45
#include "devbus.h"
46
 
47
const int       BOMBCOUNT = 32;
48
 
49
template <class VA>     class   WB_TB : public TESTB<VA>, public DEVBUS {
50
#ifdef  WBERR
51
        bool    m_buserr;
52
#endif
53
#ifdef  INTERRUPTWIRE
54
        bool    m_interrupt;
55
#endif
56
public:
57
        typedef uint32_t        BUSW;
58
 
59
        bool    m_bomb;
60
 
61
        WB_TB(void) {
62
                m_bomb = false;
63
                TESTB<VA>::m_core->i_wb_cyc = 0;
64
                TESTB<VA>::m_core->i_wb_stb = 0;
65
#ifdef  WBERR
66
                m_buserr = false;
67
#endif
68
#ifdef  INTERRUPTWIRE
69
                m_interrupt = false;
70
#endif
71
        }
72
 
73
        virtual void    close(void) {
74
                TESTB<VA>::closetrace();
75
        }
76
 
77
        virtual void    kill(void) {
78
                close();
79
        }
80
 
81
#ifdef  INTERRUPTWIRE
82
        virtual void    tick(void) {
83
                TESTB<VA>::tick();
84
                if (TESTB<VA>::m_core->INTERRUPTWIRE)
85
                        m_interrupt = true;
86
        }
87
#endif
88
#define TICK    this->tick
89
 
90
        void    idle(const unsigned counts = 1) {
91
                TESTB<VA>::m_core->i_wb_cyc = 0;
92
                TESTB<VA>::m_core->i_wb_stb = 0;
93
                for(unsigned k=0; k<counts; k++) {
94
                        this->tick();
95
                        assert(!TESTB<VA>::m_core->o_wb_ack);
96
                }
97
        }
98
 
99
        BUSW readio(BUSW a) {
100
                int             errcount = 0;
101
                BUSW            result;
102
 
103
                // printf("WB-READM(%08x)\n", a);
104
 
105
                TESTB<VA>::m_core->i_wb_cyc = 1;
106
                TESTB<VA>::m_core->i_wb_stb = 1;
107
                TESTB<VA>::m_core->i_wb_we  = 0;
108
                TESTB<VA>::m_core->i_wb_addr= (a>>2);
109
 
110
                if (TESTB<VA>::m_core->o_wb_stall) {
111
                        while((errcount++ < BOMBCOUNT)&&(TESTB<VA>::m_core->o_wb_stall)) {
112
                                TICK();
113
#ifdef  WBERR
114
                                if (TESTB<VA>::m_core->WBERR) {
115
                                        m_buserr = true;
116
                                        TESTB<VA>::m_core->i_wb_cyc = 0;
117
                                        TESTB<VA>::m_core->i_wb_stb = 0;
118
                                        return -1;
119
                                }
120
#endif
121
                        }
122
                } TICK();
123
 
124
                TESTB<VA>::m_core->i_wb_stb = 0;
125
 
126
                while((errcount++ <  BOMBCOUNT)&&(!TESTB<VA>::m_core->o_wb_ack)) {
127
                        TICK();
128
#ifdef  WBERR
129
                        if (TESTB<VA>::m_core->WBERR) {
130
                                m_buserr = true;
131
                                TESTB<VA>::m_core->i_wb_cyc = 0;
132
                                TESTB<VA>::m_core->i_wb_stb = 0;
133
                                return -1;
134
                        }
135
#endif
136
                }
137
 
138
 
139
                result = TESTB<VA>::m_core->o_wb_data;
140
 
141
                // Release the bus
142
                TESTB<VA>::m_core->i_wb_cyc = 0;
143
                TESTB<VA>::m_core->i_wb_stb = 0;
144
 
145
                if(errcount >= BOMBCOUNT) {
146
                        printf("WB/SR-BOMB: NO RESPONSE AFTER %d CLOCKS\n", errcount);
147
                        m_bomb = true;
148
                } else if (!TESTB<VA>::m_core->o_wb_ack) {
149
                        printf("WB/SR-BOMB: NO ACK, NO TIMEOUT\n");
150
                        m_bomb = true;
151
                }
152
                TICK();
153
 
154
                assert(!TESTB<VA>::m_core->o_wb_ack);
155
                assert(!TESTB<VA>::m_core->o_wb_stall);
156
 
157
                return result;
158
        }
159
 
160
        void    readv(const BUSW a, int len, BUSW *buf, const int inc=1) {
161
                int             errcount = 0;
162
                int             THISBOMBCOUNT = BOMBCOUNT * len;
163
                int             cnt, rdidx;
164
 
165
                printf("WB-READM(%08x, %d)\n", a, len);
166
                TESTB<VA>::m_core->i_wb_cyc  = 0;
167
                TESTB<VA>::m_core->i_wb_stb  = 0;
168
 
169
                while((errcount++ < BOMBCOUNT)&&(TESTB<VA>::m_core->o_wb_stall))
170
                        TICK();
171
 
172
                if (errcount >= BOMBCOUNT) {
173
                        printf("WB-READ(%d): Setting bomb to true (errcount = %d)\n", __LINE__, errcount);
174
                        m_bomb = true;
175
                        return;
176
                }
177
 
178
                errcount = 0;
179
 
180
                TESTB<VA>::m_core->i_wb_cyc  = 1;
181
                TESTB<VA>::m_core->i_wb_stb  = 1;
182
                TESTB<VA>::m_core->i_wb_we   = 0;
183
                TESTB<VA>::m_core->i_wb_addr = (a>>2);
184
 
185
                rdidx =0; cnt = 0;
186
 
187
                do {
188
                        int     s;
189
                        TESTB<VA>::m_core->i_wb_stb = ((rand()&7)!=0) ? 1:0;
190
                        s = ((TESTB<VA>::m_core->i_wb_stb)
191
                                &&(TESTB<VA>::m_core->o_wb_stall==0))?0:1;
192
                        TICK();
193
                        TESTB<VA>::m_core->i_wb_addr += (inc&(s^1))?4:0;
194
                        cnt += (s^1);
195
                        if (TESTB<VA>::m_core->o_wb_ack)
196
                                buf[rdidx++] = TESTB<VA>::m_core->o_wb_data;
197
#ifdef  WBERR
198
                        if (TESTB<VA>::m_core->WBERR) {
199
                                m_buserr = true;
200
                                TESTB<VA>::m_core->i_wb_cyc = 0;
201
                                TESTB<VA>::m_core->i_wb_stb = 0;
202
                                return -1;
203
                        }
204
#endif
205
                } while((cnt < len)&&(errcount++ < THISBOMBCOUNT));
206
 
207
                TESTB<VA>::m_core->i_wb_stb = 0;
208
 
209
                while((rdidx < len)&&(errcount++ < THISBOMBCOUNT)) {
210
                        TICK();
211
                        if (TESTB<VA>::m_core->o_wb_ack)
212
                                buf[rdidx++] = TESTB<VA>::m_core->o_wb_data;
213
#ifdef  WBERR
214
                        if (TESTB<VA>::m_core->WBERR) {
215
                                m_buserr = true;
216
                                TESTB<VA>::m_core->i_wb_cyc = 0;
217
                                TESTB<VA>::m_core->i_wb_stb = 0;
218
                                return -1;
219
                        }
220
#endif
221
                }
222
 
223
                // Release the bus
224
                TESTB<VA>::m_core->i_wb_cyc = 0;
225
 
226
                if(errcount >= THISBOMBCOUNT) {
227
                        printf("WB/PR-BOMB: NO RESPONSE AFTER %d CLOCKS\n", errcount);
228
                        m_bomb = true;
229
                } else if (!TESTB<VA>::m_core->o_wb_ack) {
230
                        printf("WB/PR-BOMB: NO ACK, NO TIMEOUT\n");
231
                        m_bomb = true;
232
                }
233
                TICK();
234
                assert(!TESTB<VA>::m_core->o_wb_ack);
235
        }
236
 
237
        void    readi(const BUSW a, const int len, BUSW *buf) {
238
                return readv(a, len, buf, 1);
239
        }
240
 
241
        void    readz(const BUSW a, const int len, BUSW *buf) {
242
                return readv(a, len, buf, 0);
243
        }
244
 
245
        void    writeio(const BUSW a, const BUSW v) {
246
                int errcount = 0;
247
 
248
                printf("WB-WRITEM(%08x) <= %08x\n", a, v);
249
                TESTB<VA>::m_core->i_wb_cyc = 1;
250
                TESTB<VA>::m_core->i_wb_stb = 1;
251
                TESTB<VA>::m_core->i_wb_we  = 1;
252
                TESTB<VA>::m_core->i_wb_addr= (a>>2);
253
                TESTB<VA>::m_core->i_wb_data= v;
254
                // TESTB<VA>::m_core->i_wb_sel = 0x0f;
255
 
256
                if (TESTB<VA>::m_core->o_wb_stall)
257
                        while((errcount++ < BOMBCOUNT)&&(TESTB<VA>::m_core->o_wb_stall)) {
258
                                printf("Stalled, so waiting, errcount=%d\n", errcount);
259
                                TICK();
260
#ifdef  WBERR
261
                                if (m_core->WBERR) {
262
                                        m_buserr = true;
263
                                        TESTB<VA>::m_core->i_wb_cyc = 0;
264
                                        TESTB<VA>::m_core->i_wb_stb = 0;
265
                                        return;
266
                                }
267
#endif
268
                        }
269
                TICK();
270
#ifdef  WBERR
271
                if (m_core->WBERR) {
272
                        m_buserr = true;
273
                        TESTB<VA>::m_core->i_wb_cyc = 0;
274
                        TESTB<VA>::m_core->i_wb_stb = 0;
275
                        return;
276
                }
277
#endif
278
 
279
                TESTB<VA>::m_core->i_wb_stb = 0;
280
 
281
                while((errcount++ <  BOMBCOUNT)&&(!TESTB<VA>::m_core->o_wb_ack)) {
282
                        TICK();
283
#ifdef  WBERR
284
                        if (m_core->WBERR) {
285
                                m_buserr = true;
286
                                TESTB<VA>::m_core->i_wb_cyc = 0;
287
                                TESTB<VA>::m_core->i_wb_stb = 0;
288
                                return;
289
                        }
290
#endif
291
                }
292
                TICK();
293
 
294
                // Release the bus?
295
                TESTB<VA>::m_core->i_wb_cyc = 0;
296
                TESTB<VA>::m_core->i_wb_stb = 0;
297
 
298
                if(errcount >= BOMBCOUNT) {
299
                        printf("WB/SW-BOMB: NO RESPONSE AFTER %d CLOCKS (LINE=%d)\n",errcount, __LINE__);
300
                        m_bomb = true;
301
                } TICK();
302
#ifdef  WBERR
303
                if (m_core->WBERR) {
304
                        m_buserr = true;
305
                        TESTB<VA>::m_core->i_wb_cyc = 0;
306
                        TESTB<VA>::m_core->i_wb_stb = 0;
307
                        return;
308
                }
309
#endif
310
                assert(!TESTB<VA>::m_core->o_wb_ack);
311
                assert(!TESTB<VA>::m_core->o_wb_stall);
312
        }
313
 
314
        void    writev(const BUSW a, const int ln, const BUSW *buf, const int inc=1) {
315
                unsigned errcount = 0, nacks = 0;
316
 
317
                printf("WB-WRITEM(%08x, %d, ...)\n", a, ln);
318
                TESTB<VA>::m_core->i_wb_cyc = 1;
319
                TESTB<VA>::m_core->i_wb_stb = 1;
320
                TESTB<VA>::m_core->i_wb_we  = 1;
321
                TESTB<VA>::m_core->i_wb_addr= (a>>2);
322
                // TESTB<VA>::m_core->i_wb_sel = 0x0f;
323
                for(unsigned stbcnt=0; stbcnt<ln; stbcnt++) {
324
                        // m_core->i_wb_addr= a+stbcnt;
325
                        TESTB<VA>::m_core->i_wb_data= buf[stbcnt];
326
                        errcount = 0;
327
 
328
                        while((errcount++ < BOMBCOUNT)&&(TESTB<VA>::m_core->o_wb_stall)) {
329
                                TICK();
330
                                if (TESTB<VA>::m_core->o_wb_ack)
331
                                        nacks++;
332
#ifdef  WBERR
333
                                if (m_core->WBERR) {
334
                                        m_buserr = true;
335
                                        TESTB<VA>::m_core->i_wb_cyc = 0;
336
                                        TESTB<VA>::m_core->i_wb_stb = 0;
337
                                        return;
338
                                }
339
#endif
340
                        }
341
                        // Tick, now that we're not stalled.  This is the tick
342
                        // that gets accepted.
343
                        TICK();
344
                        if (TESTB<VA>::m_core->o_wb_ack) nacks++;
345
#ifdef  WBERR
346
                        if (m_core->WBERR) {
347
                                m_buserr = true;
348
                                TESTB<VA>::m_core->i_wb_cyc = 0;
349
                                TESTB<VA>::m_core->i_wb_stb = 0;
350
                                return;
351
                        }
352
#endif
353
 
354
                        // Now update the address
355
                        TESTB<VA>::m_core->i_wb_addr += (inc)?4:0;
356
                }
357
 
358
                TESTB<VA>::m_core->i_wb_stb = 0;
359
 
360
                errcount = 0;
361
                while((nacks < ln)&&(errcount++ < BOMBCOUNT)) {
362
                        TICK();
363
                        if (TESTB<VA>::m_core->o_wb_ack) {
364
                                nacks++;
365
                                errcount = 0;
366
                        }
367
#ifdef  WBERR
368
                        if (m_core->WBERR) {
369
                                m_buserr = true;
370
                                TESTB<VA>::m_core->i_wb_cyc = 0;
371
                                TESTB<VA>::m_core->i_wb_stb = 0;
372
                                return;
373
                        }
374
#endif
375
                }
376
 
377
                // Release the bus
378
                TESTB<VA>::m_core->i_wb_cyc = 0;
379
                TESTB<VA>::m_core->i_wb_stb = 0;
380
 
381
                if(errcount >= BOMBCOUNT) {
382
                        printf("WB/PW-BOMB: NO RESPONSE AFTER %d CLOCKS (LINE=%d)\n",errcount,__LINE__);
383
                        m_bomb = true;
384
                }
385
                TICK();
386
                assert(!TESTB<VA>::m_core->o_wb_ack);
387
                assert(!TESTB<VA>::m_core->o_wb_stall);
388
        }
389
 
390
        void    writei(const BUSW a, const int ln, const BUSW *buf) {
391
                writev(a, ln, buf, 1);
392
        }
393
 
394
        void    writez(const BUSW a, const int ln, const BUSW *buf) {
395
                writev(a, ln, buf, 0);
396
        }
397
 
398
 
399
        bool    bombed(void) const { return m_bomb; }
400
 
401
        // bool debug(void) const       { return m_debug; }
402
        // bool debug(bool nxtv)        { return m_debug = nxtv; }
403
 
404
        bool    poll(void) {
405
#ifdef  INTERRUPTWIRE
406
                return (m_interrupt)||(TESTB<VA>::m_core->INTERRUPTWIRE != 0);
407
#else
408
                return false;
409
#endif
410
        }
411
 
412
        bool    bus_err(void) const {
413
#ifdef  WBERR
414
                return m_buserr;
415
#else
416
                return false;
417
#endif
418
        }
419
 
420
        void    reset_err(void) {
421
#ifdef  WBERR
422
                m_buserr = false;;
423
#endif
424
        }
425
 
426
        void    usleep(unsigned msec) {
427
#ifdef  CLKRATEHZ
428
                unsigned count = CLKRATEHZ / 1000 * msec;
429
#else
430
                // Assume 100MHz if no clockrate is given
431
                unsigned count = 1000*100 * msec;
432
#endif
433
                while(count-- != 0)
434
#ifdef  INTERRUPTWIRE
435
                        if (poll()) return; else
436
#endif
437
                        TICK();
438
        }
439
 
440
        void    clear(void) {
441
#ifdef  INTERRUPTWIRE
442
                m_interrupt = false;
443
#endif
444
        }
445
 
446
        void    wait(void) {
447
#ifdef  INTERRUPTWIRE
448
                while(!poll())
449
                        TICK();
450
#else
451
                assert(("No interrupt defined",0));
452
#endif
453
        }
454
};
455
 

powered by: WebSVN 2.1.0

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