mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-07-22 01:00:35 +08:00
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:
+80
-29
@@ -90,10 +90,11 @@
|
|||||||
|
|
||||||
/* Other defintions ****************************************************/
|
/* Other defintions ****************************************************/
|
||||||
/* We'll keep all data using 32-bit values only to force 32-bit alignment.
|
/* 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_WORDSIZE ((CONFIG_EXAMPLES_OSTEST_FPUSIZE+3)>>2)
|
||||||
|
#define FPU_NTHREADS 2
|
||||||
|
|
||||||
#ifndef NULL
|
#ifndef NULL
|
||||||
# define NULL (void*)0
|
# define NULL (void*)0
|
||||||
@@ -114,17 +115,43 @@
|
|||||||
extern void arch_getfpu(FAR uint32_t *fpusave);
|
extern void arch_getfpu(FAR uint32_t *fpusave);
|
||||||
|
|
||||||
/* Given two arrays of size CONFIG_EXAMPLES_OSTEST_FPUSIZE this
|
/* 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,
|
extern bool arch_cmpfpu(FAR const uint32_t *fpusave1,
|
||||||
FAR const uint32_t *fpusave2);
|
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
|
* Private Data
|
||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
|
|
||||||
static uint8_t g_fpuno;
|
static uint8_t g_fpuno;
|
||||||
|
/* static */ struct fpu_threaddata_s g_fputhread[FPU_NTHREADS];
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* Private Functions
|
* 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[])
|
static int fpu_task(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
uint32_t fpusave1[FPU_WORDSIZE];
|
FAR struct fpu_threaddata_s *fpu;
|
||||||
uint32_t fpusave2[FPU_WORDSIZE];
|
register float sp1;
|
||||||
double val1;
|
register float sp2;
|
||||||
double val2;
|
register float sp3;
|
||||||
double val3;
|
register float sp4;
|
||||||
double val4;
|
register double dp1;
|
||||||
|
register double dp2;
|
||||||
|
register double dp3;
|
||||||
|
register double dp4;
|
||||||
|
|
||||||
int id;
|
int id;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Which are we? */
|
/* Which are we? */
|
||||||
|
|
||||||
sched_lock();
|
sched_lock();
|
||||||
id = (int)(++g_fpuno);
|
fpu = &g_fputhread[g_fpuno];
|
||||||
|
id = (int)(++g_fpuno);
|
||||||
sched_unlock();
|
sched_unlock();
|
||||||
|
|
||||||
/* Seed the flowing point values */
|
/* Seed the flowing point values */
|
||||||
|
|
||||||
val1 = (double)id;
|
sp1 = (float)id;
|
||||||
|
dp1 = (double)id;
|
||||||
|
|
||||||
for (i = 0; i < CONFIG_EXAMPLES_OSTEST_FPULOOPS; i++)
|
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.
|
* that we can verify that reading of the registers actually occurs.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
memset(fpusave1, 0xff, sizeof(fpusave1));
|
memset(fpu->save1, 0xff, FPU_WORDSIZE * sizeof(uint32_t));
|
||||||
memset(fpusave2, 0xff, sizeof(fpusave1));
|
memset(fpu->save2, 0xff, FPU_WORDSIZE * sizeof(uint32_t));
|
||||||
|
|
||||||
/* Prevent context switches while we set up some stuff */
|
/* Prevent context switches while we set up some stuff */
|
||||||
|
|
||||||
sched_lock();
|
sched_lock();
|
||||||
|
|
||||||
/* Do some trivial floating point operations that should cause some
|
/* 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 */
|
sp4 = (float)3.14159 * sp1; /* Multiple by Pi */
|
||||||
val3 = val4 + 1.61803398874; /* Add the golden ratio */
|
sp3 = sp4 + (float)1.61803; /* Add the golden ratio */
|
||||||
val2 = val3 / 2.7182; /* Divide by Euler's constant */
|
sp2 = sp3 / (float)2.71828; /* Divide by Euler's constant */
|
||||||
val1 = val2 + 1.0; /* Plus one */
|
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 */
|
/* Sample the floating point registers */
|
||||||
|
|
||||||
arch_getfpu(fpusave1);
|
arch_getfpu(fpu->save1);
|
||||||
|
|
||||||
/* Re-read and verify the FPU registers consistently without corruption */
|
/* Re-read and verify the FPU registers consistently without corruption */
|
||||||
|
|
||||||
arch_getfpu(fpusave2);
|
arch_getfpu(fpu->save2);
|
||||||
if (!arch_cmpfpu(fpusave1, fpusave2))
|
if (!arch_cmpfpu(fpu->save1, fpu->save2))
|
||||||
{
|
{
|
||||||
printf("ERROR FPU#%d: fpusave1 and fpusave2 do not match\n", id);
|
printf("ERROR FPU#%d: save1 and save2 do not match\n", id);
|
||||||
fpu_dump(fpusave1, "Values after math operations (fpusave1)");
|
fpu_dump(fpu->save1, "Values after math operations (save1)");
|
||||||
fpu_dump(fpusave2, "Values after verify re-read (fpusave2)");
|
fpu_dump(fpu->save2, "Values after verify re-read (save2)");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,12 +277,12 @@ static int fpu_task(int argc, char *argv[])
|
|||||||
* point registers are still correctly set.
|
* point registers are still correctly set.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
arch_getfpu(fpusave2);
|
arch_getfpu(fpu->save2);
|
||||||
if (!arch_cmpfpu(fpusave1, fpusave2))
|
if (!arch_cmpfpu(fpu->save1, fpu->save2))
|
||||||
{
|
{
|
||||||
printf("ERROR FPU#%d: fpusave1 and fpusave2 do not match\n", id);
|
printf("ERROR FPU#%d: save1 and save2 do not match\n", id);
|
||||||
fpu_dump(fpusave1, "Values before waiting (fpusave1)");
|
fpu_dump(fpu->save1, "Values before waiting (save1)");
|
||||||
fpu_dump(fpusave2, "Values after waiting (fpusave2)");
|
fpu_dump(fpu->save2, "Values after waiting (save2)");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,6 +70,12 @@
|
|||||||
# error "CONFIG_EXAMPLES_OSTEST_FPUSIZE has the wrong size"
|
# error "CONFIG_EXAMPLES_OSTEST_FPUSIZE has the wrong size"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/************************************************************************************
|
||||||
|
* Private Data
|
||||||
|
************************************************************************************/
|
||||||
|
|
||||||
|
static uint32_t g_saveregs[XCPTCONTEXT_REGS];
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
@@ -84,17 +90,20 @@
|
|||||||
void arch_getfpu(FAR uint32_t *fpusave)
|
void arch_getfpu(FAR uint32_t *fpusave)
|
||||||
{
|
{
|
||||||
irqstate_t flags;
|
irqstate_t flags;
|
||||||
uint32_t regs[XCPTCONTEXT_REGS];
|
|
||||||
|
/* Take a snapshot of the thread context right now */
|
||||||
|
|
||||||
flags = irqsave();
|
flags = irqsave();
|
||||||
up_savefpu(regs); /* Saves the context of the FPU registers to memory */
|
up_saveusercontext(g_saveregs);
|
||||||
irqrestore(flags);
|
|
||||||
|
|
||||||
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
|
/* 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)
|
bool arch_cmpfpu(FAR const uint32_t *fpusave1, FAR const uint32_t *fpusave2)
|
||||||
|
|||||||
Reference in New Issue
Block a user