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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [kernel/] [current/] [tests/] [kcache2.c] - Blame information for rev 838

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

Line No. Rev Author Line
1 786 skrzyp
/*=================================================================
2
//
3
//        kcache2.c
4
//
5
//        Cache feature/timing tests
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later
16
// version.
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
21
// for more details.
22
//
23
// You should have received a copy of the GNU General Public License
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
26
//
27
// As a special exception, if other files instantiate templates or use
28
// macros or inline functions from this file, or you compile this file
29
// and link it with other works to produce a work based on this file,
30
// this file does not by itself cause the resulting work to be covered by
31
// the GNU General Public License. However the source code for this file
32
// must still be made available in accordance with section (3) of the GNU
33
// General Public License v2.
34
//
35
// This exception does not invalidate any other reasons why a work based
36
// on this file might be covered by the GNU General Public License.
37
// -------------------------------------------
38
// ####ECOSGPLCOPYRIGHTEND####
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):     jskov, based on kcache1.c by dsm
43
// Contributors:  jskov, gthomas
44
// Date:          1998-12-10
45
// Description:   Tests some of the more exotic cache macros.
46
//####DESCRIPTIONEND####
47
*/
48
 
49
#include <cyg/hal/hal_arch.h>           // CYGNUM_HAL_STACK_SIZE_TYPICAL
50
 
51
#include <cyg/kernel/kapi.h>
52
 
53
#include <cyg/infra/testcase.h>
54
 
55
#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK
56
#ifdef CYGFUN_KERNEL_API_C
57
 
58
#include <cyg/infra/diag.h>
59
#include <cyg/hal/hal_cache.h>
60
 
61
// -------------------------------------------------------------------------
62
 
63
#define NTHREADS 1
64
#define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
65
 
66
// The following are defaults for loop variables. Note they will be overriden
67
// on simulator targets, where detected - there is no point testing a cache
68
// which doesn't exist :-).
69
 
70
#define TEST_DZERO_LOOPS 5000  // default number of loops for test_dzero()
71
#define TIME_ILOCK_LOOPS 10000 // default number of loops for time_ilock()
72
#define TIME_DLOCK_LOOPS 10000 // default number of loops for time_dlock()
73
 
74
// Define this to enable a simple, but hopefully useful, data cache
75
// test.  It may help discover if the cache support has been defined
76
// properly (in terms of size and shape)
77
#ifdef HAL_DCACHE_LINE_SIZE
78
#define _TEST_DCACHE_OPERATION
79
#endif
80
 
81
static cyg_handle_t thread[NTHREADS];
82
 
83
static cyg_thread thread_obj[NTHREADS];
84
static char stack[NTHREADS][STACKSIZE];
85
 
86
#define MAXSIZE 1<<18
87
 
88
volatile char m[MAXSIZE];
89
 
