Add supporting RISC-V cross compilation workflows

Add RISC-V cross-compilation test
Enable RVV support at compile time
This commit is contained in:
Alex Chiang 2023-04-27 01:40:15 -07:00 committed by Hans Kristian Rosbach
parent 9087c75f8d
commit c3cdf434f3
10 changed files with 165 additions and 1 deletions

View File

@ -378,6 +378,12 @@ jobs:
# https://github.com/llvm/llvm-project/issues/55785 # https://github.com/llvm/llvm-project/issues/55785
msan-options: use_sigaltstack=0 msan-options: use_sigaltstack=0
- name: Ubuntu Clang RISC-V
os: ubuntu-latest
cmake-args: -GNinja -DCMAKE_TOOLCHAIN_FILE=./cmake/toolchain-riscv.cmake -DTOOLCHAIN_PATH=${PWD}/prebuilt-riscv-toolchain-qemu/riscv-clang -DQEMU_PATH=${PWD}/prebuilt-riscv-toolchain-qemu/riscv-qemu/bin/qemu-riscv64
packages: build-essential cmake ninja-build
codecov: ubuntu_clang_toolchain_riscv
- name: Ubuntu Emscripten WASM32 - name: Ubuntu Emscripten WASM32
os: ubuntu-latest os: ubuntu-latest
chost: wasm32 chost: wasm32
@ -502,6 +508,14 @@ jobs:
sudo apt-get update sudo apt-get update
sudo apt-get install -y --allow-downgrades --no-install-recommends ${{ matrix.packages }} sudo apt-get install -y --allow-downgrades --no-install-recommends ${{ matrix.packages }}
- name: Download prebuilt RISC-V Clang toolchain & QEMU emulator
if: runner.os == 'Linux' && contains(matrix.name, 'RISC-V')
run: |
gh release download ubuntu20.04_llvm16.0.0_qemu7.0.0 --repo sifive/prepare-riscv-toolchain-qemu
tar zxvf prebuilt-riscv-toolchain-qemu.tar.gz
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Install packages (Windows) - name: Install packages (Windows)
if: runner.os == 'Windows' if: runner.os == 'Windows'
run: | run: |

View File

