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

Subversion Repositories zipcpu

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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