neorv32 icon indicating copy to clipboard operation
neorv32 copied to clipboard

Distribution/installation of the GCC toolchain

Open umarcor opened this issue 3 years ago • 7 comments

Coming from #54

https://github.com/stnolting/neorv32/pull/54#issuecomment-853920947 By the way, what do you think about having the pre-build GCC toolchain as submodule inside this repository? Maybe in sw/gcc? Tha scripts (makefiles) could use that as default so new-user could do a simple recursive git clone and they would get everything as a bundle 🤔

https://github.com/stnolting/neorv32/pull/54#issuecomment-853938959 That's something I wanted to bring in a different issue 🤣. So, why are you using your pre-built GCC toolchain? Do you need to customise it so that it understands NEORV32 as the target architecture? Or is it because of convenience? That is, could you use an "upstream" GCC? May NEORV32 be upstreamed?

This is a tool which your project depends on. It should not be a submodule inside the repository. Furthermore, most users should not install it through a custom script in this repo. Similarly to GHDL, Yosys, nextpnr, VUnit, etc. those should be installed independently. We want this project (and potentially any open source project) to be usable very regardless of the preferred environment of the user. Some will install system packages, others will use containers, MSYS2, Conda, Homebrew... They don't want to install those tools each time, but (very) infrequently. In that context, you are currently providing a single build for a very specific subset of environments.

Please, don't take me wrong. This is absolutely normal. Most open source EDA tooling projects are not properly packaged yet. Some (a few) are available on some (a few) popular distributions. There are efforts such as HDL's bazel and conda repos, or YosysHQ's oss-cad-toolchain. Yet, each of them is an ecosystem for the domain the maintainers/supporters are interested in.

Should you need to distribute a custom GCC because you need it customised, I would recommend that we add the generation of a container image and an MSYS2 package to you other repo. Then, consume those as any user will do. In fact, this is one of the main purposes of CI: to reproduce the experience you expect users to have on different platforms.

https://github.com/stnolting/neorv32/pull/54#issuecomment-853950156 Then let's discuss that in a new issue. 😄

https://github.com/stnolting/neorv32/pull/54#issuecomment-853950156

This is a tool which your project depends on. It should not be a submodule inside the repository.

Yeah right. You convinced me. 😉

umarcor avatar Jun 03 '21 15:06 umarcor

So, why are you using your pre-built GCC toolchain? Do you need to customise it so that it understands NEORV32 as the target architecture? Or is it because of convenience? That is, could you use an "upstream" GCC? May NEORV32 be upstreamed?

I am aware of the "official RISC-V" prebuilt toolchains: https://github.com/riscv/riscv-gnu-toolchain/releases

The problem with these toolchains (for example: riscv32-elf-ubuntu-*) is they were compiled using a fixed library configuration (so no -multilib). This fixed library configs assume 64-bit double-precision floating point support. So you have to compile your code using the ilp64d ABI and accordingly with the D ISA extension (double-precision floating-point), which is not supported by the NEORV32 at all.

There are other common ABIs, like a "soft-float" ABI that is currently used by the NEORV32 makefiles. But without -multilib this is not supported by their toolchains.

Details

In theory, there is no big deal using a floating-point ABI even if the targeted core does not support floating point operations. The compiler will not emit any floating-point operations if you do not use float arithmetic in your code (in theory).

BUT the compiler will emit instructions for spilling the floating point registers inside interrupt service routines. The CPU sees these instructions and - of course - will raise an illegal instruction exception, since there is not according D floating-point support.

In summary, the executable cannot run. 😭 I don't know if this is a "bug" in their CI or if they are simply not aware of this. Or maybe there is something I did not see....

More details

The NEORV32 does support native floating-point operations. The Zfinx ISA extension provides full IEEE single-precision support. Unfortunately, this extension is not ratified yet and therefore not supported by upstream GCC.

stnolting avatar Jun 03 '21 16:06 stnolting

