NIOSV/g with FPU: inconsistent calculation results
I'm using a NIOSV/g with FPU enabled in a MAX10 project. The project involves heavy use of float point calculations, hence the need for the FPU. I noticed some occasionally inconsistent results in this program and started debugging - assuming this was a bug in my code. However I was able to run my code in a simulator and on a different RISCV microcontroller and everything worked flawlessly. I also disabled the FPU in the NIOSV design and again the code ran fine.
In order to recreate the problem, I created a basic project with just the NIOSV, some RAM and the JTAG-Uart. I also wrote a tiny C program to stress test the FPU. The results of this show that again, the FPU is producing incorrect results.
I've attached a screenshot of the Platform Designer design. I'm running the design at 75Mhz and the design meets timing requirements.
Here is the code I ran. Note that I have interrupts disabled to be sure this isn't a context switching issue. I also did not wrap the calculations into a function so I could more easily view the various calculation results in the debugger. This code works as expected when using a soft-FPU. When using the NIOSV FPU, results are inconsistent. I've attached a screenshot of one failed cycled. You can see that a1 and b1 are not equal.
#include <stdint.h> #include <math.h> #include "sys/alt_stdio.h" static void fpuTest(void) { int fail_count = 0; int iteration = 0; while (1) { float a0 = (float)iteration * 0.001f; float a1 = 1.1f * sinf((float)iteration * 0.1f); float a2 = 2.2f / (1.0f + (float)iteration * 0.0001f); float a3 = sqrtf(3.3f + (float)iteration); float a4 = powf(4.4f + (float)iteration, 1.1f); float a5 = logf(5.5f + (float)iteration + 1.0f); float a6 = 6.6f * cosf((float)iteration * 0.05f); float a7 = 7.7f + tanf((float)iteration * 0.02f); float result_a = a0 + a1 + a2 + a3 + a4 + a5 + a6 + a7; float b0 = (float)iteration * 0.001f; float b1 = 1.1f * sinf((float)iteration * 0.1f); float b2 = 2.2f / (1.0f + (float)iteration * 0.0001f); float b3 = sqrtf(3.3f + (float)iteration); float b4 = powf(4.4f + (float)iteration, 1.1f); float b5 = logf(5.5f + (float)iteration + 1.0f); float b6 = 6.6f * cosf((float)iteration * 0.05f); float b7 = 7.7f + tanf((float)iteration * 0.02f); float result_b = b0 + b1 + b2 + b3 + b4 + b5 + b6 + b7; // Check if result is consistent (should be identical) if (fabsf(result_a - result_b) > 1e-6f) { alt_printf("FPU test failed at iteration %x\n", iteration); fail_count++; } iteration++; } } int main(void) { // Make sure interrupts are disabled __asm volatile ( "csrc mstatus, 8" ); fpuTest(); while (1); return 0; }
Can someone help me investigate what could be wrong here? Could there be an issue in the FPU itself?