90
// -------------------------------------------------------------------------
91
// Test of data cache zero.
92
//  o Timing comparison with instructions doing the same amount of work.
93
//  o Check that area cleared with the DCACHE_ZERO macro contains zeros.
94
#ifdef HAL_DCACHE_ZERO
95
static void test_dzero(void)
96
{
97
    register cyg_uint32 k, i;
98
    cyg_tick_count_t count0, count1;
99
    cyg_ucount32 t;
100
    volatile cyg_uint32* aligned_p;
101
    volatile cyg_uint32* p;
102
    register CYG_INTERRUPT_STATE oldints;
103
    cyg_ucount32 test_dzero_loops = TEST_DZERO_LOOPS;
104
 
105
    CYG_TEST_INFO("Data cache zero");
106
 
107
    if (cyg_test_is_simulator)
108
        test_dzero_loops=10;
109
 
110
    aligned_p =  (volatile cyg_uint32*)
111
        (((unsigned long) &m[HAL_DCACHE_LINE_SIZE*2])
112
         & ~(HAL_DCACHE_LINE_SIZE-1));
113
 
114
    // Time with conventional instructions.
115
    HAL_DISABLE_INTERRUPTS(oldints);
116
    HAL_DCACHE_SYNC();
117
    HAL_DCACHE_DISABLE();
118
    HAL_DCACHE_SYNC();
119
    HAL_DCACHE_INVALIDATE_ALL();
120
    HAL_DCACHE_ENABLE();
121
    HAL_RESTORE_INTERRUPTS(oldints);
122
    count0 = cyg_current_time();
123
    for (k = 0; k < test_dzero_loops; k++) {
124
        p = aligned_p;
125
        for (i = 0; i < HAL_DCACHE_SETS; i++) {
126
#if (16 == HAL_DCACHE_LINE_SIZE)
127
            *p++ = 0;
128
            *p++ = 0;
129
            *p++ = 0;
130
            *p++ = 0;
131
#elif (32 == HAL_DCACHE_LINE_SIZE)
132
            *p++ = 0;
133
            *p++ = 0;
134
            *p++ = 0;
135
            *p++ = 0;
136
            *p++ = 0;
137
            *p++ = 0;
138
            *p++ = 0;
139
            *p++ = 0;
140
#else
141
#error "Not defined for this cache line size."
142
#endif
143
        }
144
 
145
        HAL_DISABLE_INTERRUPTS(oldints);
146
        HAL_DCACHE_SYNC();
147
        HAL_DCACHE_DISABLE();
148
        HAL_DCACHE_SYNC();
149
        HAL_DCACHE_INVALIDATE_ALL();
150
        HAL_DCACHE_ENABLE();
151
        HAL_RESTORE_INTERRUPTS(oldints);
152
    }
153
    count1 = cyg_current_time();
154
    t = count1 - count0;
155
    diag_printf("time with instructions:    %d\n", t);
156
 
157
    // Initialize the area with non-zero so we can check whether
158
    // the macro cleared the area properly.
159
    p = aligned_p;
160
    for (i = 0;
161
         i < HAL_DCACHE_SETS*HAL_DCACHE_LINE_SIZE/sizeof(cyg_uint32);
162
         i++) {
163
        *p++ = 0xdeadbeef;
164
    }
165
 
166
    // Time with DCACHE_ZERO.
167
    HAL_DISABLE_INTERRUPTS(oldints);
168
    HAL_DCACHE_SYNC();
169
    HAL_DCACHE_DISABLE();
170
    HAL_DCACHE_SYNC();
171
    HAL_DCACHE_INVALIDATE_ALL();
172
    HAL_DCACHE_ENABLE();
173
    HAL_RESTORE_INTERRUPTS(oldints);
174
    count0 = cyg_current_time();
175
    for (k = 0; k < test_dzero_loops; k++) {
176
        HAL_DCACHE_ZERO(aligned_p, HAL_DCACHE_SETS*HAL_DCACHE_LINE_SIZE);
177
 
178
        HAL_DISABLE_INTERRUPTS(oldints);
179
        HAL_DCACHE_SYNC();
180
        HAL_DCACHE_DISABLE();
181
        HAL_DCACHE_SYNC();
182
        HAL_DCACHE_INVALIDATE_ALL();
183
        HAL_DCACHE_ENABLE();
184
        HAL_RESTORE_INTERRUPTS(oldints);
185
    }
186
    count1 = cyg_current_time();
187
    t = count1 - count0;
188
    diag_printf("time with HAL_DCACHE_ZERO: %d\n", t);
189
 
190
    // Verify that the area was actually cleared.
191
    {
192
        cyg_uint32 d;
193
 
194
        d = 0;
195
        p = aligned_p;
196
        for (i = 0;
197
             i < HAL_DCACHE_SETS*HAL_DCACHE_LINE_SIZE/sizeof(cyg_uint32);
198
             i++) {
199
            d |= *p++;
200
        }
201
 
202
        CYG_TEST_CHECK(0 == d, "region not properly cleared");
203
    }
204
 
205
}
206
#endif
207
 
208
// -------------------------------------------------------------------------
209
// Test of data cache write hint.
210
// Just check that the macro compiles.
211
#ifdef HAL_DCACHE_WRITE_HINT
212
static void test_dwrite_hint(void)
213
{
214
    register cyg_uint32 k;
215
    register CYG_INTERRUPT_STATE oldints;
216
 
217
    CYG_TEST_INFO("Data cache write hint");
218
 
219
    HAL_DISABLE_INTERRUPTS(oldints);
220
    HAL_DCACHE_SYNC();
221
    HAL_DCACHE_DISABLE();
222
    HAL_DCACHE_SYNC();
223
    HAL_DCACHE_INVALIDATE_ALL();
224
    HAL_DCACHE_ENABLE();
225
    HAL_RESTORE_INTERRUPTS(oldints);
226
 
227
    HAL_DCACHE_WRITE_HINT(&m[HAL_DCACHE_LINE_SIZE*2], 2*HAL_DCACHE_LINE_SIZE);
228
    for (k = 0; k < 20; k++);
229
    m[HAL_DCACHE_LINE_SIZE*2] = 42;
230
}
231
#endif
232
 
233
// -------------------------------------------------------------------------
234
// Test of data cache read hint.
235
// Just check that the macro compiles.
236
#ifdef HAL_DCACHE_READ_HINT
237
static void test_dread_hint(void)
238
{
239
    register char c;
240
    register cyg_uint32 k;
241
    register CYG_INTERRUPT_STATE oldints;
242
 
243
    CYG_TEST_INFO("Data cache read hint");
244
 
245
    HAL_DISABLE_INTERRUPTS(oldints);
246
    HAL_DCACHE_SYNC();
247
    HAL_DCACHE_DISABLE();
248
    HAL_DCACHE_SYNC();
249
    HAL_DCACHE_INVALIDATE_ALL();
250
    HAL_DCACHE_ENABLE();
251
    HAL_RESTORE_INTERRUPTS(oldints);
252
 
253
    HAL_DCACHE_READ_HINT(&m[HAL_DCACHE_LINE_SIZE*2], 2*HAL_DCACHE_LINE_SIZE);
254
    for (k = 0; k < 20; k++);
255
    c = m[HAL_DCACHE_LINE_SIZE*2];
256
}
257
#endif
258
 
