]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/kernel/v2_0/tests/fptest.c
f455c8b3b3c10717884dacc5374eced29ff096f3
[karo-tx-redboot.git] / packages / kernel / v2_0 / tests / fptest.c
1 //==========================================================================
2 //
3 //        fptest.cxx
4 //
5 //        Basic FPU test
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 2003 Nick Garnett
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // -------------------------------------------
37 //####ECOSGPLCOPYRIGHTEND####
38 //==========================================================================
39 //#####DESCRIPTIONBEGIN####
40 //
41 // Author(s):     nickg@calivar.com
42 // Contributors:  nickg@calivar.com
43 // Date:          2003-01-27
44 // Description:   Simple FPU test. This is not very sophisticated as far
45 //                as checking FPU performance or accuracy. It is more
46 //                concerned with checking that several threads doing FP
47 //                operations do not interfere with eachother's use of the
48 //                FPU.
49 //
50 //####DESCRIPTIONEND####
51 //==========================================================================
52
53 #include <pkgconf/kernel.h>
54 #include <pkgconf/hal.h>
55
56 #include <cyg/hal/hal_arch.h>
57
58 #include <cyg/kernel/kapi.h>
59
60 #include <cyg/infra/testcase.h>
61 #include <cyg/infra/diag.h>
62
63 //#include <cyg/kernel/test/stackmon.h>
64 //#include CYGHWR_MEMORY_LAYOUT_H
65
66 //==========================================================================
67
68 #if defined(CYGFUN_KERNEL_API_C) &&             \
69     defined(CYGSEM_KERNEL_SCHED_MLQUEUE) &&     \
70     (CYGNUM_KERNEL_SCHED_PRIORITIES > 12)
71
72 //==========================================================================
73 // Base priority for all threads.
74
75 #define BASE_PRI        5
76
77 //==========================================================================
78 // Runtime
79 //
80 // This is the number of ticks that the program will run for. 3000
81 // ticks is equal to 30 seconds in the default configuration. For
82 // simulators we reduce the run time to 3 simulated seconds.
83
84 #define RUN_TICKS       3000
85 #define RUN_TICKS_SIM   300
86
87 //==========================================================================
88 // Thread parameters
89
90 #define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_MINIMUM)
91
92 static cyg_uint8 stacks[3][STACK_SIZE];
93 static cyg_handle_t thread[3];
94 static cyg_thread thread_struct[3];
95
96 //==========================================================================
97 // Alarm parameters.
98
99 static cyg_alarm alarm_struct;
100 static cyg_handle_t alarm;
101
102 static cyg_count8 cur_thread = 0;
103 static cyg_count32 alarm_ticks = 0;
104 static cyg_count32 run_ticks = RUN_TICKS;
105
106 //==========================================================================
107
108 static int errors = 0;
109
110 //==========================================================================
111 // Random number generator. Ripped out of the C library.
112
113 static int rand( unsigned int *seed )
114 {
115 // This is the code supplied in Knuth Vol 2 section 3.6 p.185 bottom
116
117 #define RAND_MAX 0x7fffffff
118 #define MM 2147483647    // a Mersenne prime
119 #define AA 48271         // this does well in the spectral test
120 #define QQ 44488         // (long)(MM/AA)
121 #define RR 3399          // MM % AA; it is important that RR<QQ
122
123     *seed = AA*(*seed % QQ) - RR*(unsigned int)(*seed/QQ);
124     if (*seed < 0)
125         *seed += MM;
126
127     return (int)( *seed & RAND_MAX );
128 }
129
130 //==========================================================================
131 // Test calculation.
132 //
133 // Generates an array of random FP values and then repeatedly applies
134 // a calculation to them and checks that the same result is reached
135 // each time. The calculation, in the macro CALC, is intended to make
136 // maximum use of the FPU registers. However, the i386 compiler
137 // doesn't let this expression get very complex before it starts
138 // spilling values out to memory.
139
140 static void do_test( double *values,
141                      int count,
142                      int loops,
143                      int test,
144                      const char *name)
145 {
146     unsigned int i, j;
147     // volatiles necessary to force
148     // values to 64 bits for comparison
149     volatile double sum = 1.0;
150     volatile double last_sum;
151     unsigned int seed;
152     
153 #define V(__i) (values[(__i)%count])
154 #define CALC ((V(i-1)*V(i+1))*(V(i-2)*V(i+2))*(V(i-3)*sum))
155
156     seed = ((unsigned int)&i)*count;
157
158     // Set up an array of values...
159     for( i = 0; i < count; i++ )
160         values[i] = (double)rand( &seed )/(double)0x7fffffff;
161
162     // Now calculate something from them...
163     for( i = 0; i < count; i++ )
164         sum += CALC;
165     last_sum = sum;
166     
167     // Now recalculate the sum in a loop and look for errors
168     for( j = 0; j < loops ; j++ )
169     {
170         sum = 1.0;
171         for( i = 0; i < count; i++ )
172             sum += CALC;
173
174         if( sum != last_sum )
175         {
176             union double_int_union {
177                 double d;
178                 cyg_uint32 i[2];
179             } diu_sum, diu_lastsum;
180
181             diu_sum.d = sum;
182             diu_lastsum.d = last_sum;
183             
184             errors++;
185             if (sizeof(double) != 2*sizeof(cyg_uint32)) {
186                 diag_printf("Warning: sizeof(double) != 2*sizeof(cyg_uint32), therefore next line may\n"
187                             "have invalid sum/last_sum values\n");
188             }
189             diag_printf("%s: Sum mismatch! %d sum=[%08x:%08x] last_sum=[%08x:%08x]\n",
190                         name,j, diu_sum.i[0], diu_sum.i[1], diu_lastsum.i[0], diu_lastsum.i[1] );
191         }
192         
193 #if 0
194         if( ((j*count)%1000000) == 0 )
195             diag_printf("INFO:<%s: %2d calculations done>\n",name,j*count);
196 #endif
197     }
198
199 }
200
201 //==========================================================================
202 // Alarm handler
203 //
204 // This is called every tick. It lowers the priority of the currently
205 // running thread and raises the priority of the next. Thus we
206 // implement a form of timelslicing between the threads at one tick
207 // granularity.
208
209 static void alarm_fn(cyg_handle_t alarm, cyg_addrword_t data)
210 {
211     alarm_ticks++;
212
213     if( alarm_ticks >= run_ticks )
214     {
215         if( errors )
216             CYG_TEST_FAIL("Errors detected");
217         else
218             CYG_TEST_PASS("OK");            
219         
220         CYG_TEST_FINISH("FP Test done");
221     }
222     else
223     {
224         cyg_thread_set_priority( thread[cur_thread], BASE_PRI );
225
226         cur_thread = (cur_thread+1)%3;
227
228         cyg_thread_set_priority( thread[cur_thread], BASE_PRI-1 );
229     }
230 }
231
232
233 //==========================================================================
234
235 #define FP1_COUNT 1000
236
237 static double fpt1_values[FP1_COUNT];
238
239 void fptest1( CYG_ADDRWORD id )
240 {
241     while(1)
242         do_test( fpt1_values, FP1_COUNT, 2000000000, id, "fptest1" );
243 }
244
245 //==========================================================================
246
247 #define FP2_COUNT 10000
248
249 static double fpt2_values[FP2_COUNT];
250
251 void fptest2( CYG_ADDRWORD id )
252 {
253     while(1)
254         do_test( fpt2_values, FP2_COUNT, 2000000000, id, "fptest2" );
255 }
256
257 //==========================================================================
258
259 #define FP3_COUNT 100
260
261 static double fpt3_values[FP3_COUNT];
262
263 void fptest3( CYG_ADDRWORD id )
264 {
265     while(1)
266         do_test( fpt3_values, FP3_COUNT, 2000000000, id, "fptest3" );
267 }
268
269 //==========================================================================
270
271 void fptest_main( void )
272 {
273     
274     CYG_TEST_INIT();
275
276     if( cyg_test_is_simulator )
277     {
278         run_ticks = RUN_TICKS_SIM;
279     }
280
281     CYG_TEST_INFO("Run fptest in cyg_start");
282     do_test( fpt3_values, FP3_COUNT, 1000, 0, "start" );
283     CYG_TEST_INFO( "cyg_start run done");
284     
285     cyg_thread_create( BASE_PRI-1,
286                        fptest1,
287                        0,
288                        "fptest1",
289                        &stacks[0][0],
290                        STACK_SIZE,
291                        &thread[0],
292                        &thread_struct[0]);
293
294     cyg_thread_resume( thread[0] );
295
296     cyg_thread_create( BASE_PRI,
297                        fptest2,
298                        1,
299                        "fptest2",
300                        &stacks[1][0],
301                        STACK_SIZE,
302                        &thread[1],
303                        &thread_struct[1]);
304
305     cyg_thread_resume( thread[1] );
306
307     cyg_thread_create( BASE_PRI,
308                        fptest3,
309                        2,
310                        "fptest3",
311                        &stacks[2][0],
312                        STACK_SIZE,
313                        &thread[2],
314                        &thread_struct[2]);
315
316     cyg_thread_resume( thread[2] );
317
318     cyg_alarm_create( cyg_real_time_clock(),
319                       alarm_fn,
320                       0,
321                       &alarm,
322                       &alarm_struct );
323
324     cyg_alarm_initialize( alarm, cyg_current_time()+1, 1 );
325     
326     cyg_scheduler_start();
327
328 }
329
330 //==========================================================================
331
332 #ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
333 externC void
334 cyg_hal_invoke_constructors();
335 #endif
336
337 externC void
338 cyg_start( void )
339 {
340 #ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
341     cyg_hal_invoke_constructors();
342 #endif
343     fptest_main();
344 }   
345
346 //==========================================================================
347
348 #else // CYGFUN_KERNEL_API_C...
349
350 externC void
351 cyg_start( void )
352 {
353     CYG_TEST_INIT();
354     CYG_TEST_INFO("FP test requires:\n"
355                 "CYGFUN_KERNEL_API_C && \n"
356                 "CYGSEM_KERNEL_SCHED_MLQUEUE && \n"
357                 "(CYGNUM_KERNEL_SCHED_PRIORITIES > 12)\n");
358     CYG_TEST_NA("FP test requirements");
359 }
360
361 #endif // CYGFUN_KERNEL_API_C, etc.
362
363 //==========================================================================
364 // EOF fptest.cxx