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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [kernel/] [v2_0/] [tests/] [kcache2.c] - Blame information for rev 27

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

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

powered by: WebSVN 2.1.0

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