Forum Discussion
NIOS2 HW & DIV Instructions + FPU
Hello i am in charge of designing a system that does a lot of complex sin/cos/* instructions and i need them to be fast.
I am using NIOS2-F at 100mhz in a Cyclone IV. I've enabled HW and DIV by hardware at NIOS2-F and i am using 64K data and instruction cache. My software is being compiled with these flagsCFLAGS = -Wall -DNOCRYPT -mhw-div -mhw-mul -mcustom-fpu-cfg=60-1 -mcustom-fpu-cfg=60-2 -O3
I tried to use the Custom FPU instruction at QSys but my performace is slower with Custom FPU instruction attached to NIOS2-F at QSYS (why?) Is there anything else i can do? Any suggestions?28 Replies
- Altera_Forum
Honored Contributor
If you are manually passing in the flags for your builds make sure you keep them in sync with the hardware implementation (i.e. don't pass in the 60-1 or 60-2 flags if you don't have the FPU added to the Nios II core).
The Taylor series I remember finding was under the POSIX implementation in newlib and it wasn't long enough to give an accurate answer. I ended up hardware accelerating it and since it only used the first 3 terms of the series I would end up with things like sqrt(1) = 0.999999. - Altera_Forum
Honored Contributor
I am using the 60-1 and 60-2 flags without having a FPU added to the Nios II core.
I made this tests to see if float operations are working
The results were all good.. is my test right? If i remove those flags my processing suffer a lot of lossstatic float legal; static float legal2; legal = 3.4; legal2 = 2; log_msg("Multiplicando: %f -- Dividindo: %f", legal * legal2, legal/legal2); legal = 4; legal2 = 2.3; log_msg("Multiplicando: %f -- Dividindo: %f", legal * legal2, legal/legal2); legal = 4.5; legal2 = 2.3; log_msg("Multiplicando: %f -- Dividindo: %f", legal * legal2, legal/legal2); legal = 4.3148981934; legal2 = 2.313319843; log_msg("Multiplicando: %f -- Dividindo: %f", legal * legal2, legal/legal2); legal = 4.3148981934; legal2 = 2.313319843; - Altera_Forum
Honored Contributor
Hmmm.... Either:
1) your nios has the fpu instructions. 2) the compiler is optimising out the arithmetic - which it can do for the above code. 3) there are no custom instructions at all, and the cpu takes an 'unknown instruction' trap, and some code emulates them. (I'm not sure this is possible at all) Try with 'volatile float legal;' which will force the compiler to do the memory accesses. - Altera_Forum
Honored Contributor
Can NIOS2 have the FPU instruction by default? I just selected hw divide/multiplication on the NIOS2-F core.
I will test with the volatile - Altera_Forum
Honored Contributor
Since your code is working on constants I wouldn't expect the FPU to be used even if one was present since those results can be pre-computed.
The FPU is pretty big compared to the Nios II core so the FPU is not added automatically since many would be annoyed by this (especially the folks who don't need float support or who take the time to perform fixed point math). The hardware multiple and divide options of the various Nios II cores are for integer data types, not float/double. - Altera_Forum
Honored Contributor
Damn as DSL said when i changed the type of my variable to volatile all the values from multiplication and division stayed at 0
- Altera_Forum
Honored Contributor
Well but when i use volatile int my operations also result at 0 (even when i remove the FPU flags at Makefile)....
weird - Altera_Forum
Honored Contributor
At least this is making more sense now.... So with the volatile keyword you were preventing the compiler from performing the floating point operations at compile time so that they would have to be executed at runtime. I would expect 0 to be read back when you attempt to use a custom instruction that is not implemented.
Make sure you regenerate your makefiles for the application and BSP otherwise those flags will still be present when you go to compile. It also appears you were confused by the floating point support. The multiplication and division options in the CPU parameterization are *only* for integer operations. If you want single precision floating point support you need to add the floating point custom instruction to the Nios II core. - Altera_Forum
Honored Contributor
I've attached the FPU unit and now everything works (ofc this is the obvious)
sorry for wasting ur time about that =) I changed the FPU to this one at alterawiki: http://www.alterawiki.com/wiki/configurable_fpu I am testing with this code
And everything works fine# include <stdio.h> int main() { float a = 10.; float b = 11.; float c = a * b; printf("c = %f\n", c); return 0; } - Altera_Forum
Honored Contributor
One other heads up, when you add the FPU floating point constants are treated as single precision. The 'normal' behavior is to have floating point constants treated as type double. So if you have constants in your code and you want to keep them represented as constants use the 'l' suffix which will ensure the constant is treated as a long double (Nios II doesn't support long doubles so this will become a double).
So instead of this: double a = 2.3; // with the FPU enabled you'll end up with a single precision 2.3 type cast over to a double precision 2.3 (truncation could happen if the constant was very large) Do this: double a = 2.3l; // no type casting will occur