source: rtems/testsuites/sptests/spcache01/init.c @ 698c2e50

4.115
Last change on this file since 698c2e50 was c499856, checked in by Chris Johns <chrisj@…>, on 03/20/14 at 21:10:47

Change all references of rtems.com to rtems.org.

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