source: rtems/testsuites/sptests/spcache01/init.c @ 7981a88

4.115
Last change on this file since 7981a88 was 7981a88, checked in by Sebastian Huber <sebastian.huber@…>, on 11/25/14 at 07:39:46

sptest/spcache01: New test cases

  • Property mode set to 100644
File size: 9.3 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 <inttypes.h>
21
22#include <rtems.h>
23#include <rtems/counter.h>
24
25#define TESTS_USE_PRINTF
26#include "tmacros.h"
27
28const char rtems_test_name[] = "SPCACHE 1";
29
30#ifdef __or1k__
31  #define I() __asm__ volatile ("l.nop")
32#else
33  #define I() __asm__ volatile ("nop")
34#endif
35
36#define I8() I(); I(); I(); I(); I(); I(); I(); I()
37
38#define I64() I8(); I8(); I8(); I8(); I8(); I8(); I8(); I8()
39
40#define I512() I64(); I64(); I64(); I64(); I64(); I64(); I64(); I64()
41
42CPU_STRUCTURE_ALIGNMENT static int data[1024];
43
44static void test_data_flush_and_invalidate(void)
45{
46  if (rtems_cache_get_data_line_size() > 0) {
47    rtems_interrupt_lock lock;
48    rtems_interrupt_lock_context lock_context;
49    volatile int *vdata = &data[0];
50    int n = 32;
51    int i;
52    size_t data_size = n * sizeof(data[0]);
53    bool write_through;
54
55    printf("data cache flush and invalidate test\n");
56
57    rtems_interrupt_lock_initialize(&lock, "test");
58    rtems_interrupt_lock_acquire(&lock, &lock_context);
59
60    for (i = 0; i < n; ++i) {
61      vdata[i] = i;
62    }
63
64    rtems_cache_flush_multiple_data_lines(&data[0], data_size);
65
66    for (i = 0; i < n; ++i) {
67      rtems_test_assert(vdata[i] == i);
68    }
69
70    for (i = 0; i < n; ++i) {
71      vdata[i] = ~i;
72    }
73
74    rtems_cache_invalidate_multiple_data_lines(&data[0], data_size);
75
76    write_through = vdata[0] == ~0;
77    if (write_through) {
78      for (i = 0; i < n; ++i) {
79        rtems_test_assert(vdata[i] == ~i);
80      }
81    } else {
82      for (i = 0; i < n; ++i) {
83        rtems_test_assert(vdata[i] == i);
84      }
85    }
86
87    for (i = 0; i < n; ++i) {
88      vdata[i] = ~i;
89    }
90
91    rtems_cache_flush_multiple_data_lines(&data[0], data_size);
92    rtems_cache_invalidate_multiple_data_lines(&data[0], data_size);
93
94    for (i = 0; i < n; ++i) {
95      rtems_test_assert(vdata[i] == ~i);
96    }
97
98    rtems_interrupt_lock_release(&lock, &lock_context);
99    rtems_interrupt_lock_destroy(&lock);
100
101    printf(
102      "data cache operations by line passed the test (%s cache detected)\n",
103      write_through ? "write-through" : "copy-back"
104    );
105  } else {
106    printf(
107      "skip data cache flush and invalidate test"
108        " due to cache line size of zero\n"
109    );
110  }
111
112  /* Make sure these are nops */
113  rtems_cache_flush_multiple_data_lines(NULL, 0);
114  rtems_cache_invalidate_multiple_data_lines(NULL, 0);
115}
116
117static uint64_t do_some_work(void)
118{
119  rtems_counter_ticks a;
120  rtems_counter_ticks b;
121  rtems_counter_ticks d;
122
123  /* This gives 1024 nop instructions */
124  a = rtems_counter_read();
125  I512();
126  I512();
127  b = rtems_counter_read();
128
129  d = rtems_counter_difference(b, a);
130
131  return rtems_counter_ticks_to_nanoseconds(d);
132}
133
134static uint64_t load(void)
135{
136  rtems_counter_ticks a;
137  rtems_counter_ticks b;
138  rtems_counter_ticks d;
139  size_t i;
140  volatile int *vdata = &data[0];
141
142  a = rtems_counter_read();
143  for (i = 0; i < RTEMS_ARRAY_SIZE(data); ++i) {
144    vdata[i];
145  }
146  b = rtems_counter_read();
147
148  d = rtems_counter_difference(b, a);
149
150  return rtems_counter_ticks_to_nanoseconds(d);
151}
152
153static uint64_t store(void)
154{
155  rtems_counter_ticks a;
156  rtems_counter_ticks b;
157  rtems_counter_ticks d;
158  size_t i;
159  volatile int *vdata = &data[0];
160
161  a = rtems_counter_read();
162  for (i = 0; i < RTEMS_ARRAY_SIZE(data); ++i) {
163    vdata[i] = 0;
164  }
165  b = rtems_counter_read();
166
167  d = rtems_counter_difference(b, a);
168
169  return rtems_counter_ticks_to_nanoseconds(d);
170}
171
172static void test_timing(void)
173{
174  rtems_interrupt_lock lock;
175  rtems_interrupt_lock_context lock_context;
176  size_t data_size = sizeof(data);
177  uint64_t d[3];
178  uint32_t cache_level;
179  size_t cache_size;
180
181  rtems_interrupt_lock_initialize(&lock, "test");
182
183  printf(
184    "data cache line size %zi bytes\n"
185    "data cache size %zi bytes\n",
186    rtems_cache_get_data_line_size(),
187    rtems_cache_get_data_cache_size(0)
188  );
189
190  cache_level = 1;
191  cache_size = rtems_cache_get_data_cache_size(cache_level);
192  while (cache_size > 0) {
193    printf(
194      "data cache level %" PRIu32 " size %zi bytes\n",
195      cache_level,
196      cache_size
197    );
198    ++cache_level;
199    cache_size = rtems_cache_get_data_cache_size(cache_level);
200  }
201
202  rtems_interrupt_lock_acquire(&lock, &lock_context);
203
204  d[0] = load();
205  d[1] = load();
206  rtems_cache_flush_entire_data();
207  d[2] = load();
208
209  rtems_interrupt_lock_release(&lock, &lock_context);
210
211  printf(
212    "load %zi bytes with flush entire data\n"
213    "  duration with normal cache %" PRIu64 " ns\n"
214    "  duration with warm cache %" PRIu64 " ns\n"
215    "  duration with flushed cache %" PRIu64 " ns\n",
216    data_size,
217    d[0],
218    d[1],
219    d[2]
220  );
221
222  rtems_interrupt_lock_acquire(&lock, &lock_context);
223
224  d[0] = load();
225  d[1] = load();
226  rtems_cache_flush_multiple_data_lines(&data[0], sizeof(data));
227  d[2] = load();
228
229  rtems_interrupt_lock_release(&lock, &lock_context);
230
231  printf(
232    "load %zi bytes with flush multiple data\n"
233    "  duration with normal cache %" PRIu64 " ns\n"
234    "  duration with warm cache %" PRIu64 " ns\n"
235    "  duration with flushed cache %" PRIu64 " ns\n",
236    data_size,
237    d[0],
238    d[1],
239    d[2]
240  );
241
242  rtems_interrupt_lock_acquire(&lock, &lock_context);
243
244  d[0] = load();
245  d[1] = load();
246  rtems_cache_invalidate_multiple_data_lines(&data[0], sizeof(data));
247  d[2] = load();
248
249  rtems_interrupt_lock_release(&lock, &lock_context);
250
251  printf(
252    "load %zi bytes with invalidate multiple data\n"
253    "  duration with normal cache %" PRIu64 " ns\n"
254    "  duration with warm cache %" PRIu64 " ns\n"
255    "  duration with invalidated cache %" PRIu64 " ns\n",
256    data_size,
257    d[0],
258    d[1],
259    d[2]
260  );
261
262  rtems_interrupt_lock_acquire(&lock, &lock_context);
263
264  d[0] = store();
265  d[1] = store();
266  rtems_cache_flush_entire_data();
267  d[2] = store();
268
269  rtems_interrupt_lock_release(&lock, &lock_context);
270
271  printf(
272    "store %zi bytes with flush entire data\n"
273    "  duration with normal cache %" PRIu64 " ns\n"
274    "  duration with warm cache %" PRIu64 " ns\n"
275    "  duration with flushed cache %" PRIu64 " ns\n",
276    data_size,
277    d[0],
278    d[1],
279    d[2]
280  );
281
282  rtems_interrupt_lock_acquire(&lock, &lock_context);
283
284  d[0] = store();
285  d[1] = store();
286  rtems_cache_flush_multiple_data_lines(&data[0], sizeof(data));
287  d[2] = store();
288
289  rtems_interrupt_lock_release(&lock, &lock_context);
290
291  printf(
292    "store %zi bytes with flush multiple data\n"
293    "  duration with normal cache %" PRIu64 " ns\n"
294    "  duration with warm cache %" PRIu64 " ns\n"
295    "  duration with flushed cache %" PRIu64 " ns\n",
296    data_size,
297    d[0],
298    d[1],
299    d[2]
300  );
301
302  rtems_interrupt_lock_acquire(&lock, &lock_context);
303
304  d[0] = store();
305  d[1] = store();
306  rtems_cache_invalidate_multiple_data_lines(&data[0], sizeof(data));
307  d[2] = store();
308
309  rtems_interrupt_lock_release(&lock, &lock_context);
310
311  printf(
312    "store %zi bytes with invalidate multiple data\n"
313    "  duration with normal cache %" PRIu64 " ns\n"
314    "  duration with warm cache %" PRIu64 " ns\n"
315    "  duration with invalidated cache %" PRIu64 " ns\n",
316    data_size,
317    d[0],
318    d[1],
319    d[2]
320  );
321
322  printf(
323    "instruction cache line size %zi bytes\n"
324    "instruction cache size %zi bytes\n",
325    rtems_cache_get_instruction_line_size(),
326    rtems_cache_get_instruction_cache_size(0)
327  );
328
329  cache_level = 1;
330  cache_size = rtems_cache_get_instruction_cache_size(cache_level);
331  while (cache_size > 0) {
332    printf(
333      "instruction cache level %" PRIu32 " size %zi bytes\n",
334      cache_level,
335      cache_size
336    );
337    ++cache_level;
338    cache_size = rtems_cache_get_instruction_cache_size(cache_level);
339  }
340
341  rtems_interrupt_lock_acquire(&lock, &lock_context);
342
343  d[0] = do_some_work();
344  d[1] = do_some_work();
345  rtems_cache_invalidate_entire_instruction();
346  d[2] = do_some_work();
347
348  rtems_interrupt_lock_release(&lock, &lock_context);
349
350  printf(
351    "invalidate entire instruction\n"
352    "  duration with normal cache %" PRIu64 " ns\n"
353    "  duration with warm cache %" PRIu64 " ns\n"
354    "  duration with invalidated cache %" PRIu64 " ns\n",
355    d[0],
356    d[1],
357    d[2]
358  );
359
360  rtems_interrupt_lock_acquire(&lock, &lock_context);
361
362  d[0] = do_some_work();
363  d[1] = do_some_work();
364  rtems_cache_invalidate_multiple_instruction_lines(do_some_work, 4096);
365  d[2] = do_some_work();
366
367  rtems_interrupt_lock_release(&lock, &lock_context);
368
369  printf(
370    "invalidate multiple instruction\n"
371    "  duration with normal cache %" PRIu64 " ns\n"
372    "  duration with warm cache %" PRIu64 " ns\n"
373    "  duration with invalidated cache %" PRIu64 " ns\n",
374    d[0],
375    d[1],
376    d[2]
377  );
378
379  rtems_interrupt_lock_destroy(&lock);
380}
381
382static void Init(rtems_task_argument arg)
383{
384  TEST_BEGIN();
385
386  test_data_flush_and_invalidate();
387  test_timing();
388
389  TEST_END();
390
391  rtems_test_exit(0);
392}
393
394#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
395#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
396
397#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
398
399#define CONFIGURE_MAXIMUM_TASKS 1
400
401#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
402
403#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
404
405#define CONFIGURE_INIT
406
407#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.