Using LLVM Target for RISCV (incompatibility error)

Hello everyone, I was trying to create a custom target (as a part of a thesis)

self.target = tvm.target.Target( “llvm -mcpu=rv32gc --mtriple=riscv32-unknown-elf --system-lib --runtime=c -mfloat-abi=hard”). Using LLVM backend that generated 2 object files that I linked to the tool chain in the CMake and used our micro TVM as a codegen (similar approach while using the C backend by other colleagues) and made some minor changes. Thus, I run into an incompatibility as the 2 files has an architecture of riscv32i20p (inspecting with readelf) using soft floating and the toolchain that uses hard floating.

home/heatdh/Desktop/Ba/ml_on_mcu/deps/install/gcc_riscv/bin/…/lib/gcc/riscv64-unknown-elf/8.3.0/…/…/…/…/riscv64-unknown-elf/bin/ld: …/lib/ml_interface/libml_interface.a(lib1.o): can’t link soft-float modules with double-float modules /home/heatdh/Desktop/Ba/ml_on_mcu/deps/install/gcc_riscv/bin/…/lib/gcc/riscv64-unknown-elf/8.3.0/…/…/…/…/riscv64-unknown-elf/bin/ld: failed to merge target specific data of file …/lib/ml_interface/libml_interface.a(lib1.o) /home/heatdh/Desktop/Ba/ml_on_mcu/deps/install/gcc_riscv/bin/…/lib/gcc/riscv64-unknown-elf/8.3.0/…/…/…/…/riscv64-unknown-elf/bin/ld: …/lib/ml_interface/libml_interface.a(lib1.o): in function fused_nn_contrib_dense_pack_add_compute_': TVMMod:(.text+0x57c): undefined reference to __mulsf3’ /home/heatdh/Desktop/Ba/ml_on_mcu/deps/install/gcc_riscv/bin/…/lib/gcc/riscv64-unknown-elf/8.3.0/…/…/…/…/riscv64-unknown-elf/bin/ld: TVMMod:(.text+0x588): undefined reference to __addsf3' /home/heatdh/Desktop/Ba/ml_on_mcu/deps/install/gcc_riscv/bin/../lib/gcc/riscv64-unknown-elf/8.3.0/../../../../riscv64-unknown-elf/bin/ld: TVMMod:(.text+0x5a0): undefined reference to __mulsf3’ /home/heatdh/Desktop/Ba/ml_on_mcu/deps/install/gcc_riscv/bin/…/lib/gcc/riscv64-unknown-elf/8.3.0/…/…/…/…/riscv64-unknown-elf/bin/ld: TVMMod:(.text+0x5ac): undefined reference to `__addsf3’

(These function doesn’t seem to be implemented in the object files)

I tried playing around in the TVM target implementation changing some attributes and printing within the llvm codegen, but it seems that mfloat-abi is not set properly, and the scope is not being executed. Rebuilding the tool chain as discussed with my supervisor doesn’t seem to be practical for us. Would you have any suggestions

Thank you in advance and would be happy to explain in details if something is unclear

2 Likes

hi @heatdh,

could you let me know which version of LLVM you’re using, or any other steps or scripts i could use to reproduce the problem?

thanks, Andrew

If you use llvm as your codegenerator, it will not generate double-float object file for riscv, I don’t know why, but it can’t, even though you add -mfloat-abi=hard, the workaround is save the code as a text assembly code and then call your cross compiler to generate object file.

for example

fadd = tvm.build(s, [A, B, C], tgt, name="myadd")
from tvm.contrib import cc
path = "lib/riscv.so"
fadd.save("lib/riscv.s")
cc.create_shared(path, ["lib/riscv.s"], cc="riscv64-unknown-linux-gnu-g++")

Hello Mr Reusch, I’m currently using LLVM 11.0.1 (upgraded recently from 11.0.0). The problem occurs while adding the object files to the codegen in the same way we are doing it with the lib.c generalted files by the c backend somehow while commenting some basic tvm funtions from tvm/runtime/c_runtime_api.h it passes through but for sure without processing the data (tried both our uTVM and the TVM codegen) . The code gen we are using GitHub - tum-ei-eda/utvm_staticrt_codegen: This project contains a code generator that produces static C NN inference deployment code targeting tiny micro-controllers (TinyML) as replacement for other µTVM runtimes. This tools generates a runtime, which statically executes the compiled model. This reduces the overhead in terms of code size and execution time compared to having a dynamic on-device runtime. Note : that tvmrt produces as well the same errors while trying I hope this answers your question. Thank you in advance Rayen

Thanks a lot Mr Dream-Math. It seems somehow to go in the right direction. I m not quite sure how to reach it but will keep the post updated

Hello Mr.Dream-math! I am also working on TVM-riscv, I am wondering what is the tgt in your code. Thank you!

Here is my tgt

tgt = "llvm -mtriple=riscv64-unknown-linux-gnu -mcpu=generic-rv64 -mfloat-abi=hard" 

you can add some additional attributes with -mattr, more details is here