source: rtems/testsuites/sptests/spcache01/init.c @ 6c0301d

4.115
Last change on this file since 6c0301d was 6c0301d, checked in by Sebastian Huber <sebastian.huber@…>, on 03/25/14 at 07:06:21

tests/sptests: Use <rtems/test.h>

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