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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [testsuite/] [test-code-or1k/] [cache/] [cache.c] - Blame information for rev 582

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

Line No. Rev Author Line
1 90 jeremybenn
/* cache.c. Cache test of Or1ksim
2
 
3
   Copyright (C) 1999-2006 OpenCores
4
   Copyright (C) 2010 Embecosm Limited
5
 
6
   Contributors various OpenCores participants
7
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
8
 
9
   This file is part of OpenRISC 1000 Architectural Simulator.
10
 
11
   This program is free software; you can redistribute it and/or modify it
12
   under the terms of the GNU General Public License as published by the Free
13
   Software Foundation; either version 3 of the License, or (at your option)
14
   any later version.
15
 
16
   This program is distributed in the hope that it will be useful, but WITHOUT
17
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
19
   more details.
20
 
21
   You should have received a copy of the GNU General Public License along
22
   with this program.  If not, see <http:  www.gnu.org/licenses/>.  */
23
 
24
/* ----------------------------------------------------------------------------
25
   This code is commented throughout for use with Doxygen.
26
   --------------------------------------------------------------------------*/
27
 
28
#include "support.h"
29
#include "spr-defs.h"
30
 
31
 
32
#define MEM_RAM 0x00100000
33
 
34 458 julius
/* Linker script symbols */
35
extern unsigned int _ram_end;
36
 
37
unsigned int program_ram_end;
38
 
39
unsigned int ic_present;
40
unsigned int dc_present;
41
 
42 90 jeremybenn
/* Number of IC sets (power of 2) */
43 458 julius
unsigned int ic_sets;
44
#define IC_SETS ic_sets
45
unsigned int dc_sets;
46
#define DC_SETS dc_sets
47 90 jeremybenn
 
48
/* Block size in bytes (1, 2, 4, 8, 16, 32 etc.) */
49 458 julius
unsigned int ic_bs;
50
#define IC_BLOCK_SIZE ic_bs
51
unsigned int dc_bs;
52
#define DC_BLOCK_SIZE dc_bs
53 90 jeremybenn
 
54
/* Number of IC ways (1, 2, 3 etc.). */
55 458 julius
unsigned int ic_ways;
56
#define IC_WAYS ic_ways
57
unsigned int dc_ways;
58
#define DC_WAYS dc_ways
59 90 jeremybenn
 
60
/* Cache size */
61
#define IC_SIZE (IC_WAYS*IC_SETS*IC_BLOCK_SIZE)
62
#define DC_SIZE (DC_WAYS*DC_SETS*DC_BLOCK_SIZE)
63
 
64
extern void ic_enable(void);
65
extern void ic_disable(void);
66
extern void dc_enable(void);
67
extern void dc_disable(void);
68
extern void dc_inv(void);
69
extern unsigned long ic_inv_test(void);
70
extern unsigned long dc_inv_test(unsigned long);
71
 
72
extern void (*jalr)(void);
73
extern void (*jr)(void);
74
 
75
/* Index on jump table */
76
unsigned long jump_indx;
77
 
78
/* Jump address table */
79 458 julius
#define MAX_IC_WAYS 32
80
unsigned long jump_addr[15*MAX_IC_WAYS];
81 90 jeremybenn
 
82
void dummy();
83
 
84
void jump_and_link(void)
85
{
86 346 jeremybenn
        asm("jalr:");
87 90 jeremybenn
  asm("l.jr\tr9");
88
  asm("l.nop");
89
}
90
 
91
void jump(void)
92
{
93 346 jeremybenn
        asm("jr:");
94 90 jeremybenn
        /* Read and increment index */
95
        asm("l.lwz\t\tr3,0(r11)");
96
        asm("l.addi\t\tr3,r3,4");
97
        asm("l.sw\t\t0(r11),r3");
98
        /* Load next executin address from table */
99
        asm("l.lwz\t\tr3,0(r3)");
100
        /* Jump to that address */
101
        asm("l.jr\t\tr3") ;
102
        /* Report that we succeeded */
103
        asm("l.nop\t0");
104
}
105
 
106
void copy_jr(unsigned long add)
107
{
108
        memcpy((void *)add, (void *)&jr, 24);
109
}
110
 
111
void call(unsigned long add)
112
{
113 346 jeremybenn
  asm("l.movhi\tr11,hi(jump_indx)" : :);
114
  asm("l.ori\tr11,r11,lo(jump_indx)" : :);
115 90 jeremybenn
        asm("l.jalr\t\t%0" : : "r" (add) : "r11", "r9");
116
        asm("l.nop" : :);
117
}
118
 
