Mercurial > flash_v2
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 |
