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
RevLine 
[3378be95]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
[c499856]12 * http://www.rtems.org/license/LICENSE.
[3378be95]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
[6c0301d]28const char rtems_test_name[] = "SPCACHE 1";
29
[3378be95]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) {
[d50acdbb]43    rtems_interrupt_lock lock;
44    rtems_interrupt_lock_context lock_context;
[3378be95]45    volatile int *vdata = &data[0];
46    int n = 32;
47    int i;
48    size_t data_size = n * sizeof(data[0]);
[31494ab2]49    bool write_through;
[3378be95]50
51    printf("data cache flush and invalidate test\n");
52
[53ad908]53    rtems_interrupt_lock_initialize(&lock, "test");
[d50acdbb]54    rtems_interrupt_lock_acquire(&lock, &lock_context);
[3378be95]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
[31494ab2]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      }
[3378be95]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
[d50acdbb]94    rtems_interrupt_lock_release(&lock, &lock_context);
[28779c7]95    rtems_interrupt_lock_destroy(&lock);
[3378be95]96
[31494ab2]97    printf(
98      "data cache operations by line passed the test (%s cache detected)\n",
99      write_through ? "write-through" : "copy-back"
100    );
[3378be95]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{
[d50acdbb]166  rtems_interrupt_lock lock;
167  rtems_interrupt_lock_context lock_context;
[3378be95]168  size_t data_size = sizeof(data);
169  uint64_t d[3];
[e1d7bf0]170  uint32_t cache_level;
171  size_t cache_size;
[3378be95]172
[53ad908]173  rtems_interrupt_lock_initialize(&lock, "test");
[d50acdbb]174
[3378be95]175  printf(
[e1d7bf0]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)
[3378be95]180  );
181
[e1d7bf0]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
[d50acdbb]194  rtems_interrupt_lock_acquire(&lock, &lock_context);
[3378be95]195
196  d[0] = load();
197  d[1] = load();
198  rtems_cache_flush_entire_data();
199  d[2] = load();
200
[d50acdbb]201  rtems_interrupt_lock_release(&lock, &lock_context);
[3378be95]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
[d50acdbb]214  rtems_interrupt_lock_acquire(&lock, &lock_context);
[3378be95]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
[d50acdbb]221  rtems_interrupt_lock_release(&lock, &lock_context);
[3378be95]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
[d50acdbb]234  rtems_interrupt_lock_acquire(&lock, &lock_context);
[3378be95]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
[d50acdbb]241  rtems_interrupt_lock_release(&lock, &lock_context);
[3378be95]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
[d50acdbb]254  rtems_interrupt_lock_acquire(&lock, &lock_context);
[3378be95]255
256  d[0] = store();
257  d[1] = store();
258  rtems_cache_flush_entire_data();
259  d[2] = store();
260
[d50acdbb]261  rtems_interrupt_lock_release(&lock, &lock_context);
[3378be95]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
[d50acdbb]274  rtems_interrupt_lock_acquire(&lock, &lock_context);
[3378be95]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
[d50acdbb]281  rtems_interrupt_lock_release(&lock, &lock_context);
[3378be95]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
[d50acdbb]294  rtems_interrupt_lock_acquire(&lock, &lock_context);
[3378be95]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
[d50acdbb]301  rtems_interrupt_lock_release(&lock, &lock_context);
[3378be95]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(
[e1d7bf0]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)
[3378be95]319  );
320
[e1d7bf0]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
[d50acdbb]333  rtems_interrupt_lock_acquire(&lock, &lock_context);
[3378be95]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
[d50acdbb]340  rtems_interrupt_lock_release(&lock, &lock_context);
[3378be95]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
[d50acdbb]352  rtems_interrupt_lock_acquire(&lock, &lock_context);
[3378be95]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
[d50acdbb]359  rtems_interrupt_lock_release(&lock, &lock_context);
[3378be95]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  );
[28779c7]370
371  rtems_interrupt_lock_destroy(&lock);
[3378be95]372}
373
374static void Init(rtems_task_argument arg)
375{
[6c0301d]376  TEST_BEGIN();
[3378be95]377
378  test_data_flush_and_invalidate();
379  test_timing();
380
[6c0301d]381  TEST_END();
[3378be95]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
[6c0301d]393#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
394
[3378be95]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.