119 458 julius
/* Determine cache configuration from cache configuration registers */
120
void init_cache_config(void)
121
{
122
 
123
        unsigned long iccfgr, dccfgr;
124
        unsigned long upr;
125
 
126
        ic_present = dc_present = 0;
127
 
128
        upr = mfspr (SPR_UPR);
129
 
130
        if (!(upr & SPR_UPR_ICP))
131
        {
132
                printf("No instruction cache present. Skipping tests.\n");
133
        }
134
        else
135
        {
136
                iccfgr = mfspr (SPR_ICCFGR);
137
 
138
                /* Number of ways */
139
                ic_ways = (1 << (iccfgr & SPR_ICCFGR_NCW));
140
 
141
                /* Number of sets */
142
                ic_sets = 1 << ((iccfgr & SPR_ICCFGR_NCS) >>
143
                                SPR_ICCFGR_NCS_OFF);
144
 
145
                /* Block size */
146
                ic_bs = 16 << ((iccfgr & SPR_ICCFGR_CBS) >> SPR_ICCFGR_CBS_OFF);
147
 
148
                ic_present = 1;
149
        }
150
 
151
        if (!(upr & SPR_UPR_DCP))
152
        {
153
                printf("No data cache present. Skipping tests.\n");
154
        }
155
        else
156
        {
157
                dccfgr = mfspr (SPR_DCCFGR);
158
 
159
                /* Number of ways */
160
                dc_ways = (1 << (dccfgr & SPR_DCCFGR_NCW));
161
 
162
                /* Number of sets */
163
                dc_sets = 1 << ((dccfgr & SPR_DCCFGR_NCS) >>
164
                                SPR_DCCFGR_NCS_OFF);
165
 
166
                /* Block size */
167
                dc_bs = 16 << ((dccfgr & SPR_DCCFGR_CBS) >> SPR_DCCFGR_CBS_OFF);
168
 
169
                dc_present = 1;
170
        }
171
 
172
}
173
 
