forked from Archive/PX4-Autopilot
Add single precision operations to FPU test
git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@4429 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
parent
2bc54edaf3
commit
1784e4785b
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue