comparison packages/kernel/current/tests/fptest.c @ 648:0c5540a10fcc

* tests/fptest.c: Changed to run for a constant time rather than a constant number of iterations, with a shorter run time for simulated targets.
author nickg
date Wed, 19 Feb 2003 19:14:48 +0000
parents fddb77989fbb
children 74589c7c236e
comparison
equal deleted inserted replaced
647:bf939f3a422a 648:0c5540a10fcc
31 // in accordance with section (3) of the GNU General Public License. 31 // in accordance with section (3) of the GNU General Public License.
32 // 32 //
33 // This exception does not invalidate any other reasons why a work based on 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. 34 // this file might be covered by the GNU General Public License.
35 // 35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // ------------------------------------------- 36 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND#### 37 //####ECOSGPLCOPYRIGHTEND####
40 //========================================================================== 38 //==========================================================================
41 //#####DESCRIPTIONBEGIN#### 39 //#####DESCRIPTIONBEGIN####
42 // 40 //
70 #if defined(CYGFUN_KERNEL_API_C) && \ 68 #if defined(CYGFUN_KERNEL_API_C) && \
71 defined(CYGSEM_KERNEL_SCHED_MLQUEUE) && \ 69 defined(CYGSEM_KERNEL_SCHED_MLQUEUE) && \
72 (CYGNUM_KERNEL_SCHED_PRIORITIES > 12) 70 (CYGNUM_KERNEL_SCHED_PRIORITIES > 12)
73 71
74 //========================================================================== 72 //==========================================================================
75 // Multiplier for loop counter. This allows us to tune the runtime of 73 // Base priority for all threads.
76 // the whole program easily. The current value gives a runtime of 74
77 // about 90s on an 800Mz Pentium III. 75 #define BASE_PRI 5
78 76
79 #define MULTIPLIER 100 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
80 86
81 //========================================================================== 87 //==========================================================================
82 // Thread parameters 88 // Thread parameters
83 89
84 #define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_MINIMUM+4096) 90 #define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_MINIMUM)
85 91
86 cyg_uint8 stacks[3][STACK_SIZE]; 92 cyg_uint8 stacks[3][STACK_SIZE];
87 cyg_handle_t thread[3]; 93 cyg_handle_t thread[3];
88 cyg_thread thread_struct[3]; 94 cyg_thread thread_struct[3];
95
96 //==========================================================================
97 // Alarm parameters.
98
99 cyg_alarm alarm_struct;
100 cyg_handle_t alarm;
101
102 cyg_count8 cur_thread = 0;
103 cyg_count32 alarm_ticks = 0;
104 cyg_count32 run_ticks = RUN_TICKS;
105
106 //==========================================================================
107
108 static int errors = 0;
89 109
90 //========================================================================== 110 //==========================================================================
91 // Random number generator. Ripped out of the C library. 111 // Random number generator. Ripped out of the C library.
92 112
93 static int rand( unsigned int *seed ) 113 static int rand( unsigned int *seed )
116 // maximum use of the FPU registers. However, the i386 compiler 136 // maximum use of the FPU registers. However, the i386 compiler
117 // doesn't let this expression get very complex before it starts 137 // doesn't let this expression get very complex before it starts
118 // spilling values out to memory. 138 // spilling values out to memory.
119 139
120 static void do_test( double *values, 140 static void do_test( double *values,
121 int count, 141 int count,
122 int loops, 142 int loops,
123 char *name) 143 int test,
124 { 144 const char *name)
125 int i, j; 145 {
126 double sum = 1.0; 146 unsigned int i, j;
127 double last_sum; 147 // volatiles necessary to force
148 // values to 64 bits for comparison
149 volatile double sum = 1.0;
150 volatile double last_sum;
128 unsigned int seed; 151 unsigned int seed;
129 152
130 #define V(__i) (values[(__i)%count]) 153 #define V(__i) (values[(__i)%count])
131 #define CALC ((V(i-1)*V(i+1))*(V(i-2)*V(i+2))*(V(i-3)*sum)) 154 #define CALC ((V(i-1)*V(i+1))*(V(i-2)*V(i+2))*(V(i-3)*sum))
132 155
133 seed = ((unsigned int)&i)*loops*count; 156 seed = ((unsigned int)&i)*count;
134 157
135 // Set up an array of values... 158 // Set up an array of values...
136 for( i = 0; i < count; i++ ) 159 for( i = 0; i < count; i++ )
137 values[i] = (double)rand( &seed )/(double)0x7fffffff; 160 values[i] = (double)rand( &seed )/(double)0x7fffffff;
138 161
140 for( i = 0; i < count; i++ ) 163 for( i = 0; i < count; i++ )
141 sum += CALC; 164 sum += CALC;
142 last_sum = sum; 165 last_sum = sum;
143 166
144 // Now recalculate the sum in a loop and look for errors 167 // Now recalculate the sum in a loop and look for errors
145 for( j = 0; j < loops; j++ ) 168 for( j = 0; j < loops ; j++ )
146 { 169 {
147 sum = 1.0; 170 sum = 1.0;
148 for( i = 0; i < count; i++ ) 171 for( i = 0; i < count; i++ )
149 sum += CALC; 172 sum += CALC;
150 173
151 if( sum != last_sum ) 174 if( sum != last_sum )
152 diag_printf("%s: Sum mismatch! %d\n",name,j); 175 {
153 176 errors++;
154 last_sum = sum; 177 diag_printf("%s: Sum mismatch! %d sum=[%08x:%08x] last_sum=[%08x:%08x]\n",
178 name,j,
179 ((cyg_uint32 *)&sum)[0],((cyg_uint32 *)&sum)[1],
180 ((cyg_uint32 *)&last_sum)[0],((cyg_uint32 *)&last_sum)[1]
181 );
182 }
183
184 #if 0
185 if( ((j*count)%1000000) == 0 )
186 diag_printf("INFO:<%s: %2d calculations done>\n",name,j*count);
187 #endif
155 } 188 }
156 189
157 } 190 }
158 191
159 //========================================================================== 192 //==========================================================================
160 193 // Alarm handler
161 volatile int done[4]; 194 //
162 195 // This is called every tick. It lowers the priority of the currently
163 volatile cyg_tick_count_t start, end; 196 // running thread and raises the priority of the next. Thus we
197 // implement a form of timelslicing between the threads at one tick
198 // granularity.
199
200 static void alarm_fn(cyg_handle_t alarm, cyg_addrword_t data)
201 {
202 alarm_ticks++;
203
204 if( alarm_ticks >= run_ticks )
205 {
206 if( errors )
207 CYG_TEST_FAIL("Errors detected");
208
209 CYG_TEST_FINISH("FP Test done");
210 }
211 else
212 {
213 cyg_thread_set_priority( thread[cur_thread], BASE_PRI );
214
215 cur_thread = (cur_thread+1)%3;
216
217 cyg_thread_set_priority( thread[cur_thread], BASE_PRI-1 );
218 }
219 }
220
164 221
165 //========================================================================== 222 //==========================================================================
166 223
167 #define FP1_COUNT 1000 224 #define FP1_COUNT 1000
168 #define FP1_LOOPS 1000*MULTIPLIER
169 225
170 static double fpt1_values[FP1_COUNT]; 226 static double fpt1_values[FP1_COUNT];
171 227
172 void fptest1( CYG_ADDRWORD id ) 228 void fptest1( CYG_ADDRWORD id )
173 { 229 {
174 diag_printf("fptest1: start\n"); 230 while(1)
175 231 do_test( fpt1_values, FP1_COUNT, 2000000000, id, "fptest1" );
176 do_test( &fpt1_values, FP1_COUNT, FP1_LOOPS, "fptest1" );
177
178 done[id] = 1;
179
180 diag_printf("fptest1: done\n");
181 } 232 }
182 233
183 //========================================================================== 234 //==========================================================================
184 235
185 #define FP2_COUNT 10000 236 #define FP2_COUNT 10000
186 #define FP2_LOOPS 100*MULTIPLIER
187 237
188 static double fpt2_values[FP2_COUNT]; 238 static double fpt2_values[FP2_COUNT];
189 239
190 void fptest2( CYG_ADDRWORD id ) 240 void fptest2( CYG_ADDRWORD id )
191 { 241 {
192 diag_printf("fptest2: start\n"); 242 while(1)
193 243 do_test( fpt2_values, FP2_COUNT, 2000000000, id, "fptest2" );
194 do_test( &fpt2_values, FP2_COUNT, FP2_LOOPS, "fptest2" ); 244 }
195 245
196 done[id] = 1; 246 //==========================================================================
197 247
198 diag_printf("fptest2: done\n"); 248 #define FP3_COUNT 100
199 }
200
201 //==========================================================================
202
203 #define FP3_COUNT 10000
204 #define FP3_LOOPS 100*MULTIPLIER
205 249
206 static double fpt3_values[FP3_COUNT]; 250 static double fpt3_values[FP3_COUNT];
207 251
208 void fptest3( CYG_ADDRWORD id ) 252 void fptest3( CYG_ADDRWORD id )
209 { 253 {
210 int all_done; 254 while(1)
211 255 do_test( fpt3_values, FP3_COUNT, 2000000000, id, "fptest3" );
212 diag_printf("fptest3: start\n");
213
214 do_test( &fpt3_values, FP3_COUNT, FP3_LOOPS, "fptest3" );
215
216 done[id] = 1;
217
218 diag_printf("fptest3: done\n");
219
220 // Spin here waiting for the other threads to finish. We should
221 // only wake up and test every third or second timeslice.
222 do {
223 int i;
224
225 cyg_thread_yield();
226
227 all_done = 0;
228 for( i = 0; i < 4; i++ )
229 all_done += done[i];
230
231 } while(all_done != 4 );
232
233 end = cyg_current_time();
234
235 diag_printf("Elapsed time %d ticks\n",end-start);
236
237 CYG_TEST_PASS_FINISH("FP Test OK");
238
239 } 256 }
240 257
241 //========================================================================== 258 //==========================================================================
242 259
243 void fptest_main( void ) 260 void fptest_main( void )
244 { 261 {
245 262
246 CYG_TEST_INIT(); 263 CYG_TEST_INIT();
247 264
248 start = cyg_current_time(); 265 if( cyg_test_is_simulator )
249 266 {
250 diag_printf("Run fptest1 in cyg_start\n"); 267 run_ticks = RUN_TICKS_SIM;
251 fptest1( 0 ); 268 }
252 269
253 cyg_thread_create( 5, 270 CYG_TEST_INFO("Run fptest in cyg_start");
271 do_test( fpt3_values, FP3_COUNT, 1000, 0, "start" );
272 CYG_TEST_INFO( "cyg_start run done");
273
274 cyg_thread_create( BASE_PRI-1,
254 fptest1, 275 fptest1,
255 1, 276 0,
256 "fptest1", 277 "fptest1",
257 &stacks[0][0], 278 &stacks[0][0],
258 STACK_SIZE, 279 STACK_SIZE,
259 &thread[0], 280 &thread[0],
260 &thread_struct[0]); 281 &thread_struct[0]);
261 282
262 cyg_thread_resume( thread[0] ); 283 cyg_thread_resume( thread[0] );
263 284
264 cyg_thread_create( 5, 285 cyg_thread_create( BASE_PRI,
265 fptest2, 286 fptest2,
266 2, 287 1,
267 "fptest2", 288 "fptest2",
268 &stacks[1][0], 289 &stacks[1][0],
269 STACK_SIZE, 290 STACK_SIZE,
270 &thread[1], 291 &thread[1],
271 &thread_struct[1]); 292 &thread_struct[1]);
272 293
273 cyg_thread_resume( thread[1] ); 294 cyg_thread_resume( thread[1] );
274 295
275 cyg_thread_create( 5, 296 cyg_thread_create( BASE_PRI,
276 fptest3, 297 fptest3,
277 3, 298 2,
278 "fptest3", 299 "fptest3",
279 &stacks[2][0], 300 &stacks[2][0],
280 STACK_SIZE, 301 STACK_SIZE,
281 &thread[2], 302 &thread[2],
282 &thread_struct[2]); 303 &thread_struct[2]);
283 304
284 cyg_thread_resume( thread[2] ); 305 cyg_thread_resume( thread[2] );
306
307 cyg_alarm_create( cyg_real_time_clock(),
308 alarm_fn,
309 0,
310 &alarm,
311 &alarm_struct );
312
313 cyg_alarm_initialize( alarm, cyg_current_time()+1, 1 );
285 314
286 cyg_scheduler_start(); 315 cyg_scheduler_start();
287 316
288 } 317 }
289 318