This is the mail archive of the
ecos-patches@sources.redhat.com
mailing list for the eCos project.
[APPROVAL REQUIRED] fptest.c updated
- From: Nick Garnett <nickg at ecoscentric dot com>
- To: ecos-patches at sources dot redhat dot com
- Date: 19 Feb 2003 19:16:18 +0000
- Subject: [APPROVAL REQUIRED] fptest.c updated
Approval needed for v2.0 branch, already committed to the trunk.
Index: ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/kernel/current/ChangeLog,v
retrieving revision 1.94
diff -u -5 -r1.94 ChangeLog
--- ChangeLog 10 Feb 2003 22:02:15 -0000 1.94
+++ ChangeLog 19 Feb 2003 19:09:46 -0000
@@ -1,5 +1,11 @@
+2003-02-19 Nick Garnett <nickg at calivar dot com>
+
+ * 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.
+
2003-02-10 Gary Thomas <gary at mlbassoc dot com>
* include/thread.inl: Add more debug info to thread stack checking.
* tests/clocktruth.cxx:
Index: tests/fptest.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/kernel/current/tests/fptest.c,v
retrieving revision 1.1
diff -u -5 -r1.1 fptest.c
--- tests/fptest.c 31 Jan 2003 11:44:03 -0000 1.1
+++ tests/fptest.c 19 Feb 2003 19:09:46 -0000
@@ -31,12 +31,10 @@
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
-// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
-// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
@@ -70,26 +68,48 @@
#if defined(CYGFUN_KERNEL_API_C) && \
defined(CYGSEM_KERNEL_SCHED_MLQUEUE) && \
(CYGNUM_KERNEL_SCHED_PRIORITIES > 12)
//==========================================================================
-// Multiplier for loop counter. This allows us to tune the runtime of
-// the whole program easily. The current value gives a runtime of
-// about 90s on an 800Mz Pentium III.
+// Base priority for all threads.
-#define MULTIPLIER 100
+#define BASE_PRI 5
+
+//==========================================================================
+// Runtime
+//
+// This is the number of ticks that the program will run for. 3000
+// ticks is equal to 30 seconds in the default configuration. For
+// simulators we reduce the run time to 3 simulated seconds.
+
+#define RUN_TICKS 3000
+#define RUN_TICKS_SIM 300
//==========================================================================
// Thread parameters
-#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_MINIMUM+4096)
+#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_MINIMUM)
cyg_uint8 stacks[3][STACK_SIZE];
cyg_handle_t thread[3];
cyg_thread thread_struct[3];
//==========================================================================
+// Alarm parameters.
+
+cyg_alarm alarm_struct;
+cyg_handle_t alarm;
+
+cyg_count8 cur_thread = 0;
+cyg_count32 alarm_ticks = 0;
+cyg_count32 run_ticks = RUN_TICKS;
+
+//==========================================================================
+
+static int errors = 0;
+
+//==========================================================================
// Random number generator. Ripped out of the C library.
static int rand( unsigned int *seed )
{
// This is the code supplied in Knuth Vol 2 section 3.6 p.185 bottom
@@ -116,23 +136,26 @@
// maximum use of the FPU registers. However, the i386 compiler
// doesn't let this expression get very complex before it starts
// spilling values out to memory.
static void do_test( double *values,
- int count,
- int loops,
- char *name)
-{
- int i, j;
- double sum = 1.0;
- double last_sum;
+ int count,
+ int loops,
+ int test,
+ const char *name)
+{
+ unsigned int i, j;
+ // volatiles necessary to force
+ // values to 64 bits for comparison
+ volatile double sum = 1.0;
+ volatile double last_sum;
unsigned int seed;
-
+
#define V(__i) (values[(__i)%count])
#define CALC ((V(i-1)*V(i+1))*(V(i-2)*V(i+2))*(V(i-3)*sum))
- seed = ((unsigned int)&i)*loops*count;
+ seed = ((unsigned int)&i)*count;
// Set up an array of values...
for( i = 0; i < count; i++ )
values[i] = (double)rand( &seed )/(double)0x7fffffff;
@@ -140,150 +163,156 @@
for( i = 0; i < count; i++ )
sum += CALC;
last_sum = sum;
// Now recalculate the sum in a loop and look for errors
- for( j = 0; j < loops; j++ )
+ for( j = 0; j < loops ; j++ )
{
sum = 1.0;
for( i = 0; i < count; i++ )
sum += CALC;
if( sum != last_sum )
- diag_printf("%s: Sum mismatch! %d\n",name,j);
-
- last_sum = sum;
+ {
+ errors++;
+ diag_printf("%s: Sum mismatch! %d sum=[%08x:%08x] last_sum=[%08x:%08x]\n",
+ name,j,
+ ((cyg_uint32 *)&sum)[0],((cyg_uint32 *)&sum)[1],
+ ((cyg_uint32 *)&last_sum)[0],((cyg_uint32 *)&last_sum)[1]
+ );
+ }
+
+#if 0
+ if( ((j*count)%1000000) == 0 )
+ diag_printf("INFO:<%s: %2d calculations done>\n",name,j*count);
+#endif
}
}
//==========================================================================
+// Alarm handler
+//
+// This is called every tick. It lowers the priority of the currently
+// running thread and raises the priority of the next. Thus we
+// implement a form of timelslicing between the threads at one tick
+// granularity.
+
+static void alarm_fn(cyg_handle_t alarm, cyg_addrword_t data)
+{
+ alarm_ticks++;
+
+ if( alarm_ticks >= run_ticks )
+ {
+ if( errors )
+ CYG_TEST_FAIL("Errors detected");
+
+ CYG_TEST_FINISH("FP Test done");
+ }
+ else
+ {
+ cyg_thread_set_priority( thread[cur_thread], BASE_PRI );
-volatile int done[4];
+ cur_thread = (cur_thread+1)%3;
+
+ cyg_thread_set_priority( thread[cur_thread], BASE_PRI-1 );
+ }
+}
-volatile cyg_tick_count_t start, end;
//==========================================================================
#define FP1_COUNT 1000
-#define FP1_LOOPS 1000*MULTIPLIER
static double fpt1_values[FP1_COUNT];
void fptest1( CYG_ADDRWORD id )
{
- diag_printf("fptest1: start\n");
-
- do_test( &fpt1_values, FP1_COUNT, FP1_LOOPS, "fptest1" );
-
- done[id] = 1;
-
- diag_printf("fptest1: done\n");
+ while(1)
+ do_test( fpt1_values, FP1_COUNT, 2000000000, id, "fptest1" );
}
//==========================================================================
#define FP2_COUNT 10000
-#define FP2_LOOPS 100*MULTIPLIER
static double fpt2_values[FP2_COUNT];
void fptest2( CYG_ADDRWORD id )
{
- diag_printf("fptest2: start\n");
-
- do_test( &fpt2_values, FP2_COUNT, FP2_LOOPS, "fptest2" );
-
- done[id] = 1;
-
- diag_printf("fptest2: done\n");
+ while(1)
+ do_test( fpt2_values, FP2_COUNT, 2000000000, id, "fptest2" );
}
//==========================================================================
-#define FP3_COUNT 10000
-#define FP3_LOOPS 100*MULTIPLIER
+#define FP3_COUNT 100
static double fpt3_values[FP3_COUNT];
void fptest3( CYG_ADDRWORD id )
{
- int all_done;
-
- diag_printf("fptest3: start\n");
-
- do_test( &fpt3_values, FP3_COUNT, FP3_LOOPS, "fptest3" );
-
- done[id] = 1;
-
- diag_printf("fptest3: done\n");
-
- // Spin here waiting for the other threads to finish. We should
- // only wake up and test every third or second timeslice.
- do {
- int i;
-
- cyg_thread_yield();
-
- all_done = 0;
- for( i = 0; i < 4; i++ )
- all_done += done[i];
-
- } while(all_done != 4 );
-
- end = cyg_current_time();
-
- diag_printf("Elapsed time %d ticks\n",end-start);
-
- CYG_TEST_PASS_FINISH("FP Test OK");
-
+ while(1)
+ do_test( fpt3_values, FP3_COUNT, 2000000000, id, "fptest3" );
}
//==========================================================================
void fptest_main( void )
{
CYG_TEST_INIT();
- start = cyg_current_time();
-
- diag_printf("Run fptest1 in cyg_start\n");
- fptest1( 0 );
+ if( cyg_test_is_simulator )
+ {
+ run_ticks = RUN_TICKS_SIM;
+ }
+
+ CYG_TEST_INFO("Run fptest in cyg_start");
+ do_test( fpt3_values, FP3_COUNT, 1000, 0, "start" );
+ CYG_TEST_INFO( "cyg_start run done");
- cyg_thread_create( 5,
+ cyg_thread_create( BASE_PRI-1,
fptest1,
- 1,
+ 0,
"fptest1",
&stacks[0][0],
STACK_SIZE,
&thread[0],
&thread_struct[0]);
cyg_thread_resume( thread[0] );
- cyg_thread_create( 5,
+ cyg_thread_create( BASE_PRI,
fptest2,
- 2,
+ 1,
"fptest2",
&stacks[1][0],
STACK_SIZE,
&thread[1],
&thread_struct[1]);
cyg_thread_resume( thread[1] );
- cyg_thread_create( 5,
+ cyg_thread_create( BASE_PRI,
fptest3,
- 3,
+ 2,
"fptest3",
&stacks[2][0],
STACK_SIZE,
&thread[2],
&thread_struct[2]);
cyg_thread_resume( thread[2] );
+
+ cyg_alarm_create( cyg_real_time_clock(),
+ alarm_fn,
+ 0,
+ &alarm,
+ &alarm_struct );
+
+ cyg_alarm_initialize( alarm, cyg_current_time()+1, 1 );
cyg_scheduler_start();
}
--
Nick Garnett eCos Kernel Architect
http://www.ecoscentric.com/ The eCos and RedBoot experts