| # Getting Started on RISC-V with CMake | |
| <!-- | |
| Notes to those updating this guide: | |
| * This document should be __simple__ and cover essential items only. | |
| Notes for optional components should go in separate files. | |
| --> | |
| This guide walks through cross-compiling IREE core runtime towards the RISC-V | |
| Linux platform. Cross-compiling IREE compilers towards RISC-V is not supported | |
| at the moment. | |
| Cross-compilation involves both a *host* platform and a *target* platform. One | |
| invokes compiler toolchains on the host platform to generate libraries and | |
| executables that can be run on the target platform. | |
| ## Prerequisites | |
| You'll need a RISC-V LLVM compilation toolchain and a RISC-V enabled QEMU | |
| emulator. | |
| * RISC-V toolchain is built from https://github.com/llvm/llvm-project (main branch).<br> | |
| * Currently, the LLVM compiler is built on GNU toolchain, including libgcc, | |
| GNU linker, and C libraries. You need to build GNU toolchain first.<br> | |
| * Clone GNU toolchain from: https://github.com/riscv/riscv-gnu-toolchain | |
| (master branch). Switch the "riscv-binutils" submodule to `rvv-1.0.x-zfh` | |
| branch manually. | |
| * RISC-V QEMU is built from https://github.com/sifive/qemu/tree/v5.2.0-rvv-rvb-zfh | |
| An environment variable `RISCV_TOOLCHAIN_ROOT` needs | |
| to be set to the root directory of the installed GNU toolchain. The variable can | |
| be used in building the RISCV target and a LLVM AOT module. | |
| ### Install Prebuilt RISC-V Tools (RISC-V 64-bit Linux toolchain) | |
| Execute the following script to download the prebuilt RISC-V toolchain and QEMU: | |
| ```shell | |
| # In IREE source root | |
| $ ./build_tools/riscv/riscv_bootstrap.sh | |
| ``` | |
| **NOTE**: | |
| * You also need to set `RISCV_TOOLCHAIN_ROOT` | |
| (default at ${HOME}/riscv/toolchain/clang/linux/RISCV). | |
| ## Configure and build | |
| ### Host configuration | |
| Build and install at least the compiler tools on your host machine, or install | |
| them from a binary distribution: | |
| ```shell | |
| $ cmake -G Ninja -B ../iree-build-host/ \ | |
| -DCMAKE_C_COMPILER=clang \ | |
| -DCMAKE_CXX_COMPILER=clang++ \ | |
| -DCMAKE_INSTALL_PREFIX=../iree-build-host/install \ | |
| . | |
| $ cmake --build ../iree-build-host/ --target install | |
| ``` | |
| ### Target configuration | |
| The following instruction shows how to build for the RISC-V 64-bit Linux machine | |
| and 32-bit bare-metal machine. For other RISC-V targets, please refer to | |
| [riscv.toolchain.cmake](https://github.com/google/iree/blob/main/build_tools/cmake/riscv.toolchain.cmake) | |
| as a reference of how to set up the cmake configuration. | |
| #### RISC-V 64-bit Linux target | |
| ```shell | |
| $ cmake -G Ninja -B ../iree-build-riscv/ \ | |
| -DCMAKE_TOOLCHAIN_FILE="./build_tools/cmake/riscv.toolchain.cmake" \ | |
| -DIREE_HOST_BINARY_ROOT=$(realpath ../iree-build-host/install) \ | |
| -DRISCV_CPU=rv64 \ | |
| -DIREE_BUILD_COMPILER=OFF \ | |
| -DIREE_BUILD_SAMPLES=ON \ | |
| -DRISCV_TOOLCHAIN_ROOT=${RISCV_TOOLCHAIN_ROOT} \ | |
| . | |
| ``` | |
| #### RISC-V 32-bit bare-metal target | |
| For the RISC-V 32-bit bare-metal config, append the following CMake options | |
| ```shell | |
| -DRISCV_CPU=rv32-baremetal \ | |
| -DIREE_BUILD_TESTS=OFF | |
| ``` | |
| #### Build target | |
| ```shell | |
| $ cmake --build ../iree-build-riscv/ | |
| ``` | |
| ## Test on RISC-V QEMU | |
| **NOTE**:The following instructions are meant for the RISC-V 64-bit Linux | |
| target. For the bare-metal target, please refer to | |
| [simple_embedding](https://github.com/google/iree/blob/main/iree/samples/simple_embedding) | |
| to see how to build a ML workload for a bare-metal machine. | |
| Set the environment variable `RISCV_TOOLCHAIN_ROOT` if it is not set yet: | |
| ```shell | |
| $ export RISCV_TOOLCHAIN_ROOT=<root directory of the RISC-V GNU toolchain> | |
| ``` | |
| ### VMVX HAL backend | |
| Translate a source MLIR into IREE module: | |
| ```shell | |
| $ ../iree-build-host/install/bin/iree-translate \ | |
| -iree-mlir-to-vm-bytecode-module \ | |
| -iree-hal-target-backends=vmvx \ | |
| ${PWD}/iree/samples/models/simple_abs.mlir \ | |
| -o /tmp/simple_abs_vmvx.vmfb | |
| ``` | |
| Then run on the RISC-V QEMU: | |
| Set the path to qemu-riscv64 emulator binary in the `QEMU_BIN` environment | |
| variable. If it is installed with `riscv_bootstrap.sh`, the path is default at | |
| ${HOME}/riscv/qemu/linux/RISCV/bin/qemu-riscv64. | |
| ```shell | |
| $ export QEMU_BIN=<path to qemu-riscv64 binary> | |
| ``` | |
| ```shell | |
| $ ${QEMU_BIN} \ | |
| -cpu rv64,x-v=true,x-k=true,vlen=256,elen=64,vext_spec=v1.0 \ | |
| -L ${RISCV_TOOLCHAIN_ROOT}/sysroot/ \ | |
| ../iree-build-riscv/iree/tools/iree-run-module \ | |
| --driver=vmvx \ | |
| --module_file=/tmp/simple_abs_vmvx.vmfb \ | |
| --entry_function=abs \ | |
| --function_input=f32=-5 | |
| ``` | |
| Output: | |
| ``` | |
| I ../iree/tools/utils/vm_util.cc:227] Creating driver and device for 'vmvx'... | |
| EXEC @abs | |
| f32=5 | |
| ``` | |
| ### Dylib LLVM AOT backend | |
| To compile an IREE module using the Dylib LLVM ahead-of-time (AOT) backend for | |
| a RISC-V target we need to use the corresponding cross-compile toolchain. | |
| Translate a source MLIR into an IREE module: | |
| ```shell | |
| $ ../iree-build-host/install/bin/iree-translate \ | |
| -iree-mlir-to-vm-bytecode-module \ | |
| -iree-hal-target-backends=dylib-llvm-aot \ | |
| -iree-llvm-target-triple=riscv64 \ | |
| -iree-llvm-target-cpu=sifive-u74 \ | |
| -iree-llvm-target-abi=lp64d \ | |
| ${PWD}/iree/samples/models/simple_abs.mlir \ | |
| -o /tmp/simple_abs_dylib.vmfb | |
| ``` | |
| Then run on the RISC-V QEMU: | |
| ```shell | |
| $ ${QEMU_BIN} \ | |
| -cpu rv64,x-v=true,x-k=true,vlen=256,elen=64,vext_spec=v1.0 \ | |
| -L ${RISCV_TOOLCHAIN_ROOT}/sysroot/ \ | |
| ../iree-build-riscv/iree/tools/iree-run-module \ | |
| --driver=dylib \ | |
| --module_file=/tmp/simple_abs_dylib.vmfb \ | |
| --entry_function=abs \ | |
| --function_input=f32=-5 | |
| ``` | |
| Output: | |
| ``` | |
| I ../iree/tools/utils/vm_util.cc:227] Creating driver and device for 'dylib'... | |
| EXEC @abs | |
| f32=5 | |
| ``` | |
| #### Enable RVV code-gen [Experimental] | |
| Through IREE's vectorization pass and LLVM backend, we can generate RVV | |
| VLS(Vector Length Specific) style codes. | |
| ```shell | |
| $ ../iree-build-host/install/bin/iree-translate \ | |
| -iree-mlir-to-vm-bytecode-module \ | |
| -iree-hal-target-backends=dylib-llvm-aot \ | |
| -iree-input-type=mhlo \ | |
| -iree-llvm-target-triple=riscv64 \ | |
| -iree-llvm-target-cpu=sifive-7-rv64 \ | |
| -iree-llvm-target-abi=lp64d \ | |
| -iree-llvm-target-cpu-features="+m,+a,+d,+experimental-v" \ | |
| -riscv-v-vector-bits-min=256 -riscv-v-fixed-length-vector-lmul-max=8 \ | |
| ${PWD}/iree/samples/simple_embedding/simple_embedding_test.mlir -o /tmp/output-rvv.vmfb | |
| ``` | |
| Then run on the RISC-V QEMU: | |
| ```shell | |
| $ ${QEMU_BIN} \ | |
| -cpu rv64,x-v=true,x-k=true,vlen=256,elen=64,vext_spec=v1.0 \ | |
| -L ${RISCV_TOOLCHAIN_ROOT}/sysroot/ \ | |
| ../iree-build-riscv/iree/tools/iree-run-module --driver=dylib \ | |
| --driver=dylib \ | |
| --module_file=/tmp/output-rvv.vmfb \ | |
| --entry_function=simple_mul \ | |
| --function_input="4xf32=[1 2 3 4]" \ | |
| --function_input="4xf32=[2 4 6 8]" | |
| ``` |