@ -105,6 +105,8 @@ elseif(BASEARCH_PPC_FOUND)
option(WITH_ALTIVEC "Build with AltiVec (VMX) optimisations for PowerPC" ON) option(WITH_ALTIVEC "Build with AltiVec (VMX) optimisations for PowerPC" ON)
option(WITH_POWER8 "Build with optimisations for POWER8" ON) option(WITH_POWER8 "Build with optimisations for POWER8" ON)
option(WITH_POWER9 "Build with optimisations for POWER9" ON) option(WITH_POWER9 "Build with optimisations for POWER9" ON)
elseif(BASEARCH_RISCV_FOUND)
option(WITH_RVV "Build with RVV intrinsics" ON)
elseif(BASEARCH_S360_FOUND) elseif(BASEARCH_S360_FOUND)
option(WITH_DFLTCC_DEFLATE "Build with DFLTCC intrinsics for compression on IBM Z" OFF) option(WITH_DFLTCC_DEFLATE "Build with DFLTCC intrinsics for compression on IBM Z" OFF)
option(WITH_DFLTCC_INFLATE "Build with DFLTCC intrinsics for decompression on IBM Z" OFF) option(WITH_DFLTCC_INFLATE "Build with DFLTCC intrinsics for decompression on IBM Z" OFF)
@ -135,6 +137,7 @@ mark_as_advanced(FORCE
WITH_ALTIVEC WITH_ALTIVEC
WITH_POWER8 WITH_POWER8
WITH_POWER9 WITH_POWER9
WITH_RVV
WITH_INFLATE_STRICT WITH_INFLATE_STRICT
WITH_INFLATE_ALLOW_INVALID_DIST WITH_INFLATE_ALLOW_INVALID_DIST
WITH_UNALIGNED WITH_UNALIGNED
@ -544,6 +547,8 @@ if(BASEARCH_ARM_FOUND)
set(ARCHDIR "arch/arm") set(ARCHDIR "arch/arm")
elseif(BASEARCH_PPC_FOUND) elseif(BASEARCH_PPC_FOUND)
set(ARCHDIR "arch/power") set(ARCHDIR "arch/power")
elseif(BASEARCH_RISCV_FOUND)
set(ARCHDIR "arch/riscv")
elseif(BASEARCH_S360_FOUND) elseif(BASEARCH_S360_FOUND)
set(ARCHDIR "arch/s390") set(ARCHDIR "arch/s390")
elseif(BASEARCH_X86_FOUND) elseif(BASEARCH_X86_FOUND)
@ -718,6 +723,18 @@ if(WITH_OPTIM)
set(WITH_POWER9 OFF) set(WITH_POWER9 OFF)
endif() endif()
endif() endif()
elseif(BASEARCH_RISCV_FOUND)
if(WITH_RVV)
check_rvv_intrinsics()
if(HAVE_RVV_INTRIN)
add_definitions(-DRISCV_FEATURES)
add_definitions(-DRISCV_RVV)
list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/riscv_features.h)
list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/riscv_features.c)
else()
set(WITH_RVV OFF)
endif()
endif()
elseif(BASEARCH_S360_FOUND) elseif(BASEARCH_S360_FOUND)
check_s390_intrinsics() check_s390_intrinsics()
if(HAVE_S390_INTRIN) if(HAVE_S390_INTRIN)
@ -1228,6 +1245,8 @@ elseif(BASEARCH_PPC_FOUND)
add_feature_info(WITH_ALTIVEC WITH_ALTIVEC "Build with AltiVec optimisations") add_feature_info(WITH_ALTIVEC WITH_ALTIVEC "Build with AltiVec optimisations")
add_feature_info(WITH_POWER8 WITH_POWER8 "Build with optimisations for POWER8") add_feature_info(WITH_POWER8 WITH_POWER8 "Build with optimisations for POWER8")
add_feature_info(WITH_POWER9 WITH_POWER9 "Build with optimisations for POWER9") add_feature_info(WITH_POWER9 WITH_POWER9 "Build with optimisations for POWER9")
elseif(BASEARCH_RISCV_FOUND)
add_feature_info(WITH_RVV WITH_RVV "Build with RVV intrinsics")
elseif(BASEARCH_S360_FOUND) elseif(BASEARCH_S360_FOUND)
add_feature_info(WITH_DFLTCC_DEFLATE WITH_DFLTCC_DEFLATE "Build with DFLTCC intrinsics for compression on IBM Z") add_feature_info(WITH_DFLTCC_DEFLATE WITH_DFLTCC_DEFLATE "Build with DFLTCC intrinsics for compression on IBM Z")
add_feature_info(WITH_DFLTCC_INFLATE WITH_DFLTCC_INFLATE "Build with DFLTCC intrinsics for decompression on IBM Z") add_feature_info(WITH_DFLTCC_INFLATE WITH_DFLTCC_INFLATE "Build with DFLTCC intrinsics for decompression on IBM Z")

View File