174 90 jeremybenn
int dc_test(void)
175
{
176
        int i;
177
        unsigned long base, add, ul;
178
 
179
        base = (((unsigned long)MEM_RAM / (IC_SETS*IC_BLOCK_SIZE)) * IC_SETS*IC_BLOCK_SIZE) + IC_SETS*IC_BLOCK_SIZE;
180
 
181
        dc_enable();
182
 
183
        /* Cache miss r */
184
        add = base;
185
        for(i = 0; i < DC_WAYS; i++) {
186
                ul = REG32(add);
187
                ul = REG32(add + DC_BLOCK_SIZE + 4);
188
                ul = REG32(add + 2*DC_BLOCK_SIZE + 8);
189
                ul = REG32(add + 3*DC_BLOCK_SIZE + 12);
190
                add += DC_SETS*DC_BLOCK_SIZE;
191
        }
192
 
193
        /* Cache hit w */
194
        add = base;
195
        for(i = 0; i < DC_WAYS; i++) {
196
                REG32(add + 0) = 0x00000001;
197
                REG32(add + 4) = 0x00000000;
198
                REG32(add + 8) = 0x00000000;
199
                REG32(add + 12) = 0x00000000;
200
                REG32(add + DC_BLOCK_SIZE + 0) = 0x00000000;
201
                REG32(add + DC_BLOCK_SIZE + 4) = 0x00000002;
202
                REG32(add + DC_BLOCK_SIZE + 8) = 0x00000000;
203
                REG32(add + DC_BLOCK_SIZE + 12) = 0x00000000;
204
                REG32(add + 2*DC_BLOCK_SIZE + 0) = 0x00000000;
205
                REG32(add + 2*DC_BLOCK_SIZE + 4) = 0x00000000;
206
                REG32(add + 2*DC_BLOCK_SIZE + 8) = 0x00000003;
207
                REG32(add + 2*DC_BLOCK_SIZE + 12) = 0x00000000;
208
                REG32(add + 3*DC_BLOCK_SIZE + 0) = 0x00000000;
209
                REG32(add + 3*DC_BLOCK_SIZE + 4) = 0x00000000;
210
                REG32(add + 3*DC_BLOCK_SIZE + 8) = 0x00000000;
211
                REG32(add + 3*DC_BLOCK_SIZE + 12) = 0x00000004;
212
                add += DC_SETS*DC_BLOCK_SIZE;
213
        }
214
 
215
        /* Cache hit r/w */
216
        add = base;
217
        for(i = 0; i < DC_WAYS; i++) {
218
                REG8(add + DC_BLOCK_SIZE - 4) = REG8(add + 3);
219
                REG8(add + 2*DC_BLOCK_SIZE - 8) = REG8(add + DC_BLOCK_SIZE + 7);
220
                REG8(add + 3*DC_BLOCK_SIZE - 12) = REG8(add + 2*DC_BLOCK_SIZE + 11);
221
                REG8(add + 4*DC_BLOCK_SIZE - 16) = REG8(add + 3*DC_BLOCK_SIZE + 15);
222
                add += DC_SETS*DC_BLOCK_SIZE;
223
        }
224
 
225
        /* Cache hit/miss r/w */
226
        add = base;
227
        for(i = 0; i < DC_WAYS; i++) {
228
                REG16(add + (IC_SETS - 1)*IC_BLOCK_SIZE) = REG16(add + DC_BLOCK_SIZE - 4) + REG16(add + 2);
229
                REG16(add + (IC_SETS - 1)*IC_BLOCK_SIZE + 2) = REG16(add + DC_BLOCK_SIZE - 8) + REG16(add + DC_BLOCK_SIZE + 6);
230
                REG16(add + (IC_SETS - 1)*IC_BLOCK_SIZE + 4) = REG16(add + DC_BLOCK_SIZE - 12) + REG16(add + 2*DC_BLOCK_SIZE + 10);
231
                REG16(add + (IC_SETS - 1)*IC_BLOCK_SIZE + 6) = REG16(add+ DC_BLOCK_SIZE - 16) + REG16(add + 2*DC_BLOCK_SIZE + 14);
232
                add += DC_SETS*DC_BLOCK_SIZE;
233
        }
234
 
235
        /* Fill cache with unused data */
236
        add = base + DC_WAYS*DC_SETS*DC_BLOCK_SIZE;
237
        for(i = 0; i < DC_WAYS; i++) {
238
                ul = REG32(add);
239
                ul = REG32(add + DC_BLOCK_SIZE);
240
                ul = REG32(add + 2*DC_BLOCK_SIZE);
241
                ul = REG32(add + 3*DC_BLOCK_SIZE);
242
                add += DC_SETS*DC_BLOCK_SIZE;
243
        }
244
 
245
        /* Cache hit/miss r */
246
        ul = 0;
247
        add = base;
248
        for(i = 0; i < DC_WAYS; i++) {
249
                ul +=   REG16(add + (IC_SETS - 1)*IC_BLOCK_SIZE) +
250
                        REG16(add + DC_BLOCK_SIZE - 4) +
251
                        REG16(add + 2);
252
                ul +=   REG16(add + (IC_SETS - 1)*IC_BLOCK_SIZE + 2) +
253
                        REG16(add + DC_BLOCK_SIZE - 8) +
254
                        REG16(add + DC_BLOCK_SIZE + 6);
255
                ul +=   REG16(add + (IC_SETS - 1)*IC_BLOCK_SIZE + 4) +
256
                        REG16(add + DC_BLOCK_SIZE - 12) +
257
                        REG16(add + 2*DC_BLOCK_SIZE + 10);
258
                ul +=   REG16(add + (IC_SETS - 1)*IC_BLOCK_SIZE + 6) +
259
                        REG16(add+ DC_BLOCK_SIZE - 16) +
260
                        REG16(add + 2*DC_BLOCK_SIZE + 14);
261
                add += DC_SETS*DC_BLOCK_SIZE;
262
        }
263
 
264
        dc_disable();
265
 
266
        return ul;
267
}
268
 