259
// -------------------------------------------------------------------------
260
// Test of data cache line store
261
//  o No semantic requirement.
262
//  o Check that flushed data is written to memory.
263
//  o Simple invocation check of macro.
264
#ifdef HAL_DCACHE_STORE
265
static void test_dstore(void)
266
{
267
    volatile cyg_uint8* aligned_p;
268
    cyg_int32 i;
269
    register CYG_INTERRUPT_STATE oldints;
270
 
271
    CYG_TEST_INFO("Data cache store region");
272
 
273
    for (i = 0; i < HAL_DCACHE_LINE_SIZE*16; i++)
274
        m[i] = 0;
275
 
276
    HAL_DISABLE_INTERRUPTS(oldints);
277
    HAL_DCACHE_SYNC();
278
    HAL_DCACHE_DISABLE();
279
    HAL_DCACHE_SYNC();
280
    HAL_DCACHE_INVALIDATE_ALL();
281
    HAL_DCACHE_ENABLE();
282
 
283
    aligned_p =  (volatile cyg_uint8*)
284
        (((unsigned long) &m[HAL_DCACHE_LINE_SIZE*2])
285
         & ~(HAL_DCACHE_LINE_SIZE-1));
286
 
287
    aligned_p[0] = 42 + aligned_p[1]; // Load causes cache to be used!
288
 
289
    HAL_DCACHE_STORE(aligned_p, HAL_DCACHE_LINE_SIZE);
290
 
291
    CYG_TEST_CHECK(42 == aligned_p[0],
292
                   "memory didn't contain flushed data");
293
 
294
    HAL_DCACHE_INVALIDATE_ALL(); // Discard...
295
 
296
    CYG_TEST_CHECK(42 == aligned_p[0],
297
                   "memory didn't contain flushed data after invalidate all");
298
 
299
    HAL_RESTORE_INTERRUPTS(oldints);
300
}
301
#endif
302
 
303
// -------------------------------------------------------------------------
304
// Test of data cache total flush (sync).
305
//  o No semantic requirement.
306
//  o Check that flushed data is written to memory.
307
//  o Simple invocation check of macro.
308
#ifdef HAL_DCACHE_LINE_SIZE // So we can find our way around memory
309
 
310
#ifdef _TEST_DCACHE_OPERATION
311
static void
312
test_dcache_operation(void)
313
{
314
    long *lp = (long *)m;
315
    int i, errs;
316
    cyg_uint32 oldints;
317
 
318
    CYG_TEST_INFO("Data cache basic");
319
 
320
    HAL_DISABLE_INTERRUPTS(oldints);
321
    HAL_DCACHE_SYNC();
322
    HAL_DCACHE_DISABLE();
323
    HAL_DCACHE_SYNC();
324
    // Fill test buffer
325
    for (i = 0;  i < sizeof(m)/sizeof(*lp);  i++) {
326
        lp[i] = i;
327
    }
328
    HAL_DCACHE_INVALIDATE_ALL();
329
    HAL_DCACHE_ENABLE();
330
    // Now push data through the cache
331
    // Note: 256 seems like a reasonable offset.  It may be useful to actually
332
    // compute this (and the size of the test region) based on cache geometry
333
    for (i = 256;  i < 256+HAL_DCACHE_SIZE/sizeof(*lp);  i++) {
334
        lp[i] = 0xFF000000 + i;
335
    }
336
    // Now force cache clean and off
337
    HAL_DCACHE_SYNC();
338
    HAL_DCACHE_DISABLE();
339
    // Verify the data
340
    diag_printf("Verify data with cache off\n");
341
    errs = 0;
342
    for (i = 0;  i < sizeof(m)/sizeof(*lp);  i++) {
343
        if ((i >= 256) && (i < 256+HAL_DCACHE_SIZE/sizeof(*lp))) {
344
            if (lp[i] != (0xFF000000 + i)) {
345
                if (++errs < 16) {
346
                    diag_printf("Data inside test range changed - was: %x, is %lx, index: %x\n",
347
                                0xFF000000+i, lp[i], i);
348
                }
349
            }
350
        } else {
351
            if (lp[i] != i) {
352
                if (++errs < 16) {
353
                    diag_printf("Data outside test range changed - was: %x, is %lx, index: %x\n",
354
                                i, lp[i], i);
355
                }
356
            }
357
        }
358
    }
359
    CYG_TEST_CHECK(0 == errs, "dcache basic failed");
360
#if 0 // Additional information
361
    diag_printf("%d total errors during compare\n", errs);
362
    diag_dump_buf(&lp[240], 128);
363
#endif
364
    HAL_RESTORE_INTERRUPTS(oldints);
365
}
366
#endif
367
 
