source: rtems/testsuites/sptests/spcache01/init.c @ e7549ff4

4.115
Last change on this file since e7549ff4 was e7549ff4, checked in by Sebastian Huber <sebastian.huber@…>, on 02/26/14 at 10:00:17

rtems: Use size_t for cache line size

A cache line cannot have a negative size.

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