From 1784e4785b4c640df807d5adf5b6d24df48e5f1d Mon Sep 17 00:00:00 2001 From: patacongo Date: Sun, 26 Feb 2012 15:27:36 +0000 Subject: [PATCH] Add single precision operations to FPU test git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@4429 7fd9a85b-ad96-42d3-883c-3090e2eb8679 --- apps/examples/ostest/fpu.c | 109 ++++++++++++++------ nuttx/configs/stm3240g-eval/src/up_ostest.c | 19 +++- 2 files changed, 94 insertions(+), 34 deletions(-) diff --git a/apps/examples/ostest/fpu.c b/apps/examples/ostest/fpu.c index 56cee45eed..89a1034ce9 100644 --- a/apps/examples/ostest/fpu.c +++ b/apps/examples/ostest/fpu.c @@ -90,10 +90,11 @@ /* Other defintions ****************************************************/ /* We'll keep all data using 32-bit values only to force 32-bit alignment. - * This logic has not real notion of the underlying representation. + * This logic has no real notion of the underlying representation. */ #define FPU_WORDSIZE ((CONFIG_EXAMPLES_OSTEST_FPUSIZE+3)>>2) +#define FPU_NTHREADS 2 #ifndef NULL # define NULL (void*)0 @@ -114,17 +115,43 @@ extern void arch_getfpu(FAR uint32_t *fpusave); /* Given two arrays of size CONFIG_EXAMPLES_OSTEST_FPUSIZE this - * function will compare then an return true if they are identical. + * function will compare them and return true if they are identical. */ extern bool arch_cmpfpu(FAR const uint32_t *fpusave1, FAR const uint32_t *fpusave2); +/*********************************************************************** + * Private Types + ***********************************************************************/ + +struct fpu_threaddata_s +{ + uint32_t save1[FPU_WORDSIZE]; + uint32_t save2[FPU_WORDSIZE]; + + /* These are just dummy values to force the compiler to do the + * requested floating point computations without the nonsense + * computations being optimized away. + */ + + volatile float sp1; + volatile float sp2; + volatile float sp3; + volatile float sp4; + + volatile float dp1; + volatile float dp2; + volatile float dp3; + volatile float dp4; +}; + /*********************************************************************** * Private Data ***********************************************************************/ static uint8_t g_fpuno; +/* static */ struct fpu_threaddata_s g_fputhread[FPU_NTHREADS]; /*********************************************************************** * Private Functions @@ -158,24 +185,30 @@ static void fpu_dump(FAR uint32_t *buffer, FAR const char *msg) static int fpu_task(int argc, char *argv[]) { - uint32_t fpusave1[FPU_WORDSIZE]; - uint32_t fpusave2[FPU_WORDSIZE]; - double val1; - double val2; - double val3; - double val4; + FAR struct fpu_threaddata_s *fpu; + register float sp1; + register float sp2; + register float sp3; + register float sp4; + register double dp1; + register double dp2; + register double dp3; + register double dp4; + int id; int i; /* Which are we? */ sched_lock(); - id = (int)(++g_fpuno); + fpu = &g_fputhread[g_fpuno]; + id = (int)(++g_fpuno); sched_unlock(); /* Seed the flowing point values */ - val1 = (double)id; + sp1 = (float)id; + dp1 = (double)id; for (i = 0; i < CONFIG_EXAMPLES_OSTEST_FPULOOPS; i++) { @@ -186,34 +219,52 @@ static int fpu_task(int argc, char *argv[]) * that we can verify that reading of the registers actually occurs. */ - memset(fpusave1, 0xff, sizeof(fpusave1)); - memset(fpusave2, 0xff, sizeof(fpusave1)); + memset(fpu->save1, 0xff, FPU_WORDSIZE * sizeof(uint32_t)); + memset(fpu->save2, 0xff, FPU_WORDSIZE * sizeof(uint32_t)); /* Prevent context switches while we set up some stuff */ sched_lock(); /* Do some trivial floating point operations that should cause some - * changes to floating point resters + * changes to floating point registers. First, some single preceision + * nonsense. */ - val4 = 3.1415926 * val1; /* Multiple by Pi */ - val3 = val4 + 1.61803398874; /* Add the golden ratio */ - val2 = val3 / 2.7182; /* Divide by Euler's constant */ - val1 = val2 + 1.0; /* Plus one */ - + sp4 = (float)3.14159 * sp1; /* Multiple by Pi */ + sp3 = sp4 + (float)1.61803; /* Add the golden ratio */ + sp2 = sp3 / (float)2.71828; /* Divide by Euler's constant */ + sp1 = sp2 + (float)1.0; /* Plus one */ + + fpu->sp1 = sp1; /* Make the compiler believe that somebody cares about the result */ + fpu->sp2 = sp2; + fpu->sp3 = sp3; + fpu->sp4 = sp4; + + /* Again using double precision */ + + dp4 = (double)3.14159 * dp1; /* Multiple by Pi */ + dp3 = dp4 + (double)1.61803; /* Add the golden ratio */ + dp2 = dp3 / (double)2.71828; /* Divide by Euler's constant */ + dp1 = dp2 + (double)1.0; /* Plus one */ + + fpu->dp1 = dp1; /* Make the compiler believe that somebody cares about the result */ + fpu->dp2 = dp2; + fpu->dp3 = dp3; + fpu->dp4 = dp4; + /* Sample the floating point registers */ - arch_getfpu(fpusave1); + arch_getfpu(fpu->save1); /* Re-read and verify the FPU registers consistently without corruption */ - arch_getfpu(fpusave2); - if (!arch_cmpfpu(fpusave1, fpusave2)) + arch_getfpu(fpu->save2); + if (!arch_cmpfpu(fpu->save1, fpu->save2)) { - printf("ERROR FPU#%d: fpusave1 and fpusave2 do not match\n", id); - fpu_dump(fpusave1, "Values after math operations (fpusave1)"); - fpu_dump(fpusave2, "Values after verify re-read (fpusave2)"); + printf("ERROR FPU#%d: save1 and save2 do not match\n", id); + fpu_dump(fpu->save1, "Values after math operations (save1)"); + fpu_dump(fpu->save2, "Values after verify re-read (save2)"); return EXIT_FAILURE; } @@ -226,12 +277,12 @@ static int fpu_task(int argc, char *argv[]) * point registers are still correctly set. */ - arch_getfpu(fpusave2); - if (!arch_cmpfpu(fpusave1, fpusave2)) + arch_getfpu(fpu->save2); + if (!arch_cmpfpu(fpu->save1, fpu->save2)) { - printf("ERROR FPU#%d: fpusave1 and fpusave2 do not match\n", id); - fpu_dump(fpusave1, "Values before waiting (fpusave1)"); - fpu_dump(fpusave2, "Values after waiting (fpusave2)"); + printf("ERROR FPU#%d: save1 and save2 do not match\n", id); + fpu_dump(fpu->save1, "Values before waiting (save1)"); + fpu_dump(fpu->save2, "Values after waiting (save2)"); return EXIT_FAILURE; } } diff --git a/nuttx/configs/stm3240g-eval/src/up_ostest.c b/nuttx/configs/stm3240g-eval/src/up_ostest.c index a30999d09c..b84f7a40e2 100644 --- a/nuttx/configs/stm3240g-eval/src/up_ostest.c +++ b/nuttx/configs/stm3240g-eval/src/up_ostest.c @@ -70,6 +70,12 @@ # error "CONFIG_EXAMPLES_OSTEST_FPUSIZE has the wrong size" #endif +/************************************************************************************ + * Private Data + ************************************************************************************/ + +static uint32_t g_saveregs[XCPTCONTEXT_REGS]; + /************************************************************************************ * Private Functions ************************************************************************************/ @@ -84,17 +90,20 @@ void arch_getfpu(FAR uint32_t *fpusave) { irqstate_t flags; - uint32_t regs[XCPTCONTEXT_REGS]; + + /* Take a snapshot of the thread context right now */ flags = irqsave(); - up_savefpu(regs); /* Saves the context of the FPU registers to memory */ - irqrestore(flags); + up_saveusercontext(g_saveregs); - memcpy(fpusave, ®s[REG_S0], (4*SW_FPU_REGS)); + /* Return only the floating register values */ + + memcpy(fpusave, &g_saveregs[REG_S0], (4*SW_FPU_REGS)); + irqrestore(flags); } /* Given two arrays of size CONFIG_EXAMPLES_OSTEST_FPUSIZE this function - * will compare then an return true if they are identical. + * will compare them and return true if they are identical. */ bool arch_cmpfpu(FAR const uint32_t *fpusave1, FAR const uint32_t *fpusave2)