Skip to content

Commit

Permalink
Add supporting RISC-V cross compilation workflows
Browse files Browse the repository at this point in the history
Add RISC-V cross-compilation test
Enable RVV support at compile time
  • Loading branch information
Alex Chiang authored and Dead2 committed May 12, 2023
1 parent 9087c75 commit c3cdf43
Show file tree
Hide file tree
Showing 10 changed files with 165 additions and 1 deletion.
14 changes: 14 additions & 0 deletions .github/workflows/cmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,12 @@ jobs:
# https://github.com/llvm/llvm-project/issues/55785
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
os: ubuntu-latest
chost: wasm32
Expand Down Expand Up @@ -502,6 +508,14 @@ jobs:
sudo apt-get update
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)
if: runner.os == 'Windows'
run: |
Expand Down
19 changes: 19 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ elseif(BASEARCH_PPC_FOUND)
option(WITH_ALTIVEC "Build with AltiVec (VMX) optimisations for PowerPC" ON)
option(WITH_POWER8 "Build with optimisations for POWER8" 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)
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)
Expand Down Expand Up @@ -135,6 +137,7 @@ mark_as_advanced(FORCE
WITH_ALTIVEC
WITH_POWER8
WITH_POWER9
WITH_RVV
WITH_INFLATE_STRICT
WITH_INFLATE_ALLOW_INVALID_DIST
WITH_UNALIGNED
Expand Down Expand Up @@ -544,6 +547,8 @@ if(BASEARCH_ARM_FOUND)
set(ARCHDIR "arch/arm")
elseif(BASEARCH_PPC_FOUND)
set(ARCHDIR "arch/power")
elseif(BASEARCH_RISCV_FOUND)
set(ARCHDIR "arch/riscv")
elseif(BASEARCH_S360_FOUND)
set(ARCHDIR "arch/s390")
elseif(BASEARCH_X86_FOUND)
Expand Down Expand Up @@ -718,6 +723,18 @@ if(WITH_OPTIM)
set(WITH_POWER9 OFF)
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)
check_s390_intrinsics()
if(HAVE_S390_INTRIN)
Expand Down Expand Up @@ -1228,6 +1245,8 @@ elseif(BASEARCH_PPC_FOUND)
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_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)
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")
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Features
* Comprehensive set of CMake unit tests
* Code sanitizers, fuzzing, and coverage
* 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
Expand Down Expand Up @@ -221,6 +221,7 @@ Advanced Build Options
| WITH_NEON | --without-neon | Build with NEON intrinsics | ON |
| WITH_ALTIVEC | --without-altivec | Build with AltiVec (VMX) intrinsics | 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_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 |
Expand Down
45 changes: 45 additions & 0 deletions arch/riscv/README.md
Original file line number Diff line number Diff line change
@@ -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
```
15 changes: 15 additions & 0 deletions arch/riscv/riscv_features.c
Original file line number Diff line number Diff line change
@@ -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
}
18 changes: 18 additions & 0 deletions arch/riscv/riscv_features.h
Original file line number Diff line number Diff line change
@@ -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_ */
18 changes: 18 additions & 0 deletions cmake/detect-intrinsics.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,24 @@ macro(check_power8_intrinsics)
set(CMAKE_REQUIRED_FLAGS)
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)
check_c_source_compiles(
"#include <sys/auxv.h>
Expand Down
28 changes: 28 additions & 0 deletions cmake/toolchain-riscv.cmake
Original file line number Diff line number Diff line change
@@ -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/)
2 changes: 2 additions & 0 deletions cpu_features.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,7 @@ Z_INTERNAL void cpu_check_features(struct cpu_features *features) {
power_check_features(&features->power);
#elif defined(S390_FEATURES)
s390_check_features(&features->s390);
#elif defined(RISCV_FEATURES)
riscv_check_features(&features->riscv);
#endif
}
4 changes: 4 additions & 0 deletions cpu_features.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
# include "arch/power/power_features.h"
#elif defined(S390_FEATURES)
# include "arch/s390/s390_features.h"
#elif defined(RISCV_FEATURES)
# include "arch/riscv/riscv_features.h"
#endif

struct cpu_features {
Expand All @@ -29,6 +31,8 @@ struct cpu_features {
struct power_cpu_features power;
#elif defined(S390_FEATURES)
struct s390_cpu_features s390;
#elif defined(RISCV_FEATURES)
struct riscv_cpu_features riscv;
#else
char empty;
#endif
Expand Down

0 comments on commit c3cdf43

Please sign in to comment.