source: rtems/testsuites/sptests/spcache01/init.c @ 23b14f87

4.115
Last change on this file since 23b14f87 was 23b14f87, checked in by Hesham ALMatary <heshamelmatary@…>, on Aug 22, 2014 at 8:20:16 PM

sptests/spcache01: Make inline assembly conditional to account for OpenRISC l.nop instruction.

  • 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#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
113static uint64_t do_some_work(void)
114{
115  rtems_counter_ticks a;
116  rtems_counter_ticks b;
117  rtems_counter_ticks d;
118
119  /* This gives 1024 nop instructions */
120  a = rtems_counter_read();
121  I512();
122  I512();
123  b = rtems_counter_read();
124
125  d = rtems_counter_difference(b, a);
126
127  return rtems_counter_ticks_to_nanoseconds(d);
128}
129
130static uint64_t load(void)
131{
132  rtems_counter_ticks a;
133  rtems_counter_ticks b;
134  rtems_counter_ticks d;
135  size_t i;
136  volatile int *vdata = &data[0];
137
138  a = rtems_counter_read();
139  for (i = 0; i < RTEMS_ARRAY_SIZE(data); ++i) {
140    vdata[i];
141  }
142  b = rtems_counter_read();
143
144  d = rtems_counter_difference(b, a);
145
146  return rtems_counter_ticks_to_nanoseconds(d);
147}
148
149static uint64_t store(void)
150{
151  rtems_counter_ticks a;
152  rtems_counter_ticks b;
153  rtems_counter_ticks d;
154  size_t i;
155  volatile int *vdata = &data[0];
156
157  a = rtems_counter_read();
158  for (i = 0; i < RTEMS_ARRAY_SIZE(data); ++i) {
159    vdata[i] = 0;
160  }
161  b = rtems_counter_read();
162
163  d = rtems_counter_difference(b, a);
164
165  return rtems_counter_ticks_to_nanoseconds(d);
166}
167
168static void test_timing(void)
169{
170  rtems_interrupt_lock lock;
171  rtems_interrupt_lock_context lock_context;
172  size_t data_size = sizeof(data);
173  uint64_t d[3];
174  uint32_t cache_level;
175  size_t cache_size;
176
177  rtems_interrupt_lock_initialize(&lock, "test");
178
179  printf(
180    "data cache line size %zi bytes\n"
181    "data cache size %zi bytes\n",
182    rtems_cache_get_data_line_size(),
183    rtems_cache_get_data_cache_size(0)
184  );
185
186  cache_level = 1;
187  cache_size = rtems_cache_get_data_cache_size(cache_level);
188  while (cache_size > 0) {
189    printf(
190      "data cache level %" PRIu32 " size %zi bytes\n",
191      cache_level,
192      cache_size
193    );
194    ++cache_level;
195    cache_size = rtems_cache_get_data_cache_size(cache_level);
196  }
197
198  rtems_interrupt_lock_acquire(&lock, &lock_context);
199
200  d[0] = load();
201  d[1] = load();
202  rtems_cache_flush_entire_data();
203  d[2] = load();
204
205  rtems_interrupt_lock_release(&lock, &lock_context);
206
207  printf(
208    "load %zi bytes with flush entire data\n"
209    "  duration with normal cache %" PRIu64 " ns\n"
210    "  duration with warm cache %" PRIu64 " ns\n"
211    "  duration with flushed cache %" PRIu64 " ns\n",
212    data_size,
213    d[0],
214    d[1],
215    d[2]
216  );
217
218  rtems_interrupt_lock_acquire(&lock, &lock_context);
219
220  d[0] = load();
221  d[1] = load();
222  rtems_cache_flush_multiple_data_lines(&data[0], sizeof(data));
223  d[2] = load();
224
225  rtems_interrupt_lock_release(&lock, &lock_context);
226
227  printf(
228    "load %zi bytes with flush multiple data\n"
229    "  duration with normal cache %" PRIu64 " ns\n"
230    "  duration with warm cache %" PRIu64 " ns\n"
231    "  duration with flushed cache %" PRIu64 " ns\n",
232    data_size,
233    d[0],
234    d[1],
235    d[2]
236  );
237
238  rtems_interrupt_lock_acquire(&lock, &lock_context);
239
240  d[0] = load();
241  d[1] = load();
242  rtems_cache_invalidate_multiple_data_lines(&data[0], sizeof(data));
243  d[2] = load();
244
245  rtems_interrupt_lock_release(&lock, &lock_context);
246
247  printf(
248    "load %zi bytes with invalidate multiple data\n"
249    "  duration with normal cache %" PRIu64 " ns\n"
250    "  duration with warm cache %" PRIu64 " ns\n"
251    "  duration with invalidated cache %" PRIu64 " ns\n",
252    data_size,
253    d[0],
254    d[1],
255    d[2]
256  );
257
258  rtems_interrupt_lock_acquire(&lock, &lock_context);
259
260  d[0] = store();
261  d[1] = store();
262  rtems_cache_flush_entire_data();
263  d[2] = store();
264
265  rtems_interrupt_lock_release(&lock, &lock_context);
266
267  printf(
268    "store %zi bytes with flush entire data\n"
269    "  duration with normal cache %" PRIu64 " ns\n"
270    "  duration with warm cache %" PRIu64 " ns\n"
271    "  duration with flushed cache %" PRIu64 " ns\n",
272    data_size,
273    d[0],
274    d[1],
275    d[2]
276  );
277
278  rtems_interrupt_lock_acquire(&lock, &lock_context);
279
280  d[0] = store();
281  d[1] = store();
282  rtems_cache_flush_multiple_data_lines(&data[0], sizeof(data));
283  d[2] = store();
284
285  rtems_interrupt_lock_release(&lock, &lock_context);
286
287  printf(
288    "store %zi bytes with flush multiple data\n"
289    "  duration with normal cache %" PRIu64 " ns\n"
290    "  duration with warm cache %" PRIu64 " ns\n"
291    "  duration with flushed cache %" PRIu64 " ns\n",
292    data_size,
293    d[0],
294    d[1],
295    d[2]
296  );
297
298  rtems_interrupt_lock_acquire(&lock, &lock_context);
299
300  d[0] = store();
301  d[1] = store();
302  rtems_cache_invalidate_multiple_data_lines(&data[0], sizeof(data));
303  d[2] = store();
304
305  rtems_interrupt_lock_release(&lock, &lock_context);
306
307  printf(
308    "store %zi bytes with invalidate multiple data\n"
309    "  duration with normal cache %" PRIu64 " ns\n"
310    "  duration with warm cache %" PRIu64 " ns\n"
311    "  duration with invalidated cache %" PRIu64 " ns\n",
312    data_size,
313    d[0],
314    d[1],
315    d[2]
316  );
317
318  printf(
319    "instruction cache line size %zi bytes\n"
320    "instruction cache size %zi bytes\n",
321    rtems_cache_get_instruction_line_size(),
322    rtems_cache_get_instruction_cache_size(0)
323  );
324
325  cache_level = 1;
326  cache_size = rtems_cache_get_instruction_cache_size(cache_level);
327  while (cache_size > 0) {
328    printf(
329      "instruction cache level %" PRIu32 " size %zi bytes\n",
330      cache_level,
331      cache_size
332    );
333    ++cache_level;
334    cache_size = rtems_cache_get_instruction_cache_size(cache_level);
335  }
336
337  rtems_interrupt_lock_acquire(&lock, &lock_context);
338
339  d[0] = do_some_work();
340  d[1] = do_some_work();
341  rtems_cache_invalidate_entire_instruction();
342  d[2] = do_some_work();
343
344  rtems_interrupt_lock_release(&lock, &lock_context);
345
346  printf(
347    "invalidate entire instruction\n"
348    "  duration with normal cache %" PRIu64 " ns\n"
349    "  duration with warm cache %" PRIu64 " ns\n"
350    "  duration with invalidated cache %" PRIu64 " ns\n",
351    d[0],
352    d[1],
353    d[2]
354  );
355
356  rtems_interrupt_lock_acquire(&lock, &lock_context);
357
358  d[0] = do_some_work();
359  d[1] = do_some_work();
360  rtems_cache_invalidate_multiple_instruction_lines(do_some_work, 4096);
361  d[2] = do_some_work();
362
363  rtems_interrupt_lock_release(&lock, &lock_context);
364
365  printf(
366    "invalidate multiple instruction\n"
367    "  duration with normal cache %" PRIu64 " ns\n"
368    "  duration with warm cache %" PRIu64 " ns\n"
369    "  duration with invalidated cache %" PRIu64 " ns\n",
370    d[0],
371    d[1],
372    d[2]
373  );
374
375  rtems_interrupt_lock_destroy(&lock);
376}
377
378static void Init(rtems_task_argument arg)
379{
380  TEST_BEGIN();
381
382  test_data_flush_and_invalidate();
383  test_timing();
384
385  TEST_END();
386
387  rtems_test_exit(0);
388}
389
390#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
391#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
392
393#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
394
395#define CONFIGURE_MAXIMUM_TASKS 1
396
397#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
398
399#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
400
401#define CONFIGURE_INIT
402
403#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.