I am aware of the "official RISC-V" prebuilt toolchains: https://github.com/riscv/riscv-gnu-toolchain/releases

I was not specifically thinking about those packages, but about the upstream in system package manager. For instance, the following packages are available on MSYS2:

mingw64/mingw-w64-x86_64-riscv64-unknown-elf-binutils 2.35-1 (mingw-w64-x86_64-riscv64-unknown-elf-toolchain)
    GNU Tools for RISC-V Embedded Processors - Binutils (mingw-w64)
mingw64/mingw-w64-x86_64-riscv64-unknown-elf-gcc 10.1.0-2 (mingw-w64-x86_64-riscv64-unknown-elf-toolchain)
    GNU Tools for RISC-V Embedded Processors - GCC (mingw-w64)
mingw64/mingw-w64-x86_64-riscv64-unknown-elf-newlib 3.3.0-2 (mingw-w64-x86_64-riscv64-unknown-elf-toolchain)
    GNU Tools for RISC-V Embedded Processors - Newlib (mingw-w64)

Those are riscv64. However, I used RISCV_TOOLCHAIN=riscv64-unknown-elf-gcc make install in sw/example/demo_pwm, and that produced exactly the same output as using an Ubuntu container and extracting your custom GCC there. Since you are a Windows user, I'd like to please ask you to give it a try. I do not maintain that package, but MSYS2 is my main local and quick EDA development environment, so I'd be glad if you could confirm it's usefulness.

The problem with these toolchains (for example: riscv32-elf-ubuntu-*) is they were compiled using a fixed library configuration (so no -multilib). This fixed library configs assume 64-bit double-precision floating point support. So you have to compile your code using the ilp64d ABI and accordingly with the D ISA extension (double-precision floating-point), which is not supported by the NEORV32 at all.

There are other common ABIs, like a "soft-float" ABI that is currently used by the NEORV32 makefiles. But without -multilib this is not supported by their toolchains.

I'm no expert in this area, but @Paebbels created Paebbels/GCC-Toolchains very few days ago, in order to provide alternatives to the built-in toolchains in Vivado. He is currently using manual build procedures, but I guess the plan is to provide those as containers, MSYS2 packages and/or standalone zipfiles. Therefore, it would be interesting to join efforts and cover your use case there.

umarcor avatar Jun 04 '21 15:06 umarcor

The GCC-Toolchains repo is currently a playground to build a useable toolchain, because the Xilinx toolchains are broken as .... The made it multilib, but floating point is fucked up. Newlib is not aware of FreeRTOS. FreeRTOS does nor secure FPU registers on context switch. FreeRTOS does not support atomic operations, because the task switch asember code is false ..

Anyhow, I now try to build toolchains for ARMv7 targeting A9 and R5 and ARMv8 for A53. I would like to add RISC-V, PowerPC and MIPS as well, when the general CI pipeline works. In addition to baremetal builds (newlib), I would like to support GNU Linux with glibc as well as e.g. FreeRTOS.

In a later stage, we can talk about packaging this and also how to replace compilers in vendor tools.

Paebbels avatar Jun 04 '21 17:06 Paebbels

@umarcor

Those are riscv64. However, I used RISCV_TOOLCHAIN=riscv64-unknown-elf-gcc make install in sw/example/demo_pwm, and that produced exactly the same output as using an Ubuntu container and extracting your custom GCC there. Since you are a Windows user, I'd like to please ask you to give it a try. I do not maintain that package, but MSYS2 is my main local and quick EDA development environment, so I'd be glad if you could confirm it's usefulness.

I am using Ubuntu on Windows as development environment. Please run riscv64-unknown-elf-gcc -v in your setup and check for --with-abi=ilp32 and --with-arch=rv32i. If those two are there then the toolchain is fine. If not, the toolchain can be fine, too, if it was compiled with -multilib.

However, I will try to check out the RISC-V MSYS2 toolchain this weekend.