368
static void test_dsync(void)
369
{
370
    volatile cyg_uint8* aligned_p;
371
    cyg_int32 i;
372
    register CYG_INTERRUPT_STATE oldints;
373
 
374
    CYG_TEST_INFO("Data cache sync all");
375
 
376
    for (i = 0; i < HAL_DCACHE_LINE_SIZE*16; i++)
377
        m[i] = 0;
378
 
379
    HAL_DISABLE_INTERRUPTS(oldints);
380
    HAL_DCACHE_SYNC();
381
    HAL_DCACHE_DISABLE();
382
    HAL_DCACHE_SYNC();
383
    HAL_DCACHE_INVALIDATE_ALL();
384
    HAL_DCACHE_ENABLE();
385
 
386
    aligned_p =  (volatile cyg_uint8*)
387
        (((unsigned long) &m[HAL_DCACHE_LINE_SIZE*2])
388
         & ~(HAL_DCACHE_LINE_SIZE-1));
389
 
390
    aligned_p[0] = 42 + aligned_p[1]; // Load causes cache to be used!
391
    aligned_p[HAL_DCACHE_LINE_SIZE] = 43 + aligned_p[HAL_DCACHE_LINE_SIZE + 1];
392
 
393
    HAL_DCACHE_SYNC();
394
 
395
    CYG_TEST_CHECK(42 == aligned_p[0],
396
                   "memory didn't contain flushed data");
397
    CYG_TEST_CHECK(43 == aligned_p[HAL_DCACHE_LINE_SIZE],
398
                   "memory didn't contain flushed data next block");
399
 
400
    HAL_DCACHE_INVALIDATE_ALL();
401
 
402
    CYG_TEST_CHECK(42 == aligned_p[0],
403
                   "memory didn't contain flushed data after invalidate");
404
    CYG_TEST_CHECK(43 == aligned_p[HAL_DCACHE_LINE_SIZE],
405
                   "memory didn't contain flushed data next block after invalidate");
406
 
407
    HAL_RESTORE_INTERRUPTS(oldints);
408
 
409
    HAL_ICACHE_INVALIDATE_ALL();
410
    HAL_DCACHE_DISABLE();
411
 
412
    CYG_TEST_CHECK(42 == aligned_p[0],
413
                   "memory didn't contain flushed data after disable");
414
    CYG_TEST_CHECK(43 == aligned_p[HAL_DCACHE_LINE_SIZE],
415
                   "memory didn't contain flushed data next block after disable");
416
 
417
    HAL_DCACHE_ENABLE();
418
}
419
#endif // HAL_DCACHE_LINE_SIZE
420
 
421
// -------------------------------------------------------------------------
422
// Test of data cache line flush.
423
//  o Requires write-back cache.
424
//  o Check that flushed data is written to memory.
425
//  o Simple range check of macro.
426
#ifdef HAL_DCACHE_QUERY_WRITE_MODE // only if we know this, can we test:
427
#ifdef HAL_DCACHE_FLUSH
428
static void test_dflush(void)
429
{
430
    volatile cyg_uint8* aligned_p;
431
    cyg_int32 i;
432
    register CYG_INTERRUPT_STATE oldints;
433
 
434
    CYG_TEST_INFO("Data cache flush region");
435
 
436
    for (i = 0; i < HAL_DCACHE_LINE_SIZE*16; i++)
437
        m[i] = 0;
438
 
439
    HAL_DISABLE_INTERRUPTS(oldints);
440
    HAL_DCACHE_SYNC();
441
    HAL_DCACHE_DISABLE();
442
    HAL_DCACHE_SYNC();
443
    HAL_DCACHE_INVALIDATE_ALL();
444
    HAL_DCACHE_ENABLE();
445
    HAL_RESTORE_INTERRUPTS(oldints);
446
 
447
    aligned_p =  (volatile cyg_uint8*)
448
        (((unsigned long) &m[HAL_DCACHE_LINE_SIZE*2])
449
         & ~(HAL_DCACHE_LINE_SIZE-1));
450
 
451
    HAL_DISABLE_INTERRUPTS(oldints);
452
 
453
    aligned_p[0] = 42 + aligned_p[1]; // Load causes cache to be used!
454
    aligned_p[HAL_DCACHE_LINE_SIZE] = 43 + aligned_p[HAL_DCACHE_LINE_SIZE + 1];
455
 
456
    HAL_DCACHE_FLUSH(aligned_p, HAL_DCACHE_LINE_SIZE);
457
 
458
    HAL_DCACHE_DISABLE();
459
 
460
    HAL_RESTORE_INTERRUPTS(oldints);
461
 
462
    CYG_TEST_CHECK(42 == aligned_p[0],
463
                   "memory didn't contain flushed data");
464
    CYG_TEST_CHECK(0 == aligned_p[HAL_DCACHE_LINE_SIZE],
465
                   "flushed beyond region");
466
 
467
    HAL_DCACHE_ENABLE();
468
}
469
#endif
470
#endif
471
 