269
int ic_test(void)
270
{
271
        int i;
272 458 julius
        unsigned long base, addr;
273 90 jeremybenn
 
274 458 julius
        base = (((unsigned int)program_ram_end / (IC_SETS*IC_BLOCK_SIZE)) *
275
                IC_SETS*IC_BLOCK_SIZE) + IC_SETS*IC_BLOCK_SIZE;
276
        //printf("ic_test\n");
277
        //printf("Test program from base at 0x%08x\n",(unsigned int)base);
278 90 jeremybenn
        /* Copy jr to various location */
279 458 julius
        addr = base;
280 90 jeremybenn
        for(i = 0; i < IC_WAYS; i++) {
281 458 julius
                copy_jr(addr);
282
                copy_jr(addr + 2*IC_BLOCK_SIZE + 4);
283
                copy_jr(addr + 4*IC_BLOCK_SIZE + 8);
284
                copy_jr(addr + 6*IC_BLOCK_SIZE + 12);
285 90 jeremybenn
 
286 458 julius
                copy_jr(addr + (IC_SETS - 2)*IC_BLOCK_SIZE + 0);
287
                copy_jr(addr + (IC_SETS - 4)*IC_BLOCK_SIZE + 4);
288
                copy_jr(addr + (IC_SETS - 6)*IC_BLOCK_SIZE + 8);
289
                copy_jr(addr + (IC_SETS - 8)*IC_BLOCK_SIZE + 12);
290
                addr += IC_SETS*IC_BLOCK_SIZE;
291 90 jeremybenn
        }
292
 
293 458 julius
        /* Load execution table which starts at address 4
294
           (at address 0 is table index) */
295
        addr = base;
296 90 jeremybenn
        for(i = 0; i < IC_WAYS; i++) {
297
                /* Cache miss */
298 458 julius
                jump_addr[15*i + 0] = addr + 2*IC_BLOCK_SIZE + 4;
299
                jump_addr[15*i + 1] = addr + 4*IC_BLOCK_SIZE + 8;
300
                jump_addr[15*i + 2] = addr + 6*IC_BLOCK_SIZE + 12;
301 90 jeremybenn
                /* Cache hit/miss */
302 458 julius
                jump_addr[15*i + 3] = addr;
303
                jump_addr[15*i + 4] = addr + (IC_SETS - 2)*IC_BLOCK_SIZE + 0;
304
                jump_addr[15*i + 5] = addr + 2*IC_BLOCK_SIZE + 4;
305
                jump_addr[15*i + 6] = addr + (IC_SETS - 4)*IC_BLOCK_SIZE + 4;
306
                jump_addr[15*i + 7] = addr + 4*IC_BLOCK_SIZE + 8;
307
                jump_addr[15*i + 8] = addr + (IC_SETS - 6)*IC_BLOCK_SIZE + 8;
308
                jump_addr[15*i + 9] = addr + 6*IC_BLOCK_SIZE + 12;
309
                jump_addr[15*i + 10] = addr + (IC_SETS - 8)*IC_BLOCK_SIZE + 12;
310 90 jeremybenn
                /* Cache hit */
311 458 julius
                jump_addr[15*i + 11] = addr + (IC_SETS - 2)*IC_BLOCK_SIZE + 0;
312
                jump_addr[15*i + 12] = addr + (IC_SETS - 4)*IC_BLOCK_SIZE + 4;
313
                jump_addr[15*i + 13] = addr + (IC_SETS - 6)*IC_BLOCK_SIZE + 8;
314
                jump_addr[15*i + 14] = addr + (IC_SETS - 8)*IC_BLOCK_SIZE + 12;
315 90 jeremybenn
 
316 458 julius
                addr += IC_SETS*IC_BLOCK_SIZE;
317 90 jeremybenn
        }
318
 
319
        /* Go home */
320 458 julius
        /* Warning - if using all 32 sets, the SET_MAX define above will need
321
         to be incremented*/
322
        jump_addr[15*i] = (unsigned long)&jalr;
323 90 jeremybenn
 
324
        /* Initilalize table index */
325 458 julius
        jump_indx = (unsigned long)&jump_addr[0];
326 90 jeremybenn
 
327
        ic_enable();
328
 
329
        /* Go */
330
        call(base);
331
 
332
        ic_disable();
333
 
334
        return 0;
335
}
336
 
337
/* Each of the 5 reports should be 0xdeaddead if the code is working
338
   correctly. */
339
int main(void)
340
{
341
        unsigned long rc, ret = 0;
342
 
343 458 julius
        program_ram_end = (unsigned int)&_ram_end;
344
        program_ram_end += 4;
345 90 jeremybenn
 
346
 
347 458 julius
        /* Read UPR and configuration registers, extract cache settings */
348
        init_cache_config();
349 90 jeremybenn
 
350 458 julius
        if (dc_present)
351
        {
352
                report(0);
353
 
354
                rc = dc_test();
355
 
356
                ret += rc;
357 90 jeremybenn
 
358 458 julius
                report(rc + 0xdeaddca1);
359
 
360
                report(1);
361
 
362
                rc = dc_inv_test(MEM_RAM);
363
 
364
                ret += rc;
365
 
366
                report(rc + 0x9e8daa91);
367
        }
368 90 jeremybenn
 
369 458 julius
        if (ic_present)
370
        {
371
                report(2);
372
 
373
                rc = ic_test();
374
 
375
                ret += rc;
376
 
377
                report(rc + 0xdeaddead);
378 90 jeremybenn
 
379 458 julius
                report(3);
380
 
381
                ic_enable();
382
 
383
                report(4);
384
 
385
                rc = ic_inv_test();
386
 
387
                ret += rc;
388
 
389
                report(rc + 0xdeadde8f);
390
 
391
                report(ret + 0x9e8da867);
392
        }
393
 
394
        exit(0);
395 90 jeremybenn
 
396
        return 0;
397 458 julius
 
398 90 jeremybenn
}
399
 
400
/* just for size calculation */
401
void dummy()
402
{
403
}

powered by: WebSVN 2.1.0

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