@Paebbels

I would like to add RISC-V, PowerPC and MIPS as well, when the general CI pipeline works. In addition to baremetal builds (newlib), I would like to support GNU Linux with glibc as well as e.g. FreeRTOS.

I am looking forward to this! 👍 😉

stnolting avatar Jun 04 '21 21:06 stnolting

@stnolting it was compiled with --enable-multilib :tada:

# riscv64-unknown-elf-gcc -v
Using built-in specs.
COLLECT_GCC=C:\msys64\mingw64\bin\riscv64-unknown-elf-gcc.exe
COLLECT_LTO_WRAPPER=c:/msys64/mingw64/bin/../lib/gcc/riscv64-unknown-elf/10.1.0/lto-wrapper.exe
Target: riscv64-unknown-elf
Configured with: ../configure --build=x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --prefix=/mingw64 --target=riscv64-unknown-elf --with-native-system-header-dir=/mingw64/x86_64-w64-mingw32/include --libexecdir=/mingw64/lib --enable-languages=c,c++,ada --enable-plugins --disable-decimal-float --disable-libffi --disable-libgomp --disable-libmudflap --disable-libquadmath --disable-libssp --disable-libstdcxx-pch --disable-nls --disable-shared --disable-threads --disable-tls --disable-libada --with-gnu-as --with-gnu-ld --with-system-zlib --with-newlib --with-headers=/mingw64/riscv64-unknown-elf/include --with-python-dir=share/gcc-riscv64-unknown-elf --with-gmp --with-mpfr --with-mpc --with-isl --with-libelf --enable-gnu-indirect_function --enable-multilib --with-host-libstdcxx='-static-libgcc -Wl,-Bstatic,-lstdc++,-Bdynamic -lm' --enable-linker-plugin-flags='LDFLAGS=-static-libstdc++\ -static-libgcc\ -pipe\ -Wl,--dynamicbase,--high-entropy-va,--nxcompat,--default-image-base-high\ -Wl,--stack,12582912' LDFLAGS='-pipe -Wl,--dynamicbase,--high-entropy-va,--nxcompat,--default-image-base-high -Wl,--disable-dynamicbase,--image-base=0x400000'
Thread model: single
Supported LTO compression algorithms: zlib zstd
gcc version 10.1.0 (GCC)

So, we should update the docs (user guide) to let Windows users know that they can install pacman -S mingw-w64-x86_64-riscv64-unknown-elf-gcc mingw-w64-x86_64-yosys mingw-w64-x86_64-nextpnr :rocket:

umarcor avatar Jun 04 '21 21:06 umarcor

So, we should update the docs (user guide) to let Windows users know that they can install pacman -S mingw-w64-x86_64-riscv64-unknown-elf-gcc mingw-w64-x86_64-yosys mingw-w64-x86_64-nextpnr 🚀

Absolutely! And there should also be a new section about synthesis toolchain setup as the "toolchain" documentation only focuses on RISC-V gcc right now. -> TODO stack 😉

stnolting avatar Jun 04 '21 21:06 stnolting

And there should also be a new section about synthesis toolchain setup as the "toolchain" documentation only focuses on RISC-V gcc right now. -> TODO stack 😉

Agree. However, don't write that yet :wink: There are currently 3-4 ready-to-use solutions:

  • Containers.
  • MSYS2.
  • fpga-toolchain/fomu-toolchain/yosys's oss-cad-toolchain.
  • Conda.

Hence, rather than repeat the explanations here, better refer to the corresponding documentation and to working CI examples in this repo. As soon as im-tomu/fomu-workshop#487 is merged, three of those solutions will be covered. We can then see how to reuse/cross-reference.

Overall, explaining how to install and use EDA tooling is not the purpose of this repository. Some guidelines need to be provided, but the less the best. Enough for it to be easy to follow for newcomers.

umarcor avatar Jun 04 '21 22:06 umarcor