source: rtems/testsuites/sptests/spcache01/init.c @ 48cfe68

4.115
Last change on this file since 48cfe68 was a0b1b5ed, checked in by Sebastian Huber <sebastian.huber@…>, on 12/15/14 at 13:19:43

Delete CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM

This define was superfluous, undocumented and used inconsistently.

  • Property mode set to 100644
File size: 10.9 KB
Line 
1/*
2 * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#ifdef HAVE_CONFIG_H
16  #include "config.h"
17#endif
18
19#include <stdio.h>
20#include <stdlib.h>
21#include <inttypes.h>
22
23#include <rtems.h>
24#include <rtems/counter.h>
25#include <rtems/score/sysstate.h>
26
27#define TESTS_USE_PRINTF
28#include "tmacros.h"
29
30const char rtems_test_name[] = "SPCACHE 1";
31
32#ifdef __or1k__
33  #define I() __asm__ volatile ("l.nop")
34#else
35  #define I() __asm__ volatile ("nop")
36#endif
37
38#define I8() I(); I(); I(); I(); I(); I(); I(); I()
39
40#define I64() I8(); I8(); I8(); I8(); I8(); I8(); I8(); I8()
41
42#define I512() I64(); I64(); I64(); I64(); I64(); I64(); I64(); I64()
43
44CPU_STRUCTURE_ALIGNMENT static int data[1024];
45
46static void test_data_flush_and_invalidate(void)
47{
48  if (rtems_cache_get_data_line_size() > 0) {
49    rtems_interrupt_lock lock;
50    rtems_interrupt_lock_context lock_context;
51    volatile int *vdata = &data[0];
52    int n = 32;
53    int i;
54    size_t data_size = n * sizeof(data[0]);
55    bool write_through;
56
57    printf("data cache flush and invalidate test\n");
58
59    rtems_interrupt_lock_initialize(&lock, "test");
60    rtems_interrupt_lock_acquire(&lock, &lock_context);
61
62    for (i = 0; i < n; ++i) {
63      vdata[i] = i;
64    }
65
66    rtems_cache_flush_multiple_data_lines(&data[0], data_size);
67
68    for (i = 0; i < n; ++i) {
69      rtems_test_assert(vdata[i] == i);
70    }
71
72    for (i = 0; i < n; ++i) {
73      vdata[i] = ~i;
74    }
75
76    rtems_cache_invalidate_multiple_data_lines(&data[0], data_size);
77
78    write_through = vdata[0] == ~0;
79    if (write_through) {
80      for (i = 0; i < n; ++i) {
81        rtems_test_assert(vdata[i] == ~i);
82      }
83    } else {
84      for (i = 0; i < n; ++i) {
85        rtems_test_assert(vdata[i] == i);
86      }
87    }
88
89    for (i = 0; i < n; ++i) {
90      vdata[i] = ~i;
91    }
92
93    rtems_cache_flush_multiple_data_lines(&data[0], data_size);
94    rtems_cache_invalidate_multiple_data_lines(&data[0], data_size);
95
96    for (i = 0; i < n; ++i) {
97      rtems_test_assert(vdata[i] == ~i);
98    }
99
100    rtems_interrupt_lock_release(&lock, &lock_context);
101    rtems_interrupt_lock_destroy(&lock);
102
103    printf(
104      "data cache operations by line passed the test (%s cache detected)\n",
105      write_through ? "write-through" : "copy-back"
106    );
107  } else {
108    printf(
109      "skip data cache flush and invalidate test"
110        " due to cache line size of zero\n"
111    );
112  }
113
114  /* Make sure these are nops */
115  rtems_cache_flush_multiple_data_lines(NULL, 0);
116  rtems_cache_invalidate_multiple_data_lines(NULL, 0);
117}
118
119static uint64_t do_some_work(void)
120{
121  rtems_counter_ticks a;
122  rtems_counter_ticks b;
123  rtems_counter_ticks d;
124
125  /* This gives 1024 nop instructions */
126  a = rtems_counter_read();
127  I512();
128  I512();
129  b = rtems_counter_read();
130
131  d = rtems_counter_difference(b, a);
132
133  return rtems_counter_ticks_to_nanoseconds(d);
134}
135
136static uint64_t load(void)
137{
138  rtems_counter_ticks a;
139  rtems_counter_ticks b;
140  rtems_counter_ticks d;
141  size_t i;
142  volatile int *vdata = &data[0];
143
144  a = rtems_counter_read();
145  for (i = 0; i < RTEMS_ARRAY_SIZE(data); ++i) {
146    vdata[i];
147  }
148  b = rtems_counter_read();
149
150  d = rtems_counter_difference(b, a);
151
152  return rtems_counter_ticks_to_nanoseconds(d);
153}
154
155static uint64_t store(void)
156{
157  rtems_counter_ticks a;
158  rtems_counter_ticks b;
159  rtems_counter_ticks d;
160  size_t i;
161  volatile int *vdata = &data[0];
162
163  a = rtems_counter_read();
164  for (i = 0; i < RTEMS_ARRAY_SIZE(data); ++i) {
165    vdata[i] = 0;
166  }
167  b = rtems_counter_read();
168
169  d = rtems_counter_difference(b, a);
170
171  return rtems_counter_ticks_to_nanoseconds(d);
172}
173
174static void test_timing(void)
175{
176  rtems_interrupt_lock lock;
177  rtems_interrupt_lock_context lock_context;
178  size_t data_size = sizeof(data);
179  uint64_t d[3];
180  uint32_t cache_level;
181  size_t cache_size;
182
183  rtems_interrupt_lock_initialize(&lock, "test");
184
185  printf(
186    "data cache line size %zi bytes\n"
187    "data cache size %zi bytes\n",
188    rtems_cache_get_data_line_size(),
189    rtems_cache_get_data_cache_size(0)
190  );
191
192  cache_level = 1;
193  cache_size = rtems_cache_get_data_cache_size(cache_level);
194  while (cache_size > 0) {
195    printf(
196      "data cache level %" PRIu32 " size %zi bytes\n",
197      cache_level,
198      cache_size
199    );
200    ++cache_level;
201    cache_size = rtems_cache_get_data_cache_size(cache_level);
202  }
203
204  rtems_interrupt_lock_acquire(&lock, &lock_context);
205
206  d[0] = load();
207  d[1] = load();
208  rtems_cache_flush_entire_data();
209  d[2] = load();
210
211  rtems_interrupt_lock_release(&lock, &lock_context);
212
213  printf(
214    "load %zi bytes with flush entire data\n"
215    "  duration with normal cache %" PRIu64 " ns\n"
216    "  duration with warm cache %" PRIu64 " ns\n"
217    "  duration with flushed cache %" PRIu64 " ns\n",
218    data_size,
219    d[0],
220    d[1],
221    d[2]
222  );
223
224  rtems_interrupt_lock_acquire(&lock, &lock_context);
225
226  d[0] = load();
227  d[1] = load();
228  rtems_cache_flush_multiple_data_lines(&data[0], sizeof(data));
229  d[2] = load();
230
231  rtems_interrupt_lock_release(&lock, &lock_context);
232
233  printf(
234    "load %zi bytes with flush multiple data\n"
235    "  duration with normal cache %" PRIu64 " ns\n"
236    "  duration with warm cache %" PRIu64 " ns\n"
237    "  duration with flushed cache %" PRIu64 " ns\n",
238    data_size,
239    d[0],
240    d[1],
241    d[2]
242  );
243
244  rtems_interrupt_lock_acquire(&lock, &lock_context);
245
246  d[0] = load();
247  d[1] = load();
248  rtems_cache_invalidate_multiple_data_lines(&data[0], sizeof(data));
249  d[2] = load();
250
251  rtems_interrupt_lock_release(&lock, &lock_context);
252
253  printf(
254    "load %zi bytes with invalidate multiple data\n"
255    "  duration with normal cache %" PRIu64 " ns\n"
256    "  duration with warm cache %" PRIu64 " ns\n"
257    "  duration with invalidated cache %" PRIu64 " ns\n",
258    data_size,
259    d[0],
260    d[1],
261    d[2]
262  );
263
264  rtems_interrupt_lock_acquire(&lock, &lock_context);
265
266  d[0] = store();
267  d[1] = store();
268  rtems_cache_flush_entire_data();
269  d[2] = store();
270
271  rtems_interrupt_lock_release(&lock, &lock_context);
272
273  printf(
274    "store %zi bytes with flush entire data\n"
275    "  duration with normal cache %" PRIu64 " ns\n"
276    "  duration with warm cache %" PRIu64 " ns\n"
277    "  duration with flushed cache %" PRIu64 " ns\n",
278    data_size,
279    d[0],
280    d[1],
281    d[2]
282  );
283
284  rtems_interrupt_lock_acquire(&lock, &lock_context);
285
286  d[0] = store();
287  d[1] = store();
288  rtems_cache_flush_multiple_data_lines(&data[0], sizeof(data));
289  d[2] = store();
290
291  rtems_interrupt_lock_release(&lock, &lock_context);
292
293  printf(
294    "store %zi bytes with flush multiple data\n"
295    "  duration with normal cache %" PRIu64 " ns\n"
296    "  duration with warm cache %" PRIu64 " ns\n"
297    "  duration with flushed cache %" PRIu64 " ns\n",
298    data_size,
299    d[0],
300    d[1],
301    d[2]
302  );
303
304  rtems_interrupt_lock_acquire(&lock, &lock_context);
305
306  d[0] = store();
307  d[1] = store();
308  rtems_cache_invalidate_multiple_data_lines(&data[0], sizeof(data));
309  d[2] = store();
310
311  rtems_interrupt_lock_release(&lock, &lock_context);
312
313  printf(
314    "store %zi bytes with invalidate multiple data\n"
315    "  duration with normal cache %" PRIu64 " ns\n"
316    "  duration with warm cache %" PRIu64 " ns\n"
317    "  duration with invalidated cache %" PRIu64 " ns\n",
318    data_size,
319    d[0],
320    d[1],
321    d[2]
322  );
323
324  printf(
325    "instruction cache line size %zi bytes\n"
326    "instruction cache size %zi bytes\n",
327    rtems_cache_get_instruction_line_size(),
328    rtems_cache_get_instruction_cache_size(0)
329  );
330
331  cache_level = 1;
332  cache_size = rtems_cache_get_instruction_cache_size(cache_level);
333  while (cache_size > 0) {
334    printf(
335      "instruction cache level %" PRIu32 " size %zi bytes\n",
336      cache_level,
337      cache_size
338    );
339    ++cache_level;
340    cache_size = rtems_cache_get_instruction_cache_size(cache_level);
341  }
342
343  rtems_interrupt_lock_acquire(&lock, &lock_context);
344
345  d[0] = do_some_work();
346  d[1] = do_some_work();
347  rtems_cache_invalidate_entire_instruction();
348  d[2] = do_some_work();
349
350  rtems_interrupt_lock_release(&lock, &lock_context);
351
352  printf(
353    "invalidate entire instruction\n"
354    "  duration with normal cache %" PRIu64 " ns\n"
355    "  duration with warm cache %" PRIu64 " ns\n"
356    "  duration with invalidated cache %" PRIu64 " ns\n",
357    d[0],
358    d[1],
359    d[2]
360  );
361
362  rtems_interrupt_lock_acquire(&lock, &lock_context);
363
364  d[0] = do_some_work();
365  d[1] = do_some_work();
366  rtems_cache_invalidate_multiple_instruction_lines(do_some_work, 4096);
367  d[2] = do_some_work();
368
369  rtems_interrupt_lock_release(&lock, &lock_context);
370
371  printf(
372    "invalidate multiple instruction\n"
373    "  duration with normal cache %" PRIu64 " ns\n"
374    "  duration with warm cache %" PRIu64 " ns\n"
375    "  duration with invalidated cache %" PRIu64 " ns\n",
376    d[0],
377    d[1],
378    d[2]
379  );
380
381  rtems_interrupt_lock_destroy(&lock);
382}
383
384static void test_cache_aligned_alloc(void)
385{
386  void *p0;
387  void *p1;
388  size_t cls;
389
390  printf("test rtems_cache_aligned_malloc()\n");
391
392  p0 = rtems_cache_aligned_malloc(1);
393  p1 = rtems_cache_aligned_malloc(1);
394
395  rtems_test_assert(p0 != NULL);
396  rtems_test_assert(p1 != NULL);
397
398  cls = rtems_cache_get_data_line_size();
399  if (cls > 0) {
400    size_t m = cls - 1;
401    uintptr_t a0 = (uintptr_t) p0;
402    uintptr_t a1 = (uintptr_t) p1;
403
404    rtems_test_assert(a1 - a0 > cls);
405    rtems_test_assert((a0 & m) == 0);
406    rtems_test_assert((a1 & m) == 0);
407  }
408
409  free(p0);
410  free(p1);
411}
412
413#define AREA_SIZE 256
414
415static char cache_coherent_area_0[AREA_SIZE];
416
417static char cache_coherent_area_1[AREA_SIZE];
418
419static char cache_coherent_area_2[AREA_SIZE];
420
421static void add_area(void *begin)
422{
423  rtems_cache_coherent_add_area(NULL, 0);
424  rtems_cache_coherent_add_area(begin, AREA_SIZE);
425}
426
427static void test_cache_coherent_alloc(void)
428{
429  void *p0;
430  void *p1;
431  System_state_Codes previous_state;
432
433  printf("test cache coherent allocation\n");
434
435  p0 = rtems_cache_coherent_allocate(1, 0, 0);
436  rtems_test_assert(p0 != NULL);
437
438  rtems_cache_coherent_free(p0);
439
440  p0 = rtems_cache_coherent_allocate(1, 0, 0);
441  rtems_test_assert(p0 != NULL);
442
443  add_area(&cache_coherent_area_0[0]);
444  add_area(&cache_coherent_area_1[0]);
445
446  previous_state = _System_state_Get();
447  _System_state_Set(previous_state + 1);
448  add_area(&cache_coherent_area_2[0]);
449  _System_state_Set(previous_state);
450
451  p1 = rtems_cache_coherent_allocate(1, 0, 0);
452  rtems_test_assert(p1 != NULL);
453
454  rtems_cache_coherent_free(p0);
455  rtems_cache_coherent_free(p1);
456}
457
458static void Init(rtems_task_argument arg)
459{
460  TEST_BEGIN();
461
462  test_data_flush_and_invalidate();
463  test_timing();
464  test_cache_aligned_alloc();
465  test_cache_coherent_alloc();
466
467  TEST_END();
468
469  rtems_test_exit(0);
470}
471
472#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
473#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
474
475#define CONFIGURE_MAXIMUM_TASKS 1
476
477#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
478
479#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
480
481#define CONFIGURE_INIT
482
483#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.