|
2
|
1 /*================================================================= |
|
|
2 // |
|
|
3 // kcache2.c |
|
|
4 // |
|
|
5 // Cache feature/timing tests |
|
|
6 // |
|
|
7 //========================================================================== |
|
|
8 //####COPYRIGHTBEGIN#### |
|
|
9 // |
|
|
10 // ------------------------------------------- |
|
|
11 // The contents of this file are subject to the Cygnus eCos Public License |
|
|
12 // Version 1.0 (the "License"); you may not use this file except in |
|
|
13 // compliance with the License. You may obtain a copy of the License at |
|
|
14 // http://sourceware.cygnus.com/ecos |
|
|
15 // |
|
|
16 // Software distributed under the License is distributed on an "AS IS" |
|
|
17 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the |
|
|
18 // License for the specific language governing rights and limitations under |
|
|
19 // the License. |
|
|
20 // |
|
|
21 // The Original Code is eCos - Embedded Cygnus Operating System, released |
|
|
22 // September 30, 1998. |
|
|
23 // |
|
|
24 // The Initial Developer of the Original Code is Cygnus. Portions created |
|
|
25 // by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved. |
|
|
26 // ------------------------------------------- |
|
|
27 // |
|
|
28 //####COPYRIGHTEND#### |
|
|
29 //========================================================================== |
|
|
30 //#####DESCRIPTIONBEGIN#### |
|
|
31 // |
|
|
32 // Author(s): jskov, based on kcache1.c by dsm |
|
|
33 // Contributors: jskov |
|
|
34 // Date: 1998-12-10 |
|
|
35 // Description: Tests some of the more exotic cache macros. |
|
|
36 //####DESCRIPTIONEND#### |
|
|
37 */ |
|
|
38 |
|
|
39 #include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL |
|
|
40 |
|
|
41 #include <cyg/kernel/kapi.h> |
|
|
42 |
|
|
43 #include <cyg/infra/testcase.h> |
|
|
44 |
|
|
45 #ifdef CYGVAR_KERNEL_COUNTERS_CLOCK |
|
|
46 #ifdef CYGFUN_KERNEL_API_C |
|
|
47 |
|
|
48 #include <cyg/infra/diag.h> |
|
|
49 #include <cyg/hal/hal_cache.h> |
|
|
50 |
|
|
51 // ------------------------------------------------------------------------- |
|
|
52 |
|
|
53 #define NTHREADS 1 |
|
|
54 #define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL |
|
|
55 |
|
|
56 // The following are defaults for loop variables. Note they will be overriden |
|
|
57 // on simulator targets, where detected - there is no point testing a cache |
|
|
58 // which doesn't exist :-). |
|
|
59 |
|
|
60 #define TEST_DZERO_LOOPS 5000 // default number of loops for test_dzero() |
|
|
61 #define TIME_ILOCK_LOOPS 10000 // default number of loops for time_ilock() |
|
|
62 #define TIME_DLOCK_LOOPS 10000 // default number of loops for time_dlock() |
|
|
63 |
|
|
64 |
|
|
65 static cyg_handle_t thread[NTHREADS]; |
|
|
66 |
|
|
67 static cyg_thread thread_obj[NTHREADS]; |
|
|
68 static char stack[NTHREADS][STACKSIZE]; |
|
|
69 |
|
|
70 #define MAXSIZE 1<<18 |
|
|
71 |
|
|
72 volatile char m[MAXSIZE]; |
|
|
73 |
|
|
74 // ------------------------------------------------------------------------- |
|
|
75 // Test of data cache zero. |
|
|
76 // o Timing comparison with instructions doing the same amount of work. |
|
|
77 // o Check that area cleared with the DCACHE_ZERO macro contains zeros. |
|
|
78 #ifdef HAL_DCACHE_ZERO |
|
|
79 static void test_dzero(void) |
|
|
80 { |
|
|
81 register cyg_uint32 k, i; |
|
|
82 cyg_tick_count_t count0, count1; |
|
|
83 cyg_ucount32 t; |
|
|
84 volatile cyg_uint32* aligned_p; |
|
|
85 volatile cyg_uint32* p; |
|
|
86 register CYG_INTERRUPT_STATE oldints; |
|
|
87 cyg_ucount32 test_dzero_loops = TEST_DZERO_LOOPS; |
|
|
88 |
|
|
89 CYG_TEST_INFO("Data cache zero"); |
|
|
90 |
|
|
91 if (cyg_test_is_simulator) |
|
|
92 test_dzero_loops=10; |
|
|
93 |
|
|
94 aligned_p = (volatile cyg_uint32*) |
|
|
95 (((unsigned long) &m[HAL_DCACHE_LINE_SIZE*2]) |
|
|
96 & ~(HAL_DCACHE_LINE_SIZE-1)); |
|
|
97 |
|
|
98 // Time with conventional instructions. |
|
|
99 HAL_DISABLE_INTERRUPTS(oldints); |
|
|
100 HAL_DCACHE_SYNC(); |
|
|
101 HAL_DCACHE_DISABLE(); |
|
|
102 HAL_DCACHE_SYNC(); |
|
|
103 HAL_DCACHE_INVALIDATE_ALL(); |
|
|
104 HAL_DCACHE_ENABLE(); |
|
|
105 HAL_RESTORE_INTERRUPTS(oldints); |
|
|
106 count0 = cyg_current_time(); |
|
|
107 for (k = 0; k < test_dzero_loops; k++) { |
|
|
108 p = aligned_p; |
|
|
109 for (i = 0; i < HAL_DCACHE_SETS; i++) { |
|
|
110 #if (16 == HAL_DCACHE_LINE_SIZE) |
|
|
111 *p++ = 0; |
|
|
112 *p++ = 0; |
|
|
113 *p++ = 0; |
|
|
114 *p++ = 0; |
|
|
115 #else |
|
|
116 #error "Not defined for this cache line size." |
|
|
117 #endif |
|
|
118 } |
|
|
119 |
|
|
120 HAL_DISABLE_INTERRUPTS(oldints); |
|
|
121 HAL_DCACHE_SYNC(); |
|
|
122 HAL_DCACHE_DISABLE(); |
|
|
123 HAL_DCACHE_SYNC(); |
|
|
124 HAL_DCACHE_INVALIDATE_ALL(); |
|
|
125 HAL_DCACHE_ENABLE(); |
|
|
126 HAL_RESTORE_INTERRUPTS(oldints); |
|
|
127 } |
|
|
128 count1 = cyg_current_time(); |
|
|
129 t = count1 - count0; |
|
|
130 diag_printf("time with instructions: %d\n", t); |
|
|
131 |
|
|
132 // Initialize the area with non-zero so we can check whether |
|
|
133 // the macro cleared the area properly. |
|
|
134 p = aligned_p; |
|
|
135 for (i = 0; |
|
|
136 i < HAL_DCACHE_SETS*HAL_DCACHE_LINE_SIZE/sizeof(cyg_uint32); |
|
|
137 i++) { |
|
|
138 *p++ = 0xdeadbeef; |
|
|
139 } |
|
|
140 |
|
|
141 // Time with DCACHE_ZERO. |
|
|
142 HAL_DISABLE_INTERRUPTS(oldints); |
|
|
143 HAL_DCACHE_SYNC(); |
|
|
144 HAL_DCACHE_DISABLE(); |
|
|
145 HAL_DCACHE_SYNC(); |
|
|
146 HAL_DCACHE_INVALIDATE_ALL(); |
|
|
147 HAL_DCACHE_ENABLE(); |
|
|
148 HAL_RESTORE_INTERRUPTS(oldints); |
|
|
149 count0 = cyg_current_time(); |
|
|
150 for (k = 0; k < test_dzero_loops; k++) { |
|
|
151 HAL_DCACHE_ZERO(aligned_p, HAL_DCACHE_SETS*HAL_DCACHE_LINE_SIZE); |
|
|
152 |
|
|
153 HAL_DISABLE_INTERRUPTS(oldints); |
|
|
154 HAL_DCACHE_SYNC(); |
|
|
155 HAL_DCACHE_DISABLE(); |
|
|
156 HAL_DCACHE_SYNC(); |
|
|
157 HAL_DCACHE_INVALIDATE_ALL(); |
|
|
158 HAL_DCACHE_ENABLE(); |
|
|
159 HAL_RESTORE_INTERRUPTS(oldints); |
|
|
160 } |
|
|
161 count1 = cyg_current_time(); |
|
|
162 t = count1 - count0; |
|
|
163 diag_printf("time with HAL_DCACHE_ZERO: %d\n", t); |
|
|
164 |
|
|
165 // Verify that the area was actually cleared. |
|
|
166 { |
|
|
167 cyg_uint32 d; |
|
|
168 |
|
|
169 d = 0; |
|
|
170 p = aligned_p; |
|
|
171 for (i = 0; |
|
|
172 i < HAL_DCACHE_SETS*HAL_DCACHE_LINE_SIZE/sizeof(cyg_uint32); |
|
|
173 i++) { |
|
|
174 d |= *p++; |
|
|
175 } |
|
|
176 |
|
|
177 CYG_TEST_CHECK(0 == d, "region not properly cleared"); |
|
|
178 } |
|
|
179 |
|
|
180 } |
|
|
181 #endif |
|
|
182 |
|
|
183 // ------------------------------------------------------------------------- |
|
|
184 // Test of data cache write hint. |
|
|
185 // Just check that the macro compiles. |
|
|
186 #ifdef HAL_DCACHE_WRITE_HINT |
|
|
187 static void test_dwrite_hint(void) |
|
|
188 { |
|
|
189 register cyg_uint32 k; |
|
|
190 register CYG_INTERRUPT_STATE oldints; |
|
|
191 |
|
|
192 CYG_TEST_INFO("Data cache write hint"); |
|
|
193 |
|
|
194 HAL_DISABLE_INTERRUPTS(oldints); |
|
|
195 HAL_DCACHE_SYNC(); |
|
|
196 HAL_DCACHE_DISABLE(); |
|
|
197 HAL_DCACHE_SYNC(); |
|
|
198 HAL_DCACHE_INVALIDATE_ALL(); |
|
|
199 HAL_DCACHE_ENABLE(); |
|
|
200 HAL_RESTORE_INTERRUPTS(oldints); |
|
|
201 |
|
|
202 HAL_DCACHE_WRITE_HINT(&m[HAL_DCACHE_LINE_SIZE*2], 2*HAL_DCACHE_LINE_SIZE); |
|
|
203 for (k = 0; k < 20; k++); |
|
|
204 m[HAL_DCACHE_LINE_SIZE*2] = 42; |
|
|
205 } |
|
|
206 #endif |
|
|
207 |
|
|
208 // ------------------------------------------------------------------------- |
|
|
209 // Test of data cache read hint. |
|
|
210 // Just check that the macro compiles. |
|
|
211 #ifdef HAL_DCACHE_READ_HINT |
|
|
212 static void test_dread_hint(void) |
|
|
213 { |
|
|
214 register char c; |
|
|
215 register cyg_uint32 k; |
|
|
216 register CYG_INTERRUPT_STATE oldints; |
|
|
217 |
|
|
218 CYG_TEST_INFO("Data cache read hint"); |
|
|
219 |
|
|
220 HAL_DISABLE_INTERRUPTS(oldints); |
|
|
221 HAL_DCACHE_SYNC(); |
|
|
222 HAL_DCACHE_DISABLE(); |
|
|
223 HAL_DCACHE_SYNC(); |
|
|
224 HAL_DCACHE_INVALIDATE_ALL(); |
|
|
225 HAL_DCACHE_ENABLE(); |
|
|
226 HAL_RESTORE_INTERRUPTS(oldints); |
|
|
227 |
|
|
228 HAL_DCACHE_READ_HINT(&m[HAL_DCACHE_LINE_SIZE*2], 2*HAL_DCACHE_LINE_SIZE); |
|
|
229 for (k = 0; k < 20; k++); |
|
|
230 c = m[HAL_DCACHE_LINE_SIZE*2]; |
|
|
231 } |
|
|
232 #endif |
|
|
233 |
|
|
234 // ------------------------------------------------------------------------- |
|
|
235 // Test of data cache line store. |
|
|
236 // Just check that the macro compiles. |
|
|
237 #ifdef HAL_DCACHE_STORE |
|
|
238 static void test_dstore(void) |
|
|
239 { |
|
|
240 volatile cyg_uint8* aligned_p; |
|
|
241 cyg_int32 i; |
|
|
242 register CYG_INTERRUPT_STATE oldints; |
|
|
243 |
|
|
244 CYG_TEST_INFO("Data cache store region"); |
|
|
245 |
|
|
246 for (i = 0; i < HAL_DCACHE_LINE_SIZE*16; i++) |
|
|
247 m[i] = 0; |
|
|
248 |
|
|
249 HAL_DISABLE_INTERRUPTS(oldints); |
|
|
250 HAL_DCACHE_SYNC(); |
|
|
251 HAL_DCACHE_DISABLE(); |
|
|
252 HAL_DCACHE_SYNC(); |
|
|
253 HAL_DCACHE_INVALIDATE_ALL(); |
|
|
254 HAL_DCACHE_ENABLE(); |
|
|
255 HAL_RESTORE_INTERRUPTS(oldints); |
|
|
256 |
|
|
257 aligned_p = (volatile cyg_uint8*) |
|
|
258 (((unsigned long) &m[HAL_DCACHE_LINE_SIZE*2]) |
|
|
259 & ~(HAL_DCACHE_LINE_SIZE-1)); |
|
|
260 |
|
|
261 aligned_p[0] = 42; |
|
|
262 |
|
|
263 HAL_DCACHE_STORE(aligned_p, HAL_DCACHE_LINE_SIZE); |
|
|
264 } |
|
|
265 #endif |
|
|
266 |
|
|
267 // ------------------------------------------------------------------------- |
|
|
268 // Test of data cache line flush. |
|
|
269 // o Requires write-back cache. |
|
|
270 // o Check that flushed data is written to memory. |
|
|
271 // o Simple range check of macro. |
|
|
272 #ifdef HAL_DCACHE_FLUSH |
|
|
273 static void test_dflush(void) |
|
|
274 { |
|
|
275 volatile cyg_uint8* aligned_p; |
|
|
276 cyg_int32 i; |
|
|
277 register CYG_INTERRUPT_STATE oldints; |
|
|
278 |
|
|
279 CYG_TEST_INFO("Data cache flush region"); |
|
|
280 |
|
|
281 for (i = 0; i < HAL_DCACHE_LINE_SIZE*16; i++) |
|
|
282 m[i] = 0; |
|
|
283 |
|
|
284 HAL_DISABLE_INTERRUPTS(oldints); |
|
|
285 HAL_DCACHE_SYNC(); |
|
|
286 HAL_DCACHE_DISABLE(); |
|
|
287 HAL_DCACHE_SYNC(); |
|
|
288 HAL_DCACHE_INVALIDATE_ALL(); |
|
|
289 HAL_DCACHE_ENABLE(); |
|
|
290 HAL_RESTORE_INTERRUPTS(oldints); |
|
|
291 |
|
|
292 aligned_p = (volatile cyg_uint8*) |
|
|
293 (((unsigned long) &m[HAL_DCACHE_LINE_SIZE*2]) |
|
|
294 & ~(HAL_DCACHE_LINE_SIZE-1)); |
|
|
295 |
|
|
296 aligned_p[0] = 42; |
|
|
297 aligned_p[HAL_DCACHE_LINE_SIZE] = 43; |
|
|
298 |
|
|
299 HAL_DCACHE_FLUSH(aligned_p, HAL_DCACHE_LINE_SIZE); |
|
|
300 |
|
|
301 HAL_DCACHE_DISABLE(); |
|
|
302 |
|
|
303 CYG_TEST_CHECK(42 == aligned_p[0], |
|
|
304 "memory didn't contain flushed data"); |
|
|
305 CYG_TEST_CHECK(0 == aligned_p[HAL_DCACHE_LINE_SIZE], |
|
|
306 "flushed beyond region"); |
|
|
307 |
|
|
308 HAL_DCACHE_ENABLE(); |
|
|
309 |
|
|
310 } |
|
|
311 #endif |
|
|
312 |
|
|
313 // ------------------------------------------------------------------------- |
|
|
314 // Test of data cache line invalidate. |
|
|
315 // o Requires write-back cache. |
|
|
316 // o Check that invalidated data is not written to memory and is invalidated |
|
|
317 // in the cache. |
|
|
318 // o Simple range check of macro. |
|
|
319 #ifdef HAL_DCACHE_INVALIDATE |
|
|
320 static void test_dinvalidate(void) |
|
|
321 { |
|
|
322 volatile cyg_uint8* aligned_p; |
|
|
323 cyg_int32 i; |
|
|
324 register CYG_INTERRUPT_STATE oldints; |
|
|
325 |
|
|
326 CYG_TEST_INFO("Data cache invalidate region"); |
|
|
327 |
|
|
328 for (i = 0; i < HAL_DCACHE_LINE_SIZE*16; i++) |
|
|
329 m[i] = 0; |
|
|
330 |
|
|
331 HAL_DISABLE_INTERRUPTS(oldints); |
|
|
332 HAL_DCACHE_SYNC(); |
|
|
333 HAL_DCACHE_DISABLE(); |
|
|
334 HAL_DCACHE_SYNC(); |
|
|
335 HAL_DCACHE_INVALIDATE_ALL(); |
|
|
336 HAL_DCACHE_ENABLE(); |
|
|
337 HAL_RESTORE_INTERRUPTS(oldints); |
|
|
338 |
|
|
339 aligned_p = (volatile cyg_uint8*) |
|
|
340 (((unsigned long) &m[HAL_DCACHE_LINE_SIZE*2]) |
|
|
341 & ~(HAL_DCACHE_LINE_SIZE-1)); |
|
|
342 |
|
|
343 aligned_p[0] = 43; |
|
|
344 aligned_p[HAL_DCACHE_LINE_SIZE-1] = 43; |
|
|
345 |
|
|
346 aligned_p[HAL_DCACHE_LINE_SIZE] = 42; |
|
|
347 |
|
|
348 HAL_DCACHE_INVALIDATE(aligned_p, HAL_DCACHE_LINE_SIZE); |
|
|
349 |
|
|
350 CYG_TEST_CHECK(0 == aligned_p[0] && |
|
|
351 0 == aligned_p[HAL_DCACHE_LINE_SIZE-1], |
|
|
352 "cache/memory contained invalidated data"); |
|
|
353 CYG_TEST_CHECK(42 == aligned_p[HAL_DCACHE_LINE_SIZE], |
|
|
354 "invalidated beyond range"); |
|
|
355 } |
|
|
356 #endif |
|
|
357 |
|
|
358 // ------------------------------------------------------------------------- |
|
|
359 // Test of instruction cache locking. |
|
|
360 // o Time difference between repeatedly executing a bunch of instructions |
|
|
361 // with and without locking. |
|
|
362 #ifdef HAL_ICACHE_LOCK |
|
|
363 static void iloop(unsigned long* start, unsigned long* end) |
|
|
364 { |
|
|
365 register char c; |
|
|
366 register CYG_INTERRUPT_STATE oldints; |
|
|
367 |
|
|
368 label_start: |
|
|
369 // Invalidating shouldn't affect locked lines. |
|
|
370 HAL_DISABLE_INTERRUPTS(oldints); |
|
|
371 HAL_ICACHE_DISABLE(); |
|
|
372 HAL_ICACHE_INVALIDATE_ALL(); |
|
|
373 HAL_ICACHE_ENABLE(); |
|
|
374 HAL_RESTORE_INTERRUPTS(oldints); |
|
|
375 |
|
|
376 c = m[HAL_DCACHE_LINE_SIZE*0]; |
|
|
377 c = m[HAL_DCACHE_LINE_SIZE*1]; |
|
|
378 c = m[HAL_DCACHE_LINE_SIZE*2]; |
|
|
379 c = m[HAL_DCACHE_LINE_SIZE*3]; |
|
|
380 c = m[HAL_DCACHE_LINE_SIZE*4]; |
|
|
381 c = m[HAL_DCACHE_LINE_SIZE*5]; |
|
|
382 c = m[HAL_DCACHE_LINE_SIZE*6]; |
|
|
383 c = m[HAL_DCACHE_LINE_SIZE*7]; |
|
|
384 c = m[HAL_DCACHE_LINE_SIZE*8]; |
|
|
385 c = m[HAL_DCACHE_LINE_SIZE*9]; |
|
|
386 c = m[HAL_DCACHE_LINE_SIZE*10]; |
|
|
387 c = m[HAL_DCACHE_LINE_SIZE*11]; |
|
|
388 c = m[HAL_DCACHE_LINE_SIZE*12]; |
|
|
389 c = m[HAL_DCACHE_LINE_SIZE*13]; |
|
|
390 c = m[HAL_DCACHE_LINE_SIZE*14]; |
|
|
391 c = m[HAL_DCACHE_LINE_SIZE*15]; |
|
|
392 c = m[HAL_DCACHE_LINE_SIZE*16]; |
|
|
393 c = m[HAL_DCACHE_LINE_SIZE*17]; |
|
|
394 c = m[HAL_DCACHE_LINE_SIZE*18]; |
|
|
395 c = m[HAL_DCACHE_LINE_SIZE*19]; |
|
|
396 c = m[HAL_DCACHE_LINE_SIZE*20]; |
|
|
397 c = m[HAL_DCACHE_LINE_SIZE*21]; |
|
|
398 c = m[HAL_DCACHE_LINE_SIZE*22]; |
|
|
399 c = m[HAL_DCACHE_LINE_SIZE*23]; |
|
|
400 c = m[HAL_DCACHE_LINE_SIZE*24]; |
|
|
401 c = m[HAL_DCACHE_LINE_SIZE*25]; |
|
|
402 c = m[HAL_DCACHE_LINE_SIZE*26]; |
|
|
403 c = m[HAL_DCACHE_LINE_SIZE*27]; |
|
|
404 c = m[HAL_DCACHE_LINE_SIZE*28]; |
|
|
405 c = m[HAL_DCACHE_LINE_SIZE*29]; |
|
|
406 c = m[HAL_DCACHE_LINE_SIZE*30]; |
|
|
407 c = m[HAL_DCACHE_LINE_SIZE*31]; |
|
|
408 c = m[HAL_DCACHE_LINE_SIZE*32]; |
|
|
409 c = m[HAL_DCACHE_LINE_SIZE*33]; |
|
|
410 c = m[HAL_DCACHE_LINE_SIZE*34]; |
|
|
411 c = m[HAL_DCACHE_LINE_SIZE*35]; |
|
|
412 c = m[HAL_DCACHE_LINE_SIZE*36]; |
|
|
413 c = m[HAL_DCACHE_LINE_SIZE*37]; |
|
|
414 c = m[HAL_DCACHE_LINE_SIZE*38]; |
|
|
415 c = m[HAL_DCACHE_LINE_SIZE*39]; |
|
|
416 c = m[HAL_DCACHE_LINE_SIZE*40]; |
|
|
417 c = m[HAL_DCACHE_LINE_SIZE*41]; |
|
|
418 c = m[HAL_DCACHE_LINE_SIZE*42]; |
|
|
419 c = m[HAL_DCACHE_LINE_SIZE*43]; |
|
|
420 c = m[HAL_DCACHE_LINE_SIZE*44]; |
|
|
421 c = m[HAL_DCACHE_LINE_SIZE*45]; |
|
|
422 c = m[HAL_DCACHE_LINE_SIZE*46]; |
|
|
423 c = m[HAL_DCACHE_LINE_SIZE*47]; |
|
|
424 c = m[HAL_DCACHE_LINE_SIZE*48]; |
|
|
425 c = m[HAL_DCACHE_LINE_SIZE*49]; |
|
|
426 c = m[HAL_DCACHE_LINE_SIZE*50]; |
|
|
427 c = m[HAL_DCACHE_LINE_SIZE*51]; |
|
|
428 c = m[HAL_DCACHE_LINE_SIZE*52]; |
|
|
429 c = m[HAL_DCACHE_LINE_SIZE*53]; |
|
|
430 c = m[HAL_DCACHE_LINE_SIZE*54]; |
|
|
431 c = m[HAL_DCACHE_LINE_SIZE*55]; |
|
|
432 c = m[HAL_DCACHE_LINE_SIZE*56]; |
|
|
433 c = m[HAL_DCACHE_LINE_SIZE*57]; |
|
|
434 c = m[HAL_DCACHE_LINE_SIZE*58]; |
|
|
435 c = m[HAL_DCACHE_LINE_SIZE*59]; |
|
|
436 c = m[HAL_DCACHE_LINE_SIZE*60]; |
|
|
437 c = m[HAL_DCACHE_LINE_SIZE*61]; |
|
|
438 c = m[HAL_DCACHE_LINE_SIZE*62]; |
|
|
439 c = m[HAL_DCACHE_LINE_SIZE*63]; |
|
|
440 |
|
|
441 label_end: |
|
|
442 |
|
|
443 *start = (unsigned long) &&label_start; |
|
|
444 *end = (unsigned long) &&label_end; |
|
|
445 } |
|
|
446 |
|
|
447 static void time_ilock(void) |
|
|
448 { |
|
|
449 register cyg_ucount32 k; |
|
|
450 cyg_tick_count_t count0, count1; |
|
|
451 cyg_ucount32 t; |
|
|
452 unsigned long start, end; |
|
|
453 register cyg_ucount32 time_ilock_loops = TIME_ILOCK_LOOPS; |
|
|
454 |
|
|
455 CYG_TEST_INFO("Instruction cache lock"); |
|
|
456 |
|
|
457 if (cyg_test_is_simulator) |
|
|
458 time_ilock_loops = 10; |
|
|
459 |
|
|
460 count0 = cyg_current_time(); |
|
|
461 for (k = 0; k < time_ilock_loops; k++) { |
|
|
462 iloop(&start, &end); |
|
|
463 } |
|
|
464 count1 = cyg_current_time(); |
|
|
465 t = count1 - count0; |
|
|
466 diag_printf("time without lock: %d\n", t); |
|
|
467 |
|
|
468 HAL_ICACHE_LOCK(start, end-start); |
|
|
469 |
|
|
470 count0 = cyg_current_time(); |
|
|
471 for (k = 0; k < time_ilock_loops; k++) { |
|
|
472 iloop(&start, &end); |
|
|
473 } |
|
|
474 count1 = cyg_current_time(); |
|
|
475 t = count1 - count0; |
|
|
476 diag_printf("time with lock: %d\n", t); |
|
|
477 |
|
|
478 HAL_ICACHE_UNLOCK(start, end-start); |
|
|
479 } |
|
|
480 #endif // ifdef HAL_ICACHE_LOCK |
|
|
481 |
|
|
482 // ------------------------------------------------------------------------- |
|
|
483 // Test of data cache locking. |
|
|
484 // o Time difference between repeatedly accessing a memory region |
|
|
485 // with and without locking. |
|
|
486 #ifdef HAL_DCACHE_LOCK |
|
|
487 static void dloop(void) |
|
|
488 { |
|
|
489 register cyg_uint32 j; |
|
|
490 register char c; |
|
|
491 register CYG_INTERRUPT_STATE oldints; |
|
|
492 |
|
|
493 HAL_DISABLE_INTERRUPTS(oldints); |
|
|
494 HAL_DCACHE_SYNC(); |
|
|
495 HAL_DCACHE_DISABLE(); |
|
|
496 HAL_DCACHE_SYNC(); |
|
|
497 HAL_DCACHE_INVALIDATE_ALL(); |
|
|
498 HAL_DCACHE_ENABLE(); |
|
|
499 HAL_RESTORE_INTERRUPTS(oldints); |
|
|
500 for (j = 0; j < HAL_DCACHE_SETS; j++) { |
|
|
501 c = m[HAL_DCACHE_LINE_SIZE*j]; |
|
|
502 } |
|
|
503 } |
|
|
504 |
|
|
505 static void time_dlock(void) |
|
|
506 { |
|
|
507 register cyg_ucount32 k; |
|
|
508 cyg_tick_count_t count0, count1; |
|
|
509 cyg_ucount32 t; |
|
|
510 register cyg_ucount32 time_dlock_loops = TIME_DLOCK_LOOPS; |
|
|
511 |
|
|
512 CYG_TEST_INFO("Data cache lock"); |
|
|
513 |
|
|
514 if (cyg_test_is_simulator) |
|
|
515 time_dlock_loops = 10; |
|
|
516 |
|
|
517 count0 = cyg_current_time(); |
|
|
518 for (k = 0; k < time_dlock_loops; k++) { |
|
|
519 dloop(); |
|
|
520 } |
|
|
521 count1 = cyg_current_time(); |
|
|
522 t = count1 - count0; |
|
|
523 diag_printf("time without lock: %d\n", t); |
|
|
524 |
|
|
525 HAL_DCACHE_LOCK(&m[0], HAL_DCACHE_SETS*HAL_DCACHE_LINE_SIZE); |
|
|
526 |
|
|
527 count0 = cyg_current_time(); |
|
|
528 for (k = 0; k < time_dlock_loops; k++) { |
|
|
529 dloop(); |
|
|
530 } |
|
|
531 count1 = cyg_current_time(); |
|
|
532 t = count1 - count0; |
|
|
533 diag_printf("time with lock: %d\n", t); |
|
|
534 |
|
|
535 HAL_DCACHE_UNLOCK(&m[0], HAL_DCACHE_SETS*HAL_DCACHE_LINE_SIZE); |
|
|
536 } |
|
|
537 #endif // ifdef HAL_DCACHE_LOCK |
|
|
538 |
|
|
539 // ------------------------------------------------------------------------- |
|
|
540 static void entry0( cyg_addrword_t data ) |
|
|
541 { |
|
|
542 #ifdef HAL_DCACHE_LOCK |
|
|
543 time_dlock(); |
|
|
544 #endif |
|
|
545 #ifdef HAL_ICACHE_LOCK |
|
|
546 time_ilock(); |
|
|
547 #endif |
|
|
548 #ifdef HAL_DCACHE_STORE |
|
|
549 test_dstore(); |
|
|
550 #endif |
|
|
551 #ifdef HAL_DCACHE_READ_HINT |
|
|
552 test_dread_hint(); |
|
|
553 #endif |
|
|
554 #ifdef HAL_DCACHE_WRITE_HINT |
|
|
555 test_dwrite_hint(); |
|
|
556 #endif |
|
|
557 #ifdef HAL_DCACHE_ZERO |
|
|
558 test_dzero(); |
|
|
559 #endif |
|
|
560 |
|
|
561 // The below tests only work on a copy-back cache. |
|
|
562 if (0) { |
|
|
563 #ifdef HAL_DCACHE_FLUSH |
|
|
564 test_dflush(); |
|
|
565 #endif |
|
|
566 #ifdef HAL_DCACHE_INVALIDATE |
|
|
567 test_dinvalidate(); |
|
|
568 #endif |
|
|
569 } |
|
|
570 |
|
|
571 CYG_TEST_PASS_FINISH("End of test"); |
|
|
572 } |
|
|
573 |
|
|
574 // ------------------------------------------------------------------------- |
|
|
575 |
|
|
576 void kcache2_main( void ) |
|
|
577 { |
|
|
578 CYG_TEST_INIT(); |
|
|
579 |
|
|
580 cyg_thread_create(4, entry0 , (cyg_addrword_t)0, "kcache2", |
|
|
581 (void *)stack[0], STACKSIZE, &thread[0], &thread_obj[0]); |
|
|
582 cyg_thread_resume(thread[0]); |
|
|
583 |
|
|
584 cyg_scheduler_start(); |
|
|
585 } |
|
|
586 |
|
|
587 // ------------------------------------------------------------------------- |
|
|
588 |
|
|
589 externC void |
|
|
590 cyg_start( void ) |
|
|
591 { |
|
|
592 kcache2_main(); |
|
|
593 } |
|
|
594 |
|
|
595 // ------------------------------------------------------------------------- |
|
|
596 |
|
|
597 #else // def CYGFUN_KERNEL_API_C |
|
|
598 #define N_A_MSG "Kernel C API layer disabled" |
|
|
599 #endif // def CYGFUN_KERNEL_API_C |
|
|
600 #else // def CYGVAR_KERNEL_COUNTERS_CLOCK |
|
|
601 #define N_A_MSG "Kernel real-time clock disabled" |
|
|
602 #endif // def CYGVAR_KERNEL_COUNTERS_CLOCK |
|
|
603 |
|
|
604 #ifdef N_A_MSG |
|
|
605 externC void |
|
|
606 cyg_start( void ) |
|
|
607 { |
|
|
608 CYG_TEST_INIT(); |
|
|
609 CYG_TEST_NA( N_A_MSG ); |
|
|
610 } |
|
|
611 #endif // N_A_MSG |
|
|
612 |
|
|
613 // ------------------------------------------------------------------------- |
|
|
614 /* EOF kcache2.c */ |