472
// -------------------------------------------------------------------------
473
// Test of data cache disable (which does NOT force contents out to RAM)
474
//  o Requires write-back cache [so NOT invoked unconditionally]
475
//  o Check that dirty data is not written to memory and is invalidated
476
//    in the cache.
477
//  o Simple invocation check of macro.
478
#ifdef HAL_DCACHE_QUERY_WRITE_MODE // only if we know this, can we test:
479
static void test_ddisable(void)
480
{
481
    volatile cyg_uint8* aligned_p;
482
    cyg_int32 i;
483
    register CYG_INTERRUPT_STATE oldints;
484
 
485
    CYG_TEST_INFO("Data cache gross disable");
486
 
487
    for (i = 0; i < HAL_DCACHE_LINE_SIZE*16; i++)
488
        m[i] = 0;
489
 
490
    HAL_DISABLE_INTERRUPTS(oldints);
491
    HAL_DCACHE_SYNC();
492
    HAL_DCACHE_DISABLE();
493
    HAL_DCACHE_SYNC();
494
    HAL_DCACHE_INVALIDATE_ALL();
495
    HAL_DCACHE_ENABLE();
496
    HAL_RESTORE_INTERRUPTS(oldints);
497
 
498
    aligned_p =  (volatile cyg_uint8*)
499
        (((unsigned long) &m[HAL_DCACHE_LINE_SIZE*2])
500
         & ~(HAL_DCACHE_LINE_SIZE-1));
501
 
502
    HAL_DISABLE_INTERRUPTS(oldints);
503
 
504
    aligned_p[0] = 43 + aligned_p[1]; // Load causes cache to be used!
505
    aligned_p[HAL_DCACHE_LINE_SIZE-1] = 43;
506
 
507
    aligned_p[HAL_DCACHE_LINE_SIZE] = 42 + aligned_p[HAL_DCACHE_LINE_SIZE + 1];
508
 
509
    HAL_DCACHE_DISABLE();
510
 
511
    HAL_RESTORE_INTERRUPTS(oldints);
512
 
513
    CYG_TEST_CHECK(0 == aligned_p[0] &&
514
 
515
                   "cache/memory contained invalidated data");
516
    CYG_TEST_CHECK(0 == aligned_p[HAL_DCACHE_LINE_SIZE],
517
                   "next block contained invalidated data");
518
 
519
    HAL_DCACHE_ENABLE();
520
}
521
#endif // def HAL_DCACHE_QUERY_WRITE_MODE
522
 
523
// -------------------------------------------------------------------------
524
// Test of data cache total invalidate.
525
//  o Requires write-back cache.
526
//  o Check that invalidated data is not written to memory and is invalidated
527
//    in the cache.
528
//  o Simple invocation check of macro.
529
#ifdef HAL_DCACHE_QUERY_WRITE_MODE // only if we know this, can we test:
530
#ifdef HAL_DCACHE_INVALIDATE_ALL
531
static void test_dinvalidate_all(void)
532
{
533
    volatile cyg_uint8* aligned_p;
534
    cyg_int32 i;
535
    register CYG_INTERRUPT_STATE oldints;
536
 
537
    CYG_TEST_INFO("Data cache invalidate all");
538
 
539
    for (i = 0; i < HAL_DCACHE_LINE_SIZE*16; i++)
540
        m[i] = 0;
541
 
542
    HAL_DISABLE_INTERRUPTS(oldints);
543
    HAL_DCACHE_SYNC();
544
    HAL_DCACHE_DISABLE();
545
    HAL_DCACHE_SYNC();
546
    HAL_DCACHE_INVALIDATE_ALL();
547
    HAL_DCACHE_ENABLE();
548
 
549
    aligned_p =  (volatile cyg_uint8*)
550
        (((unsigned long) &m[HAL_DCACHE_LINE_SIZE*2])
551
         & ~(HAL_DCACHE_LINE_SIZE-1));
552
 
553
    aligned_p[0] = 43 + aligned_p[1]; // Load causes cache to be used!
554
    aligned_p[HAL_DCACHE_LINE_SIZE-1] = 43;
555
 
556
    aligned_p[HAL_DCACHE_LINE_SIZE] = 42 + aligned_p[HAL_DCACHE_LINE_SIZE + 1];
557
 
558
    HAL_DCACHE_INVALIDATE_ALL();
559
 
560
    HAL_RESTORE_INTERRUPTS(oldints);
561
 
562
    CYG_TEST_CHECK(0 == aligned_p[0] &&
563
 
564
                   "cache/memory contained invalidated data");
565
    CYG_TEST_CHECK(0 == aligned_p[HAL_DCACHE_LINE_SIZE],
566
                   "next block contained invalidated data");
567
}
568
#endif
569
#endif // def HAL_DCACHE_QUERY_WRITE_MODE
570
 