@ -34,7 +34,7 @@ Features
* Comprehensive set of CMake unit tests * Comprehensive set of CMake unit tests
* Code sanitizers, fuzzing, and coverage * Code sanitizers, fuzzing, and coverage
* GitHub Actions continuous integration on Windows, macOS, and Linux * GitHub Actions continuous integration on Windows, macOS, and Linux
* Emulated CI for ARM, AARCH64, PPC, PPC64, SPARC64, S390x using qemu * Emulated CI for ARM, AARCH64, PPC, PPC64, RISCV, SPARC64, S390x using qemu
History History
@ -221,6 +221,7 @@ Advanced Build Options
| WITH_NEON | --without-neon | Build with NEON intrinsics | ON | | WITH_NEON | --without-neon | Build with NEON intrinsics | ON |
| WITH_ALTIVEC | --without-altivec | Build with AltiVec (VMX) intrinsics | ON | | WITH_ALTIVEC | --without-altivec | Build with AltiVec (VMX) intrinsics | ON |
| WITH_POWER8 | --without-power8 | Build with POWER8 optimisations | ON | | WITH_POWER8 | --without-power8 | Build with POWER8 optimisations | ON |
| WITH_RVV | | Build with RVV intrinsics | ON |
| WITH_CRC32_VX | --without-crc32-vx | Build with vectorized CRC32 on IBM Z | ON | | WITH_CRC32_VX | --without-crc32-vx | Build with vectorized CRC32 on IBM Z | ON |
| WITH_DFLTCC_DEFLATE | --with-dfltcc-deflate | Build with DFLTCC intrinsics for compression on IBM Z | OFF | | WITH_DFLTCC_DEFLATE | --with-dfltcc-deflate | Build with DFLTCC intrinsics for compression on IBM Z | OFF |
| WITH_DFLTCC_INFLATE | --with-dfltcc-inflate | Build with DFLTCC intrinsics for decompression on IBM Z | OFF | | WITH_DFLTCC_INFLATE | --with-dfltcc-inflate | Build with DFLTCC intrinsics for decompression on IBM Z | OFF |

45
arch/riscv/README.md Normal file
View File

