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

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [sim/] [verilator/] [zipmmu_tb.cpp] - Blame information for rev 209

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 204 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    zipmmu_tb.cpp
4
//
5
// Project:     Zip CPU -- a small, lightweight, RISC CPU soft core
6
//
7
// Purpose:     A quick test bench to determine if the zipmmu module works.
8
//              This test bench does nothing to determine whether or not it
9
//      is connected properly, but only tests whether or not the zipmmu works
10
//      as it is supposed to.
11
//
12
//
13
// Creator:     Dan Gisselquist, Ph.D.
14
//              Gisselquist Technology, LLC
15
//
16
////////////////////////////////////////////////////////////////////////////////
17
//
18
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
19
//
20
// This program is free software (firmware): you can redistribute it and/or
21
// modify it under the terms of  the GNU General Public License as published
22
// by the Free Software Foundation, either version 3 of the License, or (at
23
// your option) any later version.
24
//
25
// This program is distributed in the hope that it will be useful, but WITHOUT
26
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
27
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
28
// for more details.
29
//
30 209 dgisselq
// You should have received a copy of the GNU General Public License along
31
// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no
32
// target there if the PDF file isn't present.)  If not, see
33
// <http://www.gnu.org/licenses/> for a copy.
34
//
35 204 dgisselq
// License:     GPL, v3, as defined and found on www.gnu.org,
36
//              http://www.gnu.org/licenses/gpl.html
37
//
38
//
39
////////////////////////////////////////////////////////////////////////////////
40
//
41
//
42
#include <stdio.h>
43
 
44
#include <verilated.h>
45
#include <verilated_vcd_c.h>
46
#include "testb.h"
47
#include "Vzipmmu_tb.h"
48
 
49
#define MMUFLAG_RONW    8 // Read only (not writeable)
50 209 dgisselq
#define MMUFLAG_EXE     4 // Page may be executed
51 204 dgisselq
#define MMUFLAG_CCHE    2 // Cachable
52 209 dgisselq
#define MMUFLAG_ACCS    1 // Accessed
53
#define ROFLAG  8       // This page is read-only
54
#define EXFLAG  4       // This page is executable
55
#define CHFLAG  2       // This page may be cached
56
#define AXFLAG  1       // This page has been accessed since loading
57 204 dgisselq
 
58 209 dgisselq
#define setup_stb       i_ctrl_cyc_stb
59
#define setup_ack       o_rtn_ack
60
#define setup_stall     o_rtn_stall
61
#define setup_data      o_rtn_data
62
#define mem_cyc         v__DOT__mem_cyc
63
#define mem_stb         v__DOT__mem_stb
64
#define mem_we          v__DOT__mem_we
65
#define mem_r_we        v__DOT__mut__DOT__r_we
66
#define mem_r_valid     v__DOT__mut__DOT__r_valid
67
#define mem_addr        v__DOT__mem_addr
68
#define mem_err         v__DOT__mem_err
69
#define wr_vtable       v__DOT__mut__DOT__wr_vtable
70
#define wr_ptable       v__DOT__mut__DOT__wr_ptable
71
#define wr_control      v__DOT__mut__DOT__wr_control
72
#define z_context       __PVT__mut__DOT__z_context
73
#define context_word    v__DOT__mut__DOT__r_context_word
74
#define r_pending       v__DOT__mut__DOT__r_pending
75
#define r_we            v__DOT__mut__DOT__r_we
76
#define r_valid         v__DOT__mut__DOT__r_valid
77
#define r_addr          v__DOT__mut__DOT__r_addr
78
#define r_data          v__DOT__mut__DOT__r_data
79
 
80
#define R_CONTROL               0
81
#define R_STATUS                4
82
#define R_TABLESZ(LGSZ)         (8<<LGSZ)
83
#define R_ENTRYSZ(LGSZ,K)       (R_TABLESZ(LGSZ)+(K<<3))
84
#define R_TABLE         (8<<LGTBL)
85
#define R_VENTRY(K)     ((8<<LGTBL)+(K<<3))
86
#define R_PENTRY(K)     (R_VENTRY(K)+4)
87
#define LOCONTEXT(C)    ((C<<4)&((1<<LGPGSZ)-1))
88
#define HICONTEXT(C)    (((C>>(LGPGSZ-4))<<4)&((1<<LGPGSZ)-1))
89
 
90 204 dgisselq
const int       BOMBCOUNT = 32,
91
                LGMEMSIZE = 15;
92
 