571
// -------------------------------------------------------------------------
572
// Test of data cache line invalidate.
573
//  o Requires write-back cache.
574
//  o Check that invalidated data is not written to memory and is invalidated
575
//    in the cache.
576
//  o Simple range check of macro.
577
#ifdef HAL_DCACHE_QUERY_WRITE_MODE // only if we know this, can we test:
578
#ifdef HAL_DCACHE_INVALIDATE
579
static void test_dinvalidate(void)
580
{
581
    volatile cyg_uint8* aligned_p;
582
    cyg_int32 i;
583
    register CYG_INTERRUPT_STATE oldints;
584
 
585
    CYG_TEST_INFO("Data cache invalidate region");
586
 
587
    for (i = 0; i < HAL_DCACHE_LINE_SIZE*16; i++)
588
        m[i] = 0;
589
 
590
    HAL_DISABLE_INTERRUPTS(oldints);
591
    HAL_DCACHE_SYNC();
592
    HAL_DCACHE_DISABLE();
593
    HAL_DCACHE_SYNC();
594
    HAL_DCACHE_INVALIDATE_ALL();
595
    HAL_DCACHE_ENABLE();
596
    HAL_RESTORE_INTERRUPTS(oldints);
597
 
598
    aligned_p =  (volatile cyg_uint8*)
599
        (((unsigned long) &m[HAL_DCACHE_LINE_SIZE*2])
600
         & ~(HAL_DCACHE_LINE_SIZE-1));
601
 
602
    HAL_DISABLE_INTERRUPTS(oldints);
603
 
604
    aligned_p[0] = 43 + aligned_p[1]; // Load causes cache to be used!
605
    aligned_p[HAL_DCACHE_LINE_SIZE-1] = 43;
606
 
607
    aligned_p[HAL_DCACHE_LINE_SIZE] = 42 + aligned_p[HAL_DCACHE_LINE_SIZE + 1];
608
 
609
    HAL_DCACHE_INVALIDATE(aligned_p, HAL_DCACHE_LINE_SIZE);
610
 
611
    HAL_RESTORE_INTERRUPTS(oldints);
612
 
613
    CYG_TEST_CHECK(0 == aligned_p[0] &&
614
 
615
                   "cache/memory contained invalidated data");
616
    CYG_TEST_CHECK(42 == aligned_p[HAL_DCACHE_LINE_SIZE],
617
                   "invalidated beyond range");
618
 
619
    HAL_DCACHE_SYNC();
620
    HAL_DCACHE_DISABLE();
621
 
622
    CYG_TEST_CHECK(0 == aligned_p[0] &&
623
 
624
                   "cache/memory contained invalidated data after SYNC/DIS");
625
    CYG_TEST_CHECK(42 == aligned_p[HAL_DCACHE_LINE_SIZE],
626
                   "invalidated beyond range after SYNC/DIS");
627
 
628
    HAL_DCACHE_ENABLE();
629
}
630
#endif
631
#endif // def HAL_DCACHE_QUERY_WRITE_MODE
632
 
633
// -------------------------------------------------------------------------
634
// Test of instruction cache locking.
635
//  o Time difference between repeatedly executing a bunch of instructions
636
//    with and without locking.
637
#ifdef HAL_ICACHE_LOCK
638
static void iloop(unsigned long* start, unsigned long* end, int dummy)
639
{
640
    // dummy is just used to fool the compiler to not move the labels
641
    // around. All callers should call with dummy=0;
642
 
643
    register char c;
644
    register CYG_INTERRUPT_STATE oldints;
645
 
646
    if (1 == dummy) goto label_end;
647
 
648
 label_start:
649
    // Invalidating shouldn't affect locked lines.
650
    HAL_DISABLE_INTERRUPTS(oldints);
651
    HAL_ICACHE_DISABLE();
652
    HAL_ICACHE_INVALIDATE_ALL();
653
    HAL_ICACHE_ENABLE();
654
    HAL_RESTORE_INTERRUPTS(oldints);
655
 
656
    c = m[HAL_DCACHE_LINE_SIZE*0];
657
    c = m[HAL_DCACHE_LINE_SIZE*1];
658
    c = m[HAL_DCACHE_LINE_SIZE*2];
659
    c = m[HAL_DCACHE_LINE_SIZE*3];
660
    c = m[HAL_DCACHE_LINE_SIZE*4];
661
    c = m[HAL_DCACHE_LINE_SIZE*5];
662
    c = m[HAL_DCACHE_LINE_SIZE*6];
663
    c = m[HAL_DCACHE_LINE_SIZE*7];
664
    c = m[HAL_DCACHE_LINE_SIZE*8];
665
    c = m[HAL_DCACHE_LINE_SIZE*9];
666
    c = m[HAL_DCACHE_LINE_SIZE*10];
667
    c = m[HAL_DCACHE_LINE_SIZE*11];
668
    c = m[HAL_DCACHE_LINE_SIZE*12];
669
    c = m[HAL_DCACHE_LINE_SIZE*13];
670
    c = m[HAL_DCACHE_LINE_SIZE*14];
671
    c = m[HAL_DCACHE_LINE_SIZE*15];
672
    c = m[HAL_DCACHE_LINE_SIZE*16];
673
    c = m[HAL_DCACHE_LINE_SIZE*17];
674
    c = m[HAL_DCACHE_LINE_SIZE*18];
675
    c = m[HAL_DCACHE_LINE_SIZE*19];
676
    c = m[HAL_DCACHE_LINE_SIZE*20];
677
    c = m[HAL_DCACHE_LINE_SIZE*21];
678
    c = m[HAL_DCACHE_LINE_SIZE*22];
679
    c = m[HAL_DCACHE_LINE_SIZE*23];
680
    c = m[HAL_DCACHE_LINE_SIZE*24];
681
    c = m[HAL_DCACHE_LINE_SIZE*25];
682
    c = m[HAL_DCACHE_LINE_SIZE*26];
683
    c = m[HAL_DCACHE_LINE_SIZE*27];
684
    c = m[HAL_DCACHE_LINE_SIZE*28];
685
    c = m[HAL_DCACHE_LINE_SIZE*29];
686
    c = m[HAL_DCACHE_LINE_SIZE*30];
687
    c = m[HAL_DCACHE_LINE_SIZE*31];
688
    c = m[HAL_DCACHE_LINE_SIZE*32];
689
    c = m[HAL_DCACHE_LINE_SIZE*33];
690
    c = m[HAL_DCACHE_LINE_SIZE*34];
691
    c = m[HAL_DCACHE_LINE_SIZE*35];
692
    c = m[HAL_DCACHE_LINE_SIZE*36];
693
    c = m[HAL_DCACHE_LINE_SIZE*37];
694
    c = m[HAL_DCACHE_LINE_SIZE*38];
695
    c = m[HAL_DCACHE_LINE_SIZE*39];
696
    c = m[HAL_DCACHE_LINE_SIZE*40];
697
    c = m[HAL_DCACHE_LINE_SIZE*41];
698
    c = m[HAL_DCACHE_LINE_SIZE*42];
699
    c = m[HAL_DCACHE_LINE_SIZE*43];
700
    c = m[HAL_DCACHE_LINE_SIZE*44];
701
    c = m[HAL_DCACHE_LINE_SIZE*45];
702
    c = m[HAL_DCACHE_LINE_SIZE*46];
703
    c = m[HAL_DCACHE_LINE_SIZE*47];
704
    c = m[HAL_DCACHE_LINE_SIZE*48];
705
    c = m[HAL_DCACHE_LINE_SIZE*49];
706
    c = m[HAL_DCACHE_LINE_SIZE*50];
707
    c = m[HAL_DCACHE_LINE_SIZE*51];
708
    c = m[HAL_DCACHE_LINE_SIZE*52];
709
    c = m[HAL_DCACHE_LINE_SIZE*53];
710
    c = m[HAL_DCACHE_LINE_SIZE*54];
711
    c = m[HAL_DCACHE_LINE_SIZE*55];
712
    c = m[HAL_DCACHE_LINE_SIZE*56];
713
    c = m[HAL_DCACHE_LINE_SIZE*57];
714
    c = m[HAL_DCACHE_LINE_SIZE*58];
715
    c = m[HAL_DCACHE_LINE_SIZE*59];
716
    c = m[HAL_DCACHE_LINE_SIZE*60];
717
    c = m[HAL_DCACHE_LINE_SIZE*61];
718
    c = m[HAL_DCACHE_LINE_SIZE*62];
719
    c = m[HAL_DCACHE_LINE_SIZE*63];
720
 
721
 label_end:
722
 
723
    *start = (unsigned long) &&label_start;
724
    *end = (unsigned long) &&label_end;
725
 
726
    if (1 == dummy) goto label_start;
727
}
728
 