@ -0,0 +1,45 @@
# Building RISC-V Target with Cmake #
> **Warning**
> We cannot detect rvv support at runtime, running the rvv code on a no-rvv target is a risk. Users should disable the rvv when the target does not support it.
>
> We will have a better solution when the kernels update `hwcap` or `hwprobe` for risc-v.
## Prerequisite: Build RISC-V Clang Toolchain and QEMU ##
If you don't have prebuilt clang and riscv64 qemu, you can refer to the [script](https://github.com/sifive/prepare-riscv-toolchain-qemu/blob/main/prepare_riscv_toolchain_qemu.sh) to get the source. Copy the script to the zlib-ng root directory, and run it to download the source and build them. Modify the content according to your conditions (e.g., toolchain version).
```bash
./prepare_riscv_toolchain_qemu.sh
```
After running script, clang & qemu are built in `build-toolchain-qemu/riscv-clang/` & `build-toolchain-qemu/riscv-qemu/`.
`build-toolchain-qemu/riscv-clang/` is your `TOOLCHAIN_PATH`.
`build-toolchain-qemu/riscv-qemu/bin/qemu-riscv64` is your `QEMU_PATH`.
You can also download the prebuilt toolchain & qemu from [the release page](https://github.com/sifive/prepare-riscv-toolchain-qemu/releases), and enjoy using them.
## Cross-Compile for RISC-V Target ##
```bash
cmake -G Ninja -B ./build-riscv \
-D CMAKE_TOOLCHAIN_FILE=./cmake/toolchain-riscv.cmake \
-D CMAKE_INSTALL_PREFIX=./build-riscv/install \
-D TOOLCHAIN_PATH={TOOLCHAIN_PATH} \
-D QEMU_PATH={QEMU_PATH} \
.
cmake --build ./build-riscv
```
Disable the option if there is no RVV support:
```
-D WITH_RVV=OFF
```
## Run Unittests on User Mode QEMU ##
```bash
cd ./build-riscv && ctest --verbose
```

View File

@ -0,0 +1,15 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../../zbuild.h"
#include "riscv_features.h"
/* TODO: detect risc-v cpu info at runtime when the kernel updates hwcap or hwprobe for risc-v */
void Z_INTERNAL riscv_check_features(struct riscv_cpu_features *features) {
#if defined(__riscv_v) && defined(__linux__)
features->has_rvv = 1;
#else
features->has_rvv = 0;
#endif
}

View File

@ -0,0 +1,18 @@
/* riscv_features.h -- check for riscv features.
*
* Copyright (C) 2023 SiFive, Inc. All rights reserved.
* Contributed by Alex Chiang <alex.chiang@sifive.com>
*
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#ifndef RISCV_H_
#define RISCV_H_
struct riscv_cpu_features {
int has_rvv;
};
void Z_INTERNAL riscv_check_features(struct riscv_cpu_features *features);
#endif /* RISCV_H_ */

View File

@ -347,6 +347,24 @@ macro(check_power8_intrinsics)
set(CMAKE_REQUIRED_FLAGS) set(CMAKE_REQUIRED_FLAGS)
endmacro() endmacro()
macro(check_rvv_intrinsics)
if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang")
if(NOT NATIVEFLAG)
set(RISCVFLAG "-march=rv64gcv")
endif()
endif()
# Check whether compiler supports RVV
set(CMAKE_REQUIRED_FLAGS "${RISCVFLAG} ${NATIVEFLAG}")
check_c_source_compiles(
"#include <riscv_vector.h>
int main() {
return 0;
}"
HAVE_RVV_INTRIN
)
set(CMAKE_REQUIRED_FLAGS)
endmacro()
macro(check_s390_intrinsics) macro(check_s390_intrinsics)
check_c_source_compiles( check_c_source_compiles(
"#include <sys/auxv.h> "#include <sys/auxv.h>

View File

@ -0,0 +1,28 @@
set(CMAKE_CROSSCOMPILING TRUE)
set(CMAKE_SYSTEM_NAME "Linux")
set(CMAKE_SYSTEM_PROCESSOR "riscv64")
# Avoid to use system path for cross-compile
set(CMAKE_FIND_USE_CMAKE_SYSTEM_PATH FALSE)
set(TOOLCHAIN_PATH "" CACHE STRING "The toolchain path.")
if(NOT TOOLCHAIN_PATH)
set(TOOLCHAIN_PATH ${CMAKE_SOURCE_DIR}/prebuilt-riscv-toolchain-qemu/riscv-clang)
endif()
set(TOOLCHAIN_PREFIX "riscv64-unknown-linux-gnu-" CACHE STRING "The toolchain prefix.")
set(QEMU_PATH "" CACHE STRING "The qemu path.")
if(NOT QEMU_PATH)
set(QEMU_PATH ${CMAKE_SOURCE_DIR}/prebuilt-riscv-toolchain-qemu/riscv-qemu/bin/qemu-riscv64)
endif()
# toolchain setting
set(CMAKE_C_COMPILER "${TOOLCHAIN_PATH}/bin/${TOOLCHAIN_PREFIX}clang")
set(CMAKE_CXX_COMPILER "${TOOLCHAIN_PATH}/bin/${TOOLCHAIN_PREFIX}clang++")
# disable auto-vectorizer
add_compile_options(-fno-vectorize -fno-slp-vectorize)
# emulator setting
set(QEMU_CPU_OPTION "rv64,zba=true,zbb=true,zbc=true,zbs=true,v=true,vlen=512,elen=64,vext_spec=v1.0")
set(CMAKE_CROSSCOMPILING_EMULATOR ${QEMU_PATH} -cpu ${QEMU_CPU_OPTION} -L ${TOOLCHAIN_PATH}/sysroot/)

View File

@ -17,5 +17,7 @@ Z_INTERNAL void cpu_check_features(struct cpu_features *features) {
power_check_features(&features->power); power_check_features(&features->power);
#elif defined(S390_FEATURES) #elif defined(S390_FEATURES)
s390_check_features(&features->s390); s390_check_features(&features->s390);
#elif defined(RISCV_FEATURES)
riscv_check_features(&features->riscv);
#endif #endif
} }

View File

@ -18,6 +18,8 @@
# include "arch/power/power_features.h" # include "arch/power/power_features.h"
#elif defined(S390_FEATURES) #elif defined(S390_FEATURES)
# include "arch/s390/s390_features.h" # include "arch/s390/s390_features.h"
#elif defined(RISCV_FEATURES)
# include "arch/riscv/riscv_features.h"
#endif #endif
struct cpu_features { struct cpu_features {
@ -29,6 +31,8 @@ struct cpu_features {
struct power_cpu_features power; struct power_cpu_features power;
#elif defined(S390_FEATURES) #elif defined(S390_FEATURES)
struct s390_cpu_features s390; struct s390_cpu_features s390;
#elif defined(RISCV_FEATURES)
struct riscv_cpu_features riscv;
#else #else
char empty; char empty;
#endif #endif