93
class   ZIPMMU_TB : public TESTB<Vzipmmu_tb> {
94
        long            m_tickcount;
95
        bool            m_bomb, m_miss, m_err, m_debug;
96
        int             m_last_tlb_index;
97
public:
98
 
99
        ZIPMMU_TB(void) {
100
                m_debug = true;
101
                m_last_tlb_index = 0;
102
        }
103
 
104
        void    tick(void) {
105
 
106
                TESTB<Vzipmmu_tb>::tick();
107
 
108
                bool    writeout = true;
109
 
110
                if ((m_debug)&&(writeout)) {
111
                        printf("%08lx-MMU: ", m_tickcount);
112 209 dgisselq
                        printf("(%s%s%s%s%s%s) %08x (%s%s%s)%08x%s %s %08x/%08x %s%s%s%s",
113
                                (m_core->setup_stb)?"CT":"  ",
114 204 dgisselq
                                (m_core->i_wbm_cyc)?"CYC":"   ",
115
                                (m_core->i_wbm_stb)?"STB":"   ",
116
                                (m_core->i_wb_we)?"WE":"  ",
117 209 dgisselq
                                (m_core->i_gie)?"IE":"  ",
118
                                (m_core->i_exe)?"EX":"  ",
119 204 dgisselq
                                (m_core->i_wb_addr),
120 209 dgisselq
                                (m_core->mem_cyc)?"CYC":"   ",
121
                                (m_core->mem_stb)?"STB":"   ",
122
                                (m_core->mem_we)?"WE":"  ",
123
                                (m_core->mem_addr),
124
                                (m_core->mem_err)?"ER":"  ",
125 204 dgisselq
                                (m_core->i_wb_we)?"<-":"->",
126
                                (m_core->i_wb_we)?m_core->i_wb_data:m_core->o_rtn_data,
127 209 dgisselq
                                (m_core->mem_we)?m_core->r_data:m_core->v__DOT__mem_odata,
128 204 dgisselq
                                (m_core->o_rtn_stall)?"STALL":"     ",
129
                                (m_core->o_rtn_ack )?"ACK":"   ",
130
                                (m_core->o_rtn_miss)?"MISS":"    ",
131
                                (m_core->o_rtn_err )?"ERR":"   ");
132
 
133 209 dgisselq
                        printf("[%c]",
134
                                (m_core->wr_control)?'C'
135
                                :(m_core->wr_vtable)?'V'
136
                                :(m_core->wr_ptable)?'P'
137
                                :'-');
138
                        printf("[%c,%04x]",
139
                                (m_core->v__DOT__mut__DOT__kernel_context)?'K'
140
                                :(m_core->v__DOT__mut__DOT__z_context)?'Z':'-',
141 204 dgisselq
                                m_core->v__DOT__mut__DOT__r_context_word);
142
                        printf(" %s[%s%s@%08x,%08x]",
143 209 dgisselq
                                (m_core->r_pending)?"R":" ",
144
                                (m_core->r_we)?"W":" ",
145
                                (m_core->r_valid)?"V":" ",
146
                                (m_core->r_addr),
147
                                (m_core->r_data));
148
                        printf("@%2x[%s%s%s][%s%s%s%s%s]",
149 204 dgisselq
                                (m_core->v__DOT__mut__DOT__s_tlb_addr),
150
                                (m_core->v__DOT__mut__DOT__s_pending)?"P":" ",
151
                                (m_core->v__DOT__mut__DOT__s_tlb_hit)?"HT":"  ",
152
                                (m_core->v__DOT__mut__DOT__s_tlb_miss)?"MS":"  ",
153
                                (m_core->v__DOT__mut__DOT__ro_flag)?"RO":"  ",
154
                                (m_core->v__DOT__mut__DOT__simple_miss)?"SM":"  ",
155
                                (m_core->v__DOT__mut__DOT__ro_miss)?"RM":"  ",
156 209 dgisselq
                                (m_core->v__DOT__mut__DOT__exe_miss)?"EX":"  ",
157 204 dgisselq
                                (m_core->v__DOT__mut__DOT__table_err)?"TE":"  ");
158
                                //(m_core->v__DOT__mut__DOT__cachable)?"CH":"  ");
159
                        /*
160
                        printf(" M[%016lx]",
161
                                m_core->v__DOT__mut__DOT__r_tlb_match);
162 209 dgisselq
                        */
163
                        printf(" P[%3d%c] = 0x%03x, V=0x%03x, C=0x%04x, CTXT=%04x",
164 204 dgisselq
                                m_last_tlb_index,
165 209 dgisselq
                                ((m_core->v__DOT__mut__DOT__tlb_valid>>m_last_tlb_index)&1)?'V':'u',
166 204 dgisselq
                                m_core->v__DOT__mut__DOT__tlb_pdata[m_last_tlb_index],
167
                                m_core->v__DOT__mut__DOT__tlb_vdata[m_last_tlb_index],
168
                                m_core->v__DOT__mut__DOT__tlb_cdata[m_last_tlb_index],
169
                                m_core->v__DOT__mut__DOT__r_context_word);
170
                        printf("\n");
171
                }
172
        }
173
 
174
        void reset(void) {
175 209 dgisselq
                m_core->i_reset    = 1;
176 204 dgisselq
                m_core->i_ctrl_cyc_stb = 0;
177 209 dgisselq
                m_core->i_gie      = 0;
178
                m_core->i_exe      = 0;
179 204 dgisselq
                m_core->i_wbm_cyc  = 0;
180
                m_core->i_wbm_stb  = 0;
181
                tick();
182 209 dgisselq
                m_core->i_reset  = 0;
183 204 dgisselq
        }
184
 
185
        void wb_tick(void) {
186 209 dgisselq
                m_core->i_reset  = 0;
187 204 dgisselq
                m_core->i_ctrl_cyc_stb = 0;
188
                m_core->i_wbm_cyc  = 0;
189
                m_core->i_wbm_stb  = 0;
190
                tick();
191
                assert(!m_core->o_rtn_ack);
192
                assert(!m_core->o_rtn_err);
193
        }
194
 
195
        unsigned operator[](unsigned a) {
196 209 dgisselq
                unsigned        msk = (1<<LGMEMSIZE)-1;
197
// printf("OP[] Reading from %08x\n", a);
198
                assert((a&3)==0);
199
                a = (a>>2)&(msk);
200
// printf("OP[] ----> %08x\n", a);
201 204 dgisselq
                return m_core->v__DOT__ram__DOT__mem[a];
202
        }
203
 
204
        unsigned setup_read(unsigned a) {
205
                int             errcount = 0;
206
                unsigned        result;
207
                m_miss = false; m_err = false;
208
 
209
                printf("WB-READS(%08x)\n", a);
210
 
211 209 dgisselq
                m_core->i_ctrl_cyc_stb = 0;
212 204 dgisselq
                m_core->i_wbm_cyc = 0;
213
                m_core->i_wbm_stb = 0;
214
                m_core->i_wb_we  = 0;
215 209 dgisselq
                m_core->i_wb_addr= a>>2;
216 204 dgisselq
 
217 209 dgisselq
                if (m_core->i_gie) {
218
                        m_core->i_gie = 0;
219
                        wb_tick();
220
                }
221
 
222
                m_core->i_ctrl_cyc_stb = 1;
223
 
224 204 dgisselq
                if (m_core->o_rtn_stall) {
225
                        while((errcount++ < BOMBCOUNT)&&(m_core->o_rtn_stall))
226
                                tick();
227
                } tick();
228
 
229
                m_core->i_ctrl_cyc_stb = 0;
230
 
231
                while((errcount++ <  BOMBCOUNT)&&(!m_core->o_rtn_ack)) {
232
                        tick();
233
                }
234
 
235
 
236
                result = m_core->o_rtn_data;
237
                assert(!m_core->o_rtn_err);
238
                assert(!m_core->o_rtn_miss);
239
 
240
                if(errcount >= BOMBCOUNT) {
241
                        printf("SETTING ERR TO TRUE!!!!! (BOMB)\n");
242
                        m_bomb = true;
243
                } else if (!m_core->o_rtn_ack) {
244
                        printf("SETTING ERR TO TRUE--NO ACK, NO TIMEOUT\n");
245
                        m_bomb = true;
246
                }
247
                tick();
248
 
249
                assert(!m_core->o_rtn_ack);
250
                assert(!m_core->o_rtn_miss);
251
                assert(!m_core->o_rtn_err);
252
                assert(!m_core->o_rtn_stall);
253
 
254
                return result;
255
        }
256
 
257
        void setup_write(unsigned a, unsigned v) {
258
                int             errcount = 0;
259
                m_miss = false; m_err = false;
260
 
261
                printf("WB-WRITES(%08x,%08x)\n", a,v);
262
 
263 209 dgisselq
                m_core->i_ctrl_cyc_stb = 0;
264
                m_core->i_exe = 0;
265 204 dgisselq
                m_core->i_wbm_cyc = 0;
266
                m_core->i_wbm_stb = 0;
267
                m_core->i_wb_we  = 1;
268 209 dgisselq
                m_core->i_wb_addr= a>>2;
269 204 dgisselq
                m_core->i_wb_data= v;
270 209 dgisselq
                m_core->i_wb_sel= 15;
271 204 dgisselq
 
272 209 dgisselq
                if (m_core->i_gie) {
273
                        m_core->i_gie = 0;
274
                        wb_tick();
275
                }
276
                m_core->i_ctrl_cyc_stb = 1;
277 204 dgisselq
 
278 209 dgisselq
 
279
                if (a & 0x0200)
280
                        m_last_tlb_index = (a>>3)&0x3f;
281
 
282 204 dgisselq
                if (m_core->o_rtn_stall) {
283
                        while((errcount++ < BOMBCOUNT)&&(m_core->o_rtn_stall))
284
                                tick();
285
                } tick();
286
 
287
                m_core->i_ctrl_cyc_stb = 0;
288
 
289
                while((errcount++ <  BOMBCOUNT)&&(!m_core->o_rtn_ack)) {
290
                        tick();
291
                }
292
 
293
 
294
                assert(!m_core->o_rtn_err);
295
                assert(!m_core->o_rtn_miss);
296
 
297
                if(errcount >= BOMBCOUNT) {
298
                        printf("SETTING ERR TO TRUE!!!!! (BOMB)\n");
299
                        m_bomb = true;
300
                } else if (!m_core->o_rtn_ack) {
301
                        printf("SETTING ERR TO TRUE--NO ACK, NO TIMEOUT\n");
302
                        m_bomb = true;
303
                }
304
                tick();
305
 
306
                assert(!m_core->o_rtn_ack);
307
                assert(!m_core->o_rtn_miss);
308
                assert(!m_core->o_rtn_err);
309
                assert(!m_core->o_rtn_stall);
310
        }
311
 
312
        unsigned wb_read(unsigned a, bool *err) {
313
                int             errcount = 0;
314
                unsigned        result;
315
                if (err)        *err = false;
316
 
317
                printf("WB-READM(%08x)\n", a);
318
 
319
                m_core->i_ctrl_cyc_stb = 0;
320
                m_core->i_wbm_cyc = 1;
321
                m_core->i_wbm_stb = 1;
322
                m_core->i_wb_we  = 0;
323 209 dgisselq
                m_core->i_wb_addr= a>>2;
324 204 dgisselq
 
325
                if (m_core->o_rtn_stall) {
326
                        while((errcount++ < BOMBCOUNT)&&(m_core->o_rtn_stall)) {
327
                                tick();
328
                                if ((err)&&((m_core->o_rtn_err)||(m_core->o_rtn_miss))) {
329
                                        if (!*err) {
330
                                                m_miss = (m_core->o_rtn_miss);
331
                                                m_err  = (m_core->o_rtn_err);
332
                                        } *err = true;
333
                                        m_core->i_ctrl_cyc_stb = 0;
334
                                        m_core->i_wbm_cyc = 0;
335
                                        m_core->i_wbm_stb = 0;
336
                                        tick();
337
                                        return 0;
338
                                }
339
                        }
340
                } tick();
341
 
342
                m_core->i_wbm_stb = 0;
343
 
344
                while((errcount++ <  BOMBCOUNT)&&(!m_core->o_rtn_ack)) {
345
                        tick();
346
                        if ((err)&&((m_core->o_rtn_err)||(m_core->o_rtn_miss))) {
347
                                if (!*err) {
348
                                        m_miss = (m_core->o_rtn_miss);
349
                                        m_err  = (m_core->o_rtn_err);
350
                                } *err = true;
351
                                m_core->i_ctrl_cyc_stb = 0;
352
                                m_core->i_wbm_cyc = 0;
353
                                        m_core->i_wbm_stb = 0;
354
                                tick();
355
                                return 0;
356
                        }
357
                }
358
 
359
 
360
                result = m_core->o_rtn_data;
361
                assert(!m_core->o_rtn_err);
362
                assert(!m_core->o_rtn_miss);
363
 
364
                // Release the bus?
365
                m_core->i_wbm_cyc = 0;
366
                m_core->i_wbm_stb = 0;
367
 
368
                if(errcount >= BOMBCOUNT) {
369
                        printf("SETTING ERR TO TRUE!!!!! (BOMB)\n");
370
                        m_bomb = true;
371
                } else if (!m_core->o_rtn_ack) {
372
                        printf("SETTING ERR TO TRUE--NO ACK, NO TIMEOUT\n");
373
                        m_bomb = true;
374
                }
375
                tick();
376
 
377
                assert(!m_core->o_rtn_ack);
378
                assert(!m_core->o_rtn_miss);
379
                assert(!m_core->o_rtn_err);
380
                assert(!m_core->o_rtn_stall);
381
 
382
                return result;
383
        }
384
 
385
        void    wb_read(unsigned a, int len, unsigned *buf, bool *err) {
386
                int             errcount = 0;
387
                int             THISBOMBCOUNT = BOMBCOUNT * len;
388
                int             cnt, rdidx, inc;
389
 
390
                if (err)        *err = false;
391
                printf("WB-READM(%08x, %d)\n", a, len);
392
 
393
                while((errcount++ < BOMBCOUNT)&&(m_core->o_rtn_stall))
394
                        wb_tick();
395
 
396
                if (errcount >= BOMBCOUNT) {
397
                        printf("WB-READ(%d): Setting bomb to true (errcount = %d)\n", __LINE__, errcount);
398
                        m_bomb = true;
399
                        return;
400
                }
401
 
402
                errcount = 0;
403
 
404
                m_core->i_ctrl_cyc_stb = 0;
405
                m_core->i_wbm_cyc = 1;
406
                m_core->i_wbm_stb = 1;
407
                m_core->i_wb_we   = 0;
408 209 dgisselq
                m_core->i_wb_addr = a>>2;
409 204 dgisselq
 
410
                rdidx =0; cnt = 0;
411
                inc = 1;
412
 
413
                do {
414
                        int     s;
415
                        s = (m_core->o_rtn_stall==0)?0:1;
416
                        tick();
417
                        if (!s)
418
                                m_core->i_wb_addr += inc;
419
                        cnt += (s==0)?1:0;
420
                        if (m_core->o_rtn_ack)
421
                                buf[rdidx++] = m_core->o_rtn_data;
422
                        if ((err)&&((m_core->o_rtn_err)||(m_core->o_rtn_miss))) {
423
                                if (!*err) {
424
                                        m_miss = (m_core->o_rtn_miss);
425
                                        m_err  = (m_core->o_rtn_err);
426
                                } *err = true;
427
                                m_core->i_ctrl_cyc_stb = 0;
428
                                m_core->i_wbm_cyc = 0;
429
                                        m_core->i_wbm_stb = 0;
430
                                tick();
431
                                return;
432
                        }
433
                } while((cnt < len)&&(errcount++ < THISBOMBCOUNT));
434
 
435
                m_core->i_wbm_stb = 0;
436
 
437
                while((rdidx < len)&&(errcount++ < THISBOMBCOUNT)) {
438
                        tick();
439
                        if ((err)&&((m_core->o_rtn_err)||(m_core->o_rtn_miss))) {
440
                                if (!*err) {
441
                                        m_miss = (m_core->o_rtn_miss);
442
                                        m_err  = (m_core->o_rtn_err);
443
                                } *err = true;
444
                                m_core->i_ctrl_cyc_stb = 0;
445
                                m_core->i_wbm_cyc = 0;
446
                                        m_core->i_wbm_stb = 0;
447
                                tick();
448
                                return;
449
                        }
450
                        if (m_core->o_rtn_ack)
451
                                buf[rdidx++] = m_core->o_rtn_data;
452
                }
453
 
454
                // Release the bus?
455
                m_core->i_wbm_cyc = 0;
456
 
457
                if(errcount >= THISBOMBCOUNT) {
458
                        printf("SETTING ERR TO TRUE!!!!! (errcount=%08x, THISBOMBCOUNT=%08x)\n", errcount, THISBOMBCOUNT);
459
                        m_bomb = true;
460
                } else if (!m_core->o_rtn_ack) {
461
                        printf("SETTING ERR TO TRUE--NO ACK, NO TIMEOUT\n");
462
                        m_bomb = true;
463
                }
464
                tick();
465
                assert(!m_core->o_rtn_ack);
466
                assert(!m_core->o_rtn_miss);
467
                assert(!m_core->o_rtn_err);
468
                assert(!m_core->o_rtn_stall);
469
        }
470
 
471
        void    wb_write(unsigned a, unsigned v, bool *err) {
472
                int errcount = 0;
473
 
474
                if (err)        *err = false;
475
                printf("WB-WRITEM(%08x) <= %08x\n", a, v);
476
                m_core->i_ctrl_cyc_stb = 0;
477
                m_core->i_wbm_cyc = 1;
478
                m_core->i_wbm_stb = 1;
479
                m_core->i_wb_we  = 1;
480 209 dgisselq
                m_core->i_wb_addr= a>>2;
481 204 dgisselq
                m_core->i_wb_data= v;
482 209 dgisselq
                m_core->i_wb_sel= 15;
483 204 dgisselq
 
484
                if (m_core->o_rtn_stall)
485
                        while((errcount++ < BOMBCOUNT)&&(m_core->o_rtn_stall)) {
486
                                printf("Stalled, so waiting, errcount=%d\n", errcount);
487
                                tick();
488
                                if ((err)&&((m_core->o_rtn_miss)||(m_core->o_rtn_err))) {
489
                                        if (!*err) {
490
                                                m_miss = (m_core->o_rtn_miss);
491
                                                m_err  = (m_core->o_rtn_err);
492
                                        } *err = true;
493
                                        m_core->i_wbm_cyc = 0;
494
                                        m_core->i_wbm_stb = 0;
495
                                        tick();
496
                                        return;
497
                                }
498
                        }
499
                tick();
500
                if ((err)&&((m_core->o_rtn_miss)||(m_core->o_rtn_err))) {
501
                        if (!*err) {
502
                                m_miss = (m_core->o_rtn_miss);
503
                                m_err  = (m_core->o_rtn_err);
504
                        } *err = true;
505
                        m_core->i_wbm_cyc = 0;
506
                        m_core->i_wbm_stb = 0;
507
                        tick();
508
                        return;
509
                }
510
 
511
                m_core->i_wbm_stb = 0;
512
 
513
                while((errcount++ <  BOMBCOUNT)&&(!m_core->o_rtn_ack)) {
514
                        tick();
515
                        if ((err)&&((m_core->o_rtn_miss)||(m_core->o_rtn_err))) {
516
                                if (!*err) {
517
                                        m_miss = (m_core->o_rtn_miss);
518
                                        m_err  = (m_core->o_rtn_err);
519
                                } *err = true;
520
                                m_core->i_wbm_cyc = 0;
521
                                m_core->i_wbm_stb = 0;
522
                                tick();
523
                                return;
524
                        }
525
                } tick();
526
                if ((err)&&((m_core->o_rtn_miss)||(m_core->o_rtn_err))) {
527
                        if (!*err) {
528
                                m_miss = (m_core->o_rtn_miss);
529
                                m_err  = (m_core->o_rtn_err);
530
                        } *err = true;
531
                        m_core->i_wbm_cyc = 0;
532
                        m_core->i_wbm_stb = 0;
533
                        tick();
534
                        return;
535
                }
536
 
537
                // Release the bus?
538
                m_core->i_ctrl_cyc_stb = 0;
539
                m_core->i_wbm_cyc = 0;
540
                m_core->i_wbm_stb = 0;
541
 
542
                if(errcount >= BOMBCOUNT) {
543
                        printf("SETTING ERR TO TRUE!!!!! (BOMB) (LINE=%d, count=%d)\n",__LINE__, errcount);
544
                        m_bomb = true;
545
                } tick();
546
                assert(!m_core->o_rtn_ack);
547
                assert(!m_core->o_rtn_miss);
548
                assert(!m_core->o_rtn_err);
549
                assert(!m_core->o_rtn_stall);
550
        }
551
 
552
        void    wb_write(unsigned a, unsigned int ln, unsigned *buf, bool *err) {
553
                unsigned errcount = 0, nacks = 0;
554
                if (err)        *err = false;
555
 
556
                printf("WB-WRITEM(%08x, %d, ...)\n", a, ln);
557
                m_core->i_ctrl_cyc_stb = 0;
558
                m_core->i_wbm_cyc = 1;
559
                m_core->i_wbm_stb = 1;
560
                m_core->i_wb_we  = 1;
561 209 dgisselq
                m_core->i_wb_sel= 15;
562 204 dgisselq
                for(unsigned stbcnt=0; stbcnt<ln; stbcnt++) {
563 209 dgisselq
                        m_core->i_wb_addr= (a>>2)+stbcnt;
564 204 dgisselq
                        m_core->i_wb_data= buf[stbcnt];
565
                        errcount = 0;
566
 
567
                        while((errcount++ < BOMBCOUNT)&&(m_core->o_rtn_stall)) {
568
                                tick();
569
                                if ((err)&&((m_core->o_rtn_miss)||(m_core->o_rtn_err))) {
570
                                        if (!*err) {
571
                                                m_miss = (m_core->o_rtn_miss);
572
                                                m_err  = (m_core->o_rtn_err);
573
                                        } *err = true;
574
                                        m_core->i_wbm_cyc = 0;
575
                                        m_core->i_wbm_stb = 0;
576
                                        tick();
577
                                        return;
578
                                }
579
                                if (m_core->o_rtn_ack) nacks++;
580
                        }
581
                        // Tick, now that we're not stalled.  This is the tick
582
                        // that gets accepted.
583
                        tick(); if (m_core->o_rtn_ack) nacks++;
584
                        if ((err)&&((m_core->o_rtn_miss)||(m_core->o_rtn_err))) {
585
                                if (!*err) {
586
                                        m_miss = (m_core->o_rtn_miss);
587
                                        m_err  = (m_core->o_rtn_err);
588
                                } *err = true;
589
                                m_core->i_wbm_cyc = 0;
590
                                m_core->i_wbm_stb = 0;
591
                                tick();
592
                                return;
593
                        }
594
                }
595
 
596
                m_core->i_wbm_stb = 0;
597
 
598
                errcount = 0;
599
                while((nacks < ln)&&(errcount++ < BOMBCOUNT)) {
600
                        tick();
601
                        if (m_core->o_rtn_ack) {
602
                                nacks++;
603
                                errcount = 0;
604
                        }
605
                        if ((err)&&((m_core->o_rtn_miss)||(m_core->o_rtn_err))) {
606
                                if (!*err) {
607
                                        m_miss = (m_core->o_rtn_miss);
608
                                        m_err  = (m_core->o_rtn_err);
609
                                } *err = true;
610
                                m_core->i_wbm_cyc = 0;
611
                                m_core->i_wbm_stb = 0;
612
                                tick();
613
                                return;
614
                        }
615
                }
616
 
617
                // Release the bus
618
                m_core->i_wbm_cyc = 0;
619
                m_core->i_wbm_stb = 0;
620
 
621
                if(errcount >= BOMBCOUNT) {
622
                        printf("SETTING ERR TO TRUE!!!!! (BOMB)\n");
623
                        m_bomb = true;
624
                } tick();
625
                assert(!m_core->o_rtn_ack);
626
                assert(!m_core->o_rtn_miss);
627
                assert(!m_core->o_rtn_err);
628
                assert(!m_core->o_rtn_stall);
629
        }
630
 
631
        bool    miss(void) {
632
                return m_miss;
633
        } bool  err(void) {
634
                return m_err;
635
        }
636
 
637
        bool    bombed(void) const { return m_bomb; }
638
 
639
        bool    debug(void) const { return m_debug; }
640
        bool    debug(bool nxtv) { return m_debug = nxtv; }
641
};
642
 
643
void    uload(unsigned len, unsigned *buf) {
644
        FILE    *fp = fopen("/dev/urandom", "r");
645
 
646
        if ((NULL == fp)||(len != fread(buf, sizeof(unsigned), len, fp))) {
647
                for(int i=0; i<(int)len; i++)
648
                        buf[i] = ((unsigned)rand());
649
        } if (NULL == fp)
650
                fclose(fp);
651
}
652
 
653
void    install_page(ZIPMMU_TB *tb, int idx, unsigned va, unsigned pa, int flags) {
654
        int     LGTBL, LGPGSZ, LGCTXT;
655
        int     c;
656
        unsigned base;
657 209 dgisselq
        // bool hdebug = tb->debug();
658 204 dgisselq
 
659 209 dgisselq
        // tb->debug(false);
660
        c=tb->setup_read(R_CONTROL);
661 204 dgisselq
        printf("CONTEXT-REG = %08x\n", c);
662
        LGTBL  = ((c>>24)&15);
663 209 dgisselq
        LGPGSZ= (((c>>20)&15)+10)&31;   // In bytes
664 204 dgisselq
        LGCTXT= (((c>>16)&15)+1)&31;
665
        c &= ((1<<LGCTXT)-1);
666 209 dgisselq
        base  = R_ENTRYSZ(LGTBL, idx);
667 204 dgisselq
        va &= -(1<<LGPGSZ);
668
        pa &= -(1<<LGPGSZ);
669
 
670 209 dgisselq
        printf("INSTALL[%2d] %04x:%03x[%04x]%xV -> %03x[%04x]%xP %s%s\n",
671
                idx, c,
672
                (va>>LGPGSZ), LOCONTEXT(c)>>4, flags,
673
                (pa>>LGPGSZ), HICONTEXT(c)>>4, 0,
674 204 dgisselq
                (flags&MMUFLAG_RONW)?"RO":"  ",
675
                (flags&MMUFLAG_CCHE)?"Cachable":"");
676 209 dgisselq
        tb->setup_write(base  , va|(LOCONTEXT(c))|flags);
677
        tb->setup_write(base+4, pa|(HICONTEXT(c)));
678
        // tb->debug(hdebug);
679
        tb->tick();
680
        tb->m_core->i_gie = 1;
681 204 dgisselq
}
682
 
683
int main(int  argc, char **argv) {
684
        Verilated::commandArgs(argc, argv);
685
        ZIPMMU_TB       *tb = new ZIPMMU_TB;
686
        unsigned        *rdbuf; // *mbuf;
687
        unsigned        mlen = (1<<LGMEMSIZE), c, blen;
688 209 dgisselq
        const unsigned  CONTEXT = 0x0fef7;
689 204 dgisselq
 
690
        tb->opentrace("zipmmu_tb.vcd");
691
        printf("Giving the core 2 cycles to start up\n");
692
        // Before testing, let's give the unit time enough to warm up
693
        tb->reset();
694
        for(int i=0; i<2; i++)
695
                tb->wb_tick();
696
 
697
        mlen = 1<<16;
698
 
699
        printf("Getting some memory ...\n");
700
        rdbuf = new unsigned[mlen];
701
        // mbuf  = new unsigned[mlen]; // Match buffer
702
        printf("Charging my memory with random values\n");
703
        uload(mlen, rdbuf);
704
 
705
 
706 209 dgisselq
        int     LGADR, LGTBL, LGPGSZ, LGCTXT, sr, PAGESZ;
707 204 dgisselq
 
708 209 dgisselq
        c=tb->setup_read(R_CONTROL);
709 204 dgisselq
        printf("CONTROL-REG = %08x\n = %2d\n", c, c);
710 209 dgisselq
        sr = tb->setup_read(R_STATUS);
711 204 dgisselq
        printf("STATUS-REG  = %08x = %2d\n", sr, sr);
712
        LGADR = (((c>>28)&15)+17)&31;
713
        LGTBL = ((c>>24)&15);
714 209 dgisselq
        LGPGSZ= (((c>>20)&15)+10)&31;
715
        PAGESZ= 1ul<<LGPGSZ;
716 204 dgisselq
        LGCTXT= (((c>>16)&15)+1)&31;
717
        printf("LGADR       = %08x = %2d\n", LGADR, LGADR);
718
        printf("LGTBL       = %08x = %2d\n", LGTBL, LGTBL);
719
        printf("LGPGSZ      = %08x = %2d\n", LGPGSZ, LGPGSZ);
720
        printf("LGCTXT      = %08x = %2d\n", LGCTXT, LGCTXT);
721 209 dgisselq
        printf("PAGESZ      = %08x = %2d\n", PAGESZ, PAGESZ);
722 204 dgisselq
 
723
        // First, let's make sure we can read/write the context
724
        printf("\n\nTest: Can we read/write the context register?\n");
725 209 dgisselq
        tb->setup_write(R_CONTROL,CONTEXT);
726
        c=tb->setup_read(R_CONTROL);
727
        printf("CONTEXT     = %04x (0x%04x)\n", c &0x0ffff, CONTEXT & 0x0ffff);
728
        if ((c&0x0ffff) != CONTEXT)
729 204 dgisselq
                goto test_failure;
730
 
731
        // Load the table with TLB misses
732
        printf("\n\nTest: Can we load the table with TLB misses? (%d entries)\n", (1<<LGTBL));
733
        for(int i=0; i<(1<<LGTBL); i++) {
734 209 dgisselq
                c = CONTEXT; // Context: 0xfef7, no flags
735
                tb->setup_write(R_VENTRY(i), (LOCONTEXT(c))
736
                        |(((1<<LGTBL)-1-i)<<LGPGSZ) | ROFLAG);
737
                tb->setup_write(R_PENTRY(i), (HICONTEXT(c))
738
                        |(((1<<LGTBL)-1-i)<<LGPGSZ));
739 204 dgisselq
        }
740
 
741
        // Dump the table, make sure we got it right
742
        for(int i=0; i<(1<<LGTBL); i++) {
743 209 dgisselq
                unsigned v, p, c;
744 204 dgisselq
 
745 209 dgisselq
                c = 0x0fef7;
746
                v=tb->setup_read(R_VENTRY(i));
747
                p=tb->setup_read(R_PENTRY(i));
748
 
749
                printf("TBL[%2d] = %08x -> %08x", i, v, p);
750
                printf("\tEXPECTING %08x -> %08x\n",
751
                        (unsigned)((LOCONTEXT(c))|(((1<<LGTBL)-1-i)<<LGPGSZ)|ROFLAG),
752
                        (unsigned)(HICONTEXT(c))|(((1<<LGTBL)-1-i)<<LGPGSZ));
753
                if (v != (unsigned)((LOCONTEXT(c))|(((1<<LGTBL)-1-i)<<LGPGSZ)|ROFLAG))
754 204 dgisselq
                        goto test_failure;
755 209 dgisselq
                if (p != (unsigned)((HICONTEXT(c))|(((1<<LGTBL)-1-i)<<LGPGSZ)))
756 204 dgisselq
                        goto test_failure;
757 209 dgisselq
        } printf("-- PASS\n\n");
758 204 dgisselq
 
759
        // Now, let's create a fictitious process, context 1, with no pages.
760
        // See what happens when we try to access his stack at 0xffffffff
761
        bool    tberr;
762
        printf("\n\nTest: Do we get a TLB miss when attempting to find a non-existent page?\n");
763 209 dgisselq
        tb->m_core->i_gie = 1;
764
        tb->tick();
765 204 dgisselq
        tberr = false;
766 209 dgisselq
        tb->wb_write(0xfffffffc, 0x0fe, &tberr);
767 204 dgisselq
        if ((!tberr)||(!tb->miss())||(tb->err())) {
768
                printf("TBERR = %s\nMISS  = %s\nERR   = %s\n",
769
                        (tberr)?"true":"false", (tb->miss())?"true":"false",
770
                        (tb->err())?"true":"false");
771
                goto test_failure;
772 209 dgisselq
        } printf("-- PASS\n\n");
773 204 dgisselq
 
774
        tberr = false;
775 209 dgisselq
        install_page(tb, 0, 0xfffffffc, (4<<LGMEMSIZE)+0*PAGESZ,
776 204 dgisselq
                        MMUFLAG_RONW);
777
        printf("\n\nTest: Do we get a TLB miss when attempting to write a RO page?\n");
778
        tb->wb_write(0xffffffff, 0x0fe, &tberr);
779
        if ((!tberr)||(!tb->miss())||(tb->err())) {
780
                printf("TBERR = %s\nMISS  = %s\nERR   = %s\n",
781
                        (tberr)?"true":"false", (tb->miss())?"true":"false",
782
                        (tb->err())?"true":"false");
783
                goto test_failure;
784 209 dgisselq
        } printf("-- PASS\n\n");
785 204 dgisselq
 
786
        tberr = false;
787
        printf("\n\nTest: What if we make this into a writeable page?\n");
788 209 dgisselq
        install_page(tb, 0, 0xfffffffc, (4<<LGMEMSIZE)+0*PAGESZ, 0);
789
        tb->m_core->i_gie = 1;
790
        tb->m_core->i_exe = 0;
791
        tb->wb_write(0xfffffff8, 0x0fe, &tberr);
792 204 dgisselq
        if (tberr) {
793
                printf("TBERR = %s\nMISS  = %s\nERR   = %s\n",
794
                        (tberr)?"true":"false", (tb->miss())?"true":"false",
795
                        (tb->err())?"true":"false");
796
                goto test_failure;
797 209 dgisselq
        } printf("-- PASS\n\n");
798 204 dgisselq
        printf("\n\nTest: Is the next access done w/in a single clock?\n");
799 209 dgisselq
        tb->wb_write(0xfffffffc, 0xdeadbeef, &tberr);
800 204 dgisselq
        if (tberr) {
801
                printf("TBERR = %s\nMISS  = %s\nERR   = %s\n",
802
                        (tberr)?"true":"false", (tb->miss())?"true":"false",
803
                        (tb->err())?"true":"false");
804
                goto test_failure;
805 209 dgisselq
        } printf("-- PASS\n\n");
806 204 dgisselq
 
807
 
808
        tberr = false;
809
        printf("\n\nTest: What if we make this into a writeable page?\n");
810 209 dgisselq
        install_page(tb, 0, 0xffffffff, (4<<LGMEMSIZE)+0*PAGESZ, 0);
811
        tb->wb_write(0xfffffffc, 0x0fe, &tberr);
812
        if ((tberr)||((*tb)[0x0ffc]!=0x0fe)) {
813 204 dgisselq
                unsigned v;
814 209 dgisselq
                v = ((*tb)[0x0ffc]!=0x0fe);
815 204 dgisselq
                printf("V     = 0x%08x (!= 0x0fe?)\nTBERR = %s\nMISS  = %s\nERR   = %s\n",
816
                        v, (tberr)?"true":"false", (tb->miss())?"true":"false",
817
                        (tb->err())?"true":"false");
818
                goto test_failure;
819 209 dgisselq
        } printf("-- PASS\n\n");
820 204 dgisselq
 
821
        tberr = false;
822
        printf("\n\nTest: How about a read from the same location?\n");
823
        {
824
                unsigned        v;
825 209 dgisselq
                v = tb->wb_read(0xfffffffc, &tberr);
826 204 dgisselq
                if ((tberr)||(v != 0x0fe)) {
827
                        printf("V     = 0x%08x (!= 0x0fe?)\nTBERR = %s\nMISS  = %s\nERR   = %s\n",
828
                                v,
829
                                (tberr)?"true":"false", (tb->miss())?"true":"false",
830
                                (tb->err())?"true":"false");
831
                        goto test_failure;
832
                }
833 209 dgisselq
        } printf("-- PASS\n\n");
834 204 dgisselq
 
835 209 dgisselq
        printf("Test: Burst write, within page (PAGESZ = %04x)\n", PAGESZ);
836
        tb->setup_write(R_CONTROL, 0x0dad);
837
#define TEST_VPAGE      ((0x0ffffffffl)&(-(1l<<LGPGSZ)))
838
        install_page(tb, 0, TEST_VPAGE-2*PAGESZ, (4<<LGMEMSIZE)+0*PAGESZ, 0);
839
        install_page(tb, 1, TEST_VPAGE-1*PAGESZ, (4<<LGMEMSIZE)+1*PAGESZ, 0);
840
        install_page(tb, 2, TEST_VPAGE-0*PAGESZ, (4<<LGMEMSIZE)+2*PAGESZ, 0);
841 204 dgisselq
 
842
        tberr = false;
843
        blen = (1<<(LGPGSZ-2));
844 209 dgisselq
        tb->wb_write(TEST_VPAGE-2*(1<<LGPGSZ), blen, rdbuf, &tberr);
845 204 dgisselq
        if (tberr) {
846
                printf("TBERR = %s\nMISS  = %s\nERR   = %s\n",
847
                        (tberr)?"true":"false", (tb->miss())?"true":"false",
848
                        (tb->err())?"true":"false");
849 209 dgisselq
                printf("STATUS= %08x\n", tb->setup_read(R_STATUS));
850 204 dgisselq
                goto test_failure;
851
        } for(unsigned i=0; i<blen; i++) {
852 209 dgisselq
                if ((*tb)[i*4] != rdbuf[i]) {
853 204 dgisselq
                        printf("MEM[%04x] = %08x (!= %08x as expected)\n",
854 209 dgisselq
                                i, (*tb)[4*i], rdbuf[i]);
855 204 dgisselq
                        goto test_failure;
856
                }
857 209 dgisselq
        } printf("-- PASS\n\n");
858 204 dgisselq
 
859
        printf("Test: Burst read\n");
860
        // Try somewhere within that last page
861
        tberr = false;
862 209 dgisselq
        tb->wb_read(TEST_VPAGE-2*(1<<LGPGSZ)+(18*4), blen, rdbuf, &tberr);
863 204 dgisselq
        if (tberr) {
864
                printf("TBERR = %s\nMISS  = %s\nERR   = %s\n",
865
                        (tberr)?"true":"false", (tb->miss())?"true":"false",
866
                        (tb->err())?"true":"false");
867 209 dgisselq
                printf("STATUS= %08x\n", tb->setup_read(R_STATUS));
868 204 dgisselq
                goto test_failure;
869
        } for(unsigned i=0; i<blen; i++) {
870 209 dgisselq
                if ((*tb)[(i+18)*4] != rdbuf[i]) {
871 204 dgisselq
                        printf("MEM[%04x] = %08x (!= %08x as expected)\n",
872
                                i+18, (*tb)[i+18], rdbuf[i]);
873
                        goto test_failure;
874
                }
875 209 dgisselq
        } printf("-- PASS\n\n");
876 204 dgisselq
 
877
 
878
        printf("Tests not (yet) implemented\n");
879
        printf("Test: Burst read crossing pages, second page valid\n");
880
        printf("Test: Burst read crossing pages, second page invalid\n");
881
 
882
        printf("SUCCESS!!\n");
883
        exit(0);
884
test_failure:
885
        printf("FAIL-HERE\n");
886
        for(int i=0; i<4; i++)
887
                tb->tick();
888
        printf("TEST FAILED\n");
889
        exit(-1);
890
}

powered by: WebSVN 2.1.0

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