729
static void time_ilock(void)
730
{
731
    register cyg_ucount32 k;
732
    cyg_tick_count_t count0, count1;
733
    cyg_ucount32 t;
734
    unsigned long start, end;
735
    register cyg_ucount32 time_ilock_loops = TIME_ILOCK_LOOPS;
736
 
737
    CYG_TEST_INFO("Instruction cache lock");
738
 
739
    if (cyg_test_is_simulator)
740
        time_ilock_loops = 10;
741
 
742
    count0 = cyg_current_time();
743
    for (k = 0; k < time_ilock_loops; k++) {
744
        iloop(&start, &end, 0);
745
    }
746
    count1 = cyg_current_time();
747
    t = count1 - count0;
748
    diag_printf("time without lock: %d\n", t);
749
 
750
    HAL_ICACHE_LOCK(start, end-start);
751
 
752
    count0 = cyg_current_time();
753
    for (k = 0; k < time_ilock_loops; k++) {
754
        iloop(&start, &end, 0);
755
    }
756
    count1 = cyg_current_time();
757
    t = count1 - count0;
758
    diag_printf("time with lock:    %d\n", t);
759
 
760
    HAL_ICACHE_UNLOCK(start, end-start);
761
}
762
#endif // ifdef HAL_ICACHE_LOCK
763
 
764
// -------------------------------------------------------------------------
765
// Test of data cache locking.
766
//  o Time difference between repeatedly accessing a memory region
767
//    with and without locking.
768
#ifdef HAL_DCACHE_LOCK
769
static void dloop(void)
770
{
771
    register cyg_uint32 j;
772
    register char c;
773
    register CYG_INTERRUPT_STATE oldints;
774
 
775
    HAL_DISABLE_INTERRUPTS(oldints);
776
    HAL_DCACHE_SYNC();
777
    HAL_DCACHE_DISABLE();
778
    HAL_DCACHE_SYNC();
779
    HAL_DCACHE_INVALIDATE_ALL();
780
    HAL_DCACHE_ENABLE();
781
    HAL_RESTORE_INTERRUPTS(oldints);
782
    for (j = 0; j < HAL_DCACHE_SETS; j++) {
783
        c = m[HAL_DCACHE_LINE_SIZE*j];
784
    }
785
}
786
 
