agra-uni-bremen / riscv-vp

RISC-V Virtual Prototype
MIT License
139 stars 49 forks source link

Floating point operations cause unsupported sys call #24

Open aneskovic opened 1 year ago

aneskovic commented 1 year ago

Executing baremetal C code with floating point numbers causes the VP to throw the following error:

unsupported syscall '0'

Error: (E549) uncaught exception: unsupported syscall '0' In file: ../../../src/sysc/kernel/sc_except.cpp:101 In process: run0 @ 8940 ns make: *** [Makefile:5: sim] Error 1

This error is reproducable with the provied printf-float software example in the repository. I'm aware thath printf() can cause strange behaviour, but the error occurs also without calling the printf() function. Just multiplying two floating point numbers causes the same behaviour.

I tested it with the basic riscv-vp an the compiler flags from the printf-float software example function.

The behaviour is the same when I use the --intercept-syscalls command when invoking the riscv-vp.

Tested on Ubuntu 20.04, but also on with the provided Dockerfile. Same issues.

Has someone expirienced something similar or has an ide what could be the problem?

Cirromulus commented 1 year ago

We can reproduce this issue, but it behaves differently on our system. We will investigate this in the near future, but to be exact, the error is only due to using the syscall interface.

Actual floating point numbers are processed correctly when using the VP. To clarify, the SW examples are not bare metal. They use the syscall interface, which is just an example workaround to try out a few things. Actual bare metal programs (such as the ones provided in https://github.com/agra-uni-bremen/sifive-hifive1) do not use the host's functions.

CA92697 commented 1 year ago

We think the problem described is neither the system-call interface nor any printf issues (which have been resolved).

When floating-point operations result in an unsupported system-call, then the reason is likely a trap raised due to an illegal instruction. If that trap is not properly caught, the system-call handler accidentally catches it and, since it is unprepared for such situation, reports "unsupported syscall".

Note that a floating-point multiplication is actually illegal in the default setting this riscv-vp comes in. It's unfortunately hidden in the code, but the default ISS is a RV32IMACF (rv32/iss.cpp:1119), or more precisely a rv32 with IMACF + NUS extensions (rv32/csr.h:76).

Two more things to note: First, the D extension is not enabled, so floating-point multiplications of type 'double' are not supported (and thus result in raising an illegal instruction trap). See REQUIRE_ISA(D_ISA_EXT) in rv32/iss.cpp:885. Second, multiplications of 'float' type are enabled in the ISA with the F extension, but still result in an illegal instruction because the FPU is turned off by default. The ISS checks this with fp_require_not_off() in fp_prepare_instr() and finds csrs.mstatus.fs == FS_OFF.

So, if you like to execute 'float' and 'double' instructions natively (without the softfloat library), then you need to (1) cross-compile your code with -march=rv32imafd_zicsr -mabi=ilp32d options (or similar), (2) turn on the 'D' extension in the ISS (e.g. csrs.misa.extensions |= D;), and (3) turn on the FPU (e.g. extend ISS::ISS() to also do this: if (csrs.misa.extensions & ((F_ISA_EXT)|(D_ISA_EXT))) csrs.mstatus.fs = FS_INITIAL;

With these adjustments, we can explore the benefits of the F and D extensions easily.

Hope this helps!