Make fp_sharing a 'parent' test suite directory, and rename the original fp_sharing test into tests/kernel/fp_sharing/generic. In this way more FP-related tests can be grouped together in the same test directory. Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
159 lines
3.6 KiB
C
159 lines
3.6 KiB
C
/*
|
|
* Copyright (c) 2011-2014 Wind River Systems, Inc.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/*
|
|
* @file
|
|
* pi computation portion of FPU sharing test
|
|
*
|
|
* This module is used for the FPU sharing test, and supplements the basic
|
|
* load/store test by incorporating two additional threads that utilize the
|
|
* floating point unit.
|
|
*
|
|
* Testing utilizes a pair of tasks that independently compute pi. The lower
|
|
* priority task is regularly preempted by the higher priority task, thereby
|
|
* testing whether floating point context information is properly preserved.
|
|
*
|
|
* The following formula is used to compute pi:
|
|
*
|
|
* pi = 4 * (1 - 1/3 + 1/5 - 1/7 + 1/9 - ... )
|
|
*
|
|
* This series converges to pi very slowly. For example, performing 50,000
|
|
* iterations results in an accuracy of 3 decimal places.
|
|
*
|
|
* A reference value of pi is computed once at the start of the test. All
|
|
* subsequent computations must produce the same value, otherwise an error
|
|
* has occurred.
|
|
*/
|
|
|
|
#include <zephyr.h>
|
|
|
|
#include <stdio.h>
|
|
#include <tc_util.h>
|
|
|
|
#include "float_context.h"
|
|
|
|
/*
|
|
* PI_NUM_ITERATIONS: This macro is defined in the project's Makefile and
|
|
* is configurable from the command line.
|
|
*/
|
|
|
|
static double reference_pi = 0.0f;
|
|
|
|
/*
|
|
* Test counters are "volatile" because GCC wasn't properly updating
|
|
* calc_pi_low_count properly when calculate_pi_low() contained a "return"
|
|
* in its error handling logic -- the value was incremented in a register,
|
|
* but never written back to memory. (Seems to be a compiler bug!)
|
|
*/
|
|
|
|
static volatile unsigned int calc_pi_low_count;
|
|
static volatile unsigned int calc_pi_high_count;
|
|
|
|
/**
|
|
*
|
|
* @brief Entry point for the low priority pi compute task
|
|
*
|
|
* @ingroup kernel_fpsharing_tests
|
|
*/
|
|
|
|
void calculate_pi_low(void)
|
|
{
|
|
volatile double pi; /* volatile to avoid optimizing out of loop */
|
|
double divisor = 3.0;
|
|
double sign = -1.0;
|
|
unsigned int ix;
|
|
|
|
/* loop forever, unless an error is detected */
|
|
|
|
while (1) {
|
|
|
|
sign = -1.0;
|
|
pi = 1.0;
|
|
divisor = 3.0;
|
|
|
|
for (ix = 0U; ix < PI_NUM_ITERATIONS; ix++) {
|
|
pi += sign / divisor;
|
|
divisor += 2.0;
|
|
sign *= -1.0;
|
|
}
|
|
|
|
pi *= 4;
|
|
|
|
if (reference_pi == 0.0f) {
|
|
reference_pi = pi;
|
|
} else if (reference_pi != pi) {
|
|
TC_ERROR("Computed pi %1.6f, reference pi %1.6f\n",
|
|
pi, reference_pi);
|
|
fpu_sharing_error = 1;
|
|
return;
|
|
}
|
|
|
|
++calc_pi_low_count;
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @brief Entry point for the high priority pi compute task
|
|
*
|
|
* @ingroup kernel_fpsharing_tests
|
|
*/
|
|
|
|
void calculate_pi_high(void)
|
|
{
|
|
volatile double pi; /* volatile to avoid optimizing out of loop */
|
|
double divisor = 3.0;
|
|
double sign = -1.0;
|
|
unsigned int ix;
|
|
|
|
/* loop forever, unless an error is detected */
|
|
|
|
while (1) {
|
|
|
|
sign = -1.0;
|
|
pi = 1.0;
|
|
divisor = 3.0;
|
|
|
|
for (ix = 0U; ix < PI_NUM_ITERATIONS; ix++) {
|
|
pi += sign / divisor;
|
|
divisor += 2.0;
|
|
sign *= -1.0;
|
|
}
|
|
|
|
/*
|
|
* Relinquish the processor for the remainder of the current
|
|
* system clock tick, so that lower priority threads get a
|
|
* chance to run.
|
|
*
|
|
* This exercises the ability of the kernel to restore the
|
|
* FPU state of a low priority thread _and_ the ability of the
|
|
* kernel to provide a "clean" FPU state to this thread
|
|
* once the sleep ends.
|
|
*/
|
|
|
|
k_sleep(10);
|
|
|
|
pi *= 4;
|
|
|
|
if (reference_pi == 0.0f) {
|
|
reference_pi = pi;
|
|
} else if (reference_pi != pi) {
|
|
TC_ERROR("Computed pi %1.6f, reference pi %1.6f\n",
|
|
pi, reference_pi);
|
|
fpu_sharing_error = 1;
|
|
return;
|
|
}
|
|
|
|
/* periodically issue progress report */
|
|
|
|
if ((++calc_pi_high_count % 100) == 50U) {
|
|
PRINT_DATA("Pi calculation OK after %u (high) +"
|
|
" %u (low) tests (computed %1.6f)\n",
|
|
calc_pi_high_count, calc_pi_low_count, pi);
|
|
}
|
|
}
|
|
}
|