787
static void time_dlock(void)
788
{
789
    register cyg_ucount32 k;
790
    cyg_tick_count_t count0, count1;
791
    cyg_ucount32 t;
792
    register cyg_ucount32 time_dlock_loops = TIME_DLOCK_LOOPS;
793
 
794
    CYG_TEST_INFO("Data cache lock");
795
 
796
    if (cyg_test_is_simulator)
797
        time_dlock_loops = 10;
798
 
799
    count0 = cyg_current_time();
800
    for (k = 0; k < time_dlock_loops; k++) {
801
        dloop();
802
    }
803
    count1 = cyg_current_time();
804
    t = count1 - count0;
805
    diag_printf("time without lock: %d\n", t);
806
 
807
    HAL_DCACHE_LOCK(&m[0], HAL_DCACHE_SETS*HAL_DCACHE_LINE_SIZE);
808
 
809
    count0 = cyg_current_time();
810
    for (k = 0; k < time_dlock_loops; k++) {
811
        dloop();
812
    }
813
    count1 = cyg_current_time();
814
    t = count1 - count0;
815
    diag_printf("time with lock:    %d\n", t);
816
 
817
    HAL_DCACHE_UNLOCK(&m[0], HAL_DCACHE_SETS*HAL_DCACHE_LINE_SIZE);
818
}
819
#endif // ifdef HAL_DCACHE_LOCK
820
 
821
// -------------------------------------------------------------------------
822
static void entry0( cyg_addrword_t data )
823
{
824
    int numtests = 0;
825
#ifdef HAL_DCACHE_QUERY_WRITE_MODE
826
    int wmode;
827
#endif
828
#ifdef HAL_DCACHE_LOCK
829
    time_dlock(); numtests++;
830
#endif
831
#ifdef HAL_ICACHE_LOCK
832
    time_ilock(); numtests++;
833
#endif
834
#ifdef HAL_DCACHE_LINE_SIZE // So we can find our way around memory
835
    test_dsync(); numtests++;
836
#endif
837
#ifdef HAL_DCACHE_STORE
838
    test_dstore(); numtests++;
839
#endif
840
#ifdef _TEST_DCACHE_OPERATION
841
    test_dcache_operation(); numtests++;
842
#endif
843
#ifdef HAL_DCACHE_READ_HINT
844
    test_dread_hint(); numtests++;
845
#endif
846
#ifdef HAL_DCACHE_WRITE_HINT
847
    test_dwrite_hint(); numtests++;
848
#endif
849
#ifdef HAL_DCACHE_ZERO
850
    test_dzero(); numtests++;
851
#endif
852
 
853
    // The below tests only work on a copy-back cache.
854
#ifdef HAL_DCACHE_QUERY_WRITE_MODE
855
    HAL_DCACHE_QUERY_WRITE_MODE( wmode );
856
 
857
    if ( HAL_DCACHE_WRITEBACK_MODE == wmode ) {
858
        test_ddisable(); numtests++;
859
#ifdef HAL_DCACHE_INVALIDATE
860
        test_dinvalidate_all(); numtests++;
861
#endif
862
#ifdef HAL_DCACHE_FLUSH
863
        test_dflush(); numtests++;
864
#endif
865
#ifdef HAL_DCACHE_INVALIDATE
866
        test_dinvalidate(); numtests++;
867
#endif
868
    }
869
#endif // def HAL_DCACHE_QUERY_WRITE_MODE
870
    if ( numtests ) {
871
        CYG_TEST_PASS_FINISH("End of test");
872
    }
873
    else {
874
        CYG_TEST_NA( "No applicable cache tests" );
875
    }
876
}
877
 
878
// -------------------------------------------------------------------------
879
 
880
void kcache2_main( void )
881
{
882
    CYG_TEST_INIT();
883
 
884
    cyg_thread_create(4, entry0 , (cyg_addrword_t)0, "kcache2",
885
        (void *)stack[0], STACKSIZE, &thread[0], &thread_obj[0]);
886
    cyg_thread_resume(thread[0]);
887
 
888
    cyg_scheduler_start();
889
}
890
 
891
// -------------------------------------------------------------------------
892
 
893
externC void
894
cyg_start( void )
895
{
896
    kcache2_main();
897
}
898
 
899
// -------------------------------------------------------------------------
900
 
901
#else // def CYGFUN_KERNEL_API_C
902
#define N_A_MSG "Kernel C API layer disabled"
903
#endif // def CYGFUN_KERNEL_API_C
904
#else // def CYGVAR_KERNEL_COUNTERS_CLOCK
905
#define N_A_MSG "Kernel real-time clock disabled"
906
#endif // def CYGVAR_KERNEL_COUNTERS_CLOCK
907
 
908
#ifdef N_A_MSG
909
externC void
910
cyg_start( void )
911
{
912
    CYG_TEST_INIT();
913
    CYG_TEST_NA( N_A_MSG );
914
}
915
#endif // N_A_MSG
916
 
917
// -------------------------------------------------------------------------
918
/* EOF kcache2.c */

powered by: WebSVN 2.1.0

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