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

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [sim/] [verilator/] [pfcache_tb.cpp] - Blame information for rev 204

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 204 dgisselq
///////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    pfcache_tb.cpp
4
//
5
// Project:     Zip CPU -- a small, lightweight, RISC CPU soft core
6
//
7
// Purpose:     Bench testing for the prefetch cache used within the ZipCPU
8
//              when it is in pipelind mode.  Whether or not this module is
9
//      used depends upon how the CPU is set up in cpudefs.v.
10
//
11
//
12
// Creator:     Dan Gisselquist, Ph.D.
13
//              Gisselquist Technology, LLC
14
//
15
///////////////////////////////////////////////////////////////////////////////
16
//
17
// Copyright (C) 2015-2017, 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
// License:     GPL, v3, as defined and found on www.gnu.org,
30
//              http://www.gnu.org/licenses/gpl.html
31
//
32
//
33
///////////////////////////////////////////////////////////////////////////////
34
//
35
//
36
#include <signal.h>
37
#include <time.h>
38
#include <unistd.h>
39
#include <assert.h>
40
 
41
#include <stdlib.h>
42
#include <ctype.h>
43
 
44
#include "verilated.h"
45
#include "verilated_vcd_c.h"
46
#include "Vpfcache.h"
47
 
48
#include "testb.h"
49
#include "cpudefs.h"
50
#include "memsim.h"
51
 
52
#define RAMBASE         (1<<20)
53
#define RAMWORDS        RAMBASE
54
#define MAXTIMEOUT      128
55
 
56
FILE    *gbl_dbgfp = NULL; // Can also be set to stdout
57
 
58
class   PFCACHE_TB : public TESTB<Vpfcache> {
59
public:
60
        MEMSIM  m_mem;
61
        bool    m_bomb;
62
 
63
        // Nothing special to do in a startup.
64
        PFCACHE_TB(void) : m_mem(RAMWORDS), m_bomb(false) {}
65
 
66
        void    randomize_memory(void) {
67
                m_mem.load("/dev/urandom");
68
        }
69
 
70
        // ~CPUOPS_TB(void) {}
71
 
72
        //
73
        // Calls TESTB<>::reset to reset the core.  Makes sure the i_ce line
74
        // is low during this reset.
75
        //
76
        void    reset(void) {
77
                m_core->i_rst         = 0;
78
                m_core->i_pc          = RAMBASE;
79
                m_core->i_new_pc = 0;
80
                m_core->i_clear_cache = 1;
81
                m_core->i_stall_n = 1;
82
                m_core->i_stall_n = 1;
83
 
84
                TESTB<Vpfcache>::reset();
85
        }
86
 
87
        //
88
        // dbgdump();
89
        //
90
        void    dbgdump(void) {
91
                /*
92
                char    outstr[2048], *s;
93
                sprintf(outstr, "Tick %4ld %s%s ",
94
                        m_tickcount,
95
                        (m_core->i_rst)?"R":" ",
96
                        (m_core->i_ce)?"CE":"  ");
97
                s = &outstr[strlen(outstr)];
98
 
99
                puts(outstr);
100
                */
101
        }
102
 
103
        bool    valid_mem(uint32_t addr) {
104
                if (addr < RAMBASE)
105
                        return false;
106
                if (addr >= RAMBASE + RAMWORDS)
107
                        return false;
108
                return true;
109
        }
110
 
111
        //
112
        // tick()
113
        //
114
        // Call this to step the module under test.
115
        //
116
        void    tick(void) {
117
                bool    debug = false;
118
 
119
                if ((m_core->o_wb_cyc)&&(m_core->o_wb_stb)) {
120
                        if (!valid_mem(m_core->o_wb_addr))
121
                                m_core->i_wb_err = 1;
122
                } else if (m_core->o_wb_stb) {
123
                        m_bomb = true;
124
                }
125
 
126
                if (m_core->o_wb_we)
127
                        m_bomb = true;
128
                if (m_core->o_wb_data != 0)
129
                        m_bomb = true;
130
 
131
                if (debug)
132
                        dbgdump();
133
 
134
                unsigned mask = (RAMBASE-1);
135
 
136
                m_mem(m_core->o_wb_cyc, m_core->o_wb_stb, m_core->o_wb_we,
137
                        m_core->o_wb_addr & mask, m_core->o_wb_data, 0,
138
                        m_core->i_wb_ack, m_core->i_wb_stall,m_core->i_wb_data);
139
 
140
                TESTB<Vpfcache>::tick();
141
 
142
                if (m_core->o_v) {
143
                        uint32_t        pc, insn;
144
 
145
                        pc   = m_core->o_pc;
146
                        insn = m_core->o_i;
147
                        if (insn != m_mem[pc & (RAMWORDS-1)]) {
148
                                fprintf(stderr, "ERR: PF[%08x] = %08x != %08x\n", pc,
149
                                        insn, m_mem[pc & (RAMWORDS-1)]);
150
                                closetrace();
151
                                assert(insn == m_mem[pc & (RAMWORDS-1)]);
152
                        }
153
                }
154
        }
155
 
156
        //
157
        // fetch_insn()
158
        //
159
        void fetch_insn(void) {
160
                uint32_t        timeout = 0;
161
 
162
                if ((m_core->o_v)&&(m_core->i_stall_n))
163
                        m_core->i_pc++;
164
 
165
                m_core->i_rst         = 0;
166
                m_core->i_new_pc      = 0;
167
                m_core->i_clear_cache = 0;
168
                m_core->i_stall_n     = 1;
169
                do {
170
                        tick();
171
                } while((!m_core->o_v)&&(!m_core->o_illegal)&&(timeout++ < MAXTIMEOUT));
172
 
173
                if (timeout >= MAXTIMEOUT)
174
                        m_bomb = true;
175
        }
176
 
177
        //
178
        // skip_fetch()
179
        //
180
        void    skip_fetch(void) {
181
                uint32_t        prevalid, insn;
182
 
183
                if ((m_core->o_v)&&(m_core->i_stall_n))
184
                        m_core->i_pc++;
185
 
186
                m_core->i_rst         = 0;
187
                m_core->i_new_pc      = 0;
188
                m_core->i_clear_cache = 0;
189
                m_core->i_stall_n     = 0;
190
                insn = m_core->o_i;
191
                prevalid= m_core->o_v;
192
 
193
                tick();
194
 
195
                if (prevalid) {
196
                        // if (!m_core->o_v) {
197
                                // fprintf(stderr, "ERR: VALID dropped on stall!\n");
198
                                // closetrace();
199
                                // assert(m_core->o_v);
200
                        // }
201
                        if (insn != m_core->o_i) {
202
                                fprintf(stderr, "ERR: VALID INSN CHANGED on stall!\n");
203
                                closetrace();
204
                                assert(insn == m_core->o_i);
205
                        }
206
                }
207
        }
208
 
209
 
210
        //
211
        // jump
212
        //
213
        void    jump(unsigned target) {
214
                uint32_t        timeout = 0;
215
 
216
                m_core->i_rst         = 0;
217
                m_core->i_new_pc      = 1;
218
                m_core->i_clear_cache = 0;
219
                m_core->i_stall_n     = 1;
220
                m_core->i_pc          = target;
221
 
222
                tick();
223
                m_core->i_pc++;
224
                m_core->i_new_pc      = 0;
225
                m_core->i_stall_n     = 0;
226
 
227
                while((!m_core->o_v)&&(timeout++ < MAXTIMEOUT))
228
                        tick();
229
 
230
                if (timeout >= MAXTIMEOUT)
231
                        m_bomb = true;
232
                if (m_core->o_v)
233
                        assert(m_core->o_pc == target);
234
        }
235
};
236
 
237
void    usage(void) {
238
        printf("USAGE: pfcache_tb\n");
239
        printf("\n");
240
}
241
 
242
int     main(int argc, char **argv) {
243
        // Setup verilator
244
        Verilated::commandArgs(argc, argv);
245
        // Now, create a test bench.
246
        PFCACHE_TB      *tb = new PFCACHE_TB();
247
        int     rcode = EXIT_SUCCESS;
248
 
249
        tb->opentrace("pfcache.vcd");
250
        tb->randomize_memory();
251
 
252
        tb->jump(RAMBASE);
253
 
254
        // Simulate running straight through code
255
        for(int i=0; i<130; i++) {
256
                // printf("FETCH\n");
257
                tb->fetch_insn();
258
        }
259
 
260
        // Now, let's bounce around through the cache
261
        for(int j=0; j<20; j++) {
262
                tb->jump(RAMBASE+j);
263
                for(int i=0; i<130; i++) {
264
                        // printf("FETCH\n");
265
                        tb->fetch_insn();
266
                }
267
 
268
                if (tb->m_bomb) {
269
                        printf("TEST FAILURE!\n");
270
                        delete  tb;
271
                        exit(EXIT_FAILURE);
272
                }
273
        }
274
 
275
        // Now, add in some CIS-type instructions
276
        for(int i=0; i<130; i++) {
277
                unsigned v = rand() & 0x0f;
278
 
279
                if ((v&3)==2) {
280
                        // printf("SKIP\n");
281
                        tb->skip_fetch();
282
                } else {
283
                        // printf("FETCH\n");
284
                        tb->fetch_insn();
285
                }
286
 
287
                if (tb->m_bomb) {
288
                        printf("TEST FAILURE!\n");
289
                        delete  tb;
290
                        exit(EXIT_FAILURE);
291
                }
292
        }
293
 
294
        // Finally, try it all: stalls, CIS, and jumps
295
        for(int i=0; i<10000; i++) {
296
                unsigned v = rand() & 0x0f;
297
                if (v == 0) {
298
                        uint32_t target = rand() & (RAMWORDS-1);
299
                        target += RAMBASE;
300
                        // printf("JUMP TO %08x\n", target);
301
                        tb->jump(target);
302
                } else if ((v & 3)==2) {
303
                        // printf("SKIP\n");
304
                        tb->skip_fetch();
305
                } else {
306
                        // printf("FETCH\n");
307
                        tb->fetch_insn();
308
                }
309
 
310
                if (tb->m_bomb) {
311
                        printf("TEST FAILURE!\n");
312
                        delete  tb;
313
                        exit(EXIT_FAILURE);
314
                }
315
        }
316
 
317
        printf("SUCCESS!\n");
318
        exit(rcode);
319
}
320
 

powered by: WebSVN 2.1.0

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