Skip to content

Commit 6f56203

Browse files
committed
feat: Add rv64im runner for qemu and gh workflow (#22)
1 parent 6046d6a commit 6f56203

File tree

8 files changed

+555
-29
lines changed

8 files changed

+555
-29
lines changed
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
name: Qemu EESTs on RV64IM
2+
3+
on:
4+
schedule:
5+
- cron: "0 0 */3 * *" # Run every 3 days at midnight UTC
6+
workflow_dispatch:
7+
8+
jobs:
9+
build-and-run-rv64im:
10+
name: Build and Run EEST Tests RV64IM (Ubuntu 25.10)
11+
runs-on: ubuntu-latest
12+
container: ubuntu:25.10
13+
environment: ci
14+
steps:
15+
- name: Install system dependencies
16+
env:
17+
DEBIAN_FRONTEND: noninteractive
18+
TZ: Etc/UTC
19+
run: |
20+
apt update
21+
apt install -y \
22+
build-essential cmake ninja-build \
23+
git git-lfs \
24+
python3 python3-pip pipx \
25+
nodejs npm \
26+
qemu-system-misc
27+
pipx install conan
28+
pipx ensurepath
29+
npm i -g xpm
30+
xpm install @xpack-dev-tools/riscv-none-elf-gcc@latest --global --verbose
31+
echo 'export PATH=$HOME/.local/xPacks/@xpack-dev-tools/riscv-none-elf-gcc/15.2.0-1.1/.content/bin:$PATH' >> ~/.bashrc
32+
echo "PATH=$HOME/.local/xPacks/@xpack-dev-tools/riscv-none-elf-gcc/15.2.0-1.1/.content/bin:$PATH" >> $GITHUB_ENV
33+
34+
- name: Verify tool versions
35+
run: |
36+
riscv-none-elf-gcc --version
37+
riscv-none-elf-g++ --version
38+
cmake --version
39+
ninja --version
40+
git --version
41+
git lfs version
42+
python3 --version
43+
ctest --version
44+
qemu-system-riscv64 --version
45+
46+
- name: Checkout repository
47+
uses: actions/checkout@v4
48+
with:
49+
token: ${{ secrets.PAT_TOKEN }}
50+
submodules: recursive
51+
lfs: true
52+
53+
- name: Build EEST blockchain tests (RV64IM)
54+
run: |
55+
cd qemu_runner && make ARCH=rv64 xpack-elf-eest
56+
57+
- name: Run EEST blockchain tests (RV64IM)
58+
id: run_tests
59+
shell: bash
60+
run: |
61+
set +e
62+
cd qemu_runner
63+
make ARCH=rv64 rerun-ctest 2>&1 | tee output.log
64+
65+
exit_code=${PIPESTATUS[0]}
66+
67+
# Parse test results
68+
if grep -q "tests passed" output.log; then
69+
result_line=$(grep "tests passed" output.log | tail -1)
70+
# Extract numbers: "X% tests passed, Y tests failed out of Z"
71+
passed=$(echo "$result_line" | grep -oP '\d+(?=% tests passed)')
72+
failed=$(echo "$result_line" | grep -oP '\d+(?= tests failed)')
73+
total=$(echo "$result_line" | grep -oP '(?<=out of )\d+')
74+
75+
echo "passed_percent=$passed" >> $GITHUB_OUTPUT
76+
echo "failed=$failed" >> $GITHUB_OUTPUT
77+
echo "total=$total" >> $GITHUB_OUTPUT
78+
echo "exit_code=$exit_code" >> $GITHUB_OUTPUT
79+
else
80+
echo "passed_percent=0" >> $GITHUB_OUTPUT
81+
echo "failed=-1" >> $GITHUB_OUTPUT
82+
echo "total=0" >> $GITHUB_OUTPUT
83+
echo "exit_code=$exit_code" >> $GITHUB_OUTPUT
84+
fi
85+
86+
- name: Print test summary
87+
if: always()
88+
shell: bash
89+
run: |
90+
echo "========================================"
91+
echo " EEST TEST SUMMARY (RV64IM)"
92+
echo "========================================"
93+
echo ""
94+
echo "Results: ${{ steps.run_tests.outputs.passed_percent }}% passed, ${{ steps.run_tests.outputs.failed }} failed out of ${{ steps.run_tests.outputs.total }}"
95+
echo "========================================"
96+
97+
- name: Upload test logs
98+
if: always()
99+
uses: actions/upload-artifact@v4
100+
with:
101+
name: eest-test-logs-rv64im
102+
path: |
103+
qemu_runner/output.log
104+
qemu_runner/build64/Testing/Temporary/LastTest.log
105+
retention-days: 30
106+
107+
- name: Check failure threshold
108+
if: always()
109+
shell: bash
110+
run: |
111+
failed=${{ steps.run_tests.outputs.failed }}
112+
total=${{ steps.run_tests.outputs.total }}
113+
exit_code=${{ steps.run_tests.outputs.exit_code }}
114+
115+
if [[ "$failed" == "-1" ]]; then
116+
echo "ERROR: Could not parse test results"
117+
exit 1
118+
fi
119+
120+
if (( failed > 5 )); then
121+
echo "Too many failures - ${failed} failed out of ${total}"
122+
echo "failed" > failed.log
123+
exit 1
124+
fi
125+
126+
if (( failed > 0 )); then
127+
echo "WARNING: ${failed} test(s) failed, but within acceptable threshold (<=5)"
128+
else
129+
echo "SUCCESS: All ${total} tests passed!"
130+
fi

qemu_runner/CMakeLists.txt

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,27 @@
11
cmake_minimum_required(VERSION 3.16)
2-
project(SilkwormRV32Demo C CXX ASM)
2+
project(SilkwormRVDemo C CXX ASM)
33

44
set(CMAKE_CXX_STANDARD 23)
55
set(CMAKE_CXX_EXTENSIONS OFF)
66

7+
# ========== Architecture detection ==========
8+
# Detect based on CMAKE_SYSTEM_PROCESSOR set in toolchain file
9+
set(START_ASM "start.S" CACHE STRING "Assembly startup file")
10+
set(QEMU_SYSTEM "qemu-system-riscv32" CACHE STRING "QEMU system emulator")
11+
12+
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64")
13+
set(ARCH_RV64 TRUE)
14+
message(STATUS "Building for RISC-V 64-bit (rv64im)")
15+
if(NOT DEFINED START_ASM OR START_ASM STREQUAL "start.S")
16+
set(START_ASM "start64.S")
17+
endif()
18+
if(NOT DEFINED QEMU_SYSTEM OR QEMU_SYSTEM STREQUAL "qemu-system-riscv32")
19+
set(QEMU_SYSTEM "qemu-system-riscv64")
20+
endif()
21+
else()
22+
set(ARCH_RV64 FALSE)
23+
message(STATUS "Building for RISC-V 32-bit (rv32im)")
24+
endif()
725

826
set(SW_INSTALL_DIR ${CMAKE_BINARY_DIR}/zilkworm-install CACHE PATH "")
927
set(SW_INCLUDE_DIR ${SW_INSTALL_DIR}/include)
@@ -13,15 +31,15 @@ set(SW_INC_FALLBACK "${CMAKE_SOURCE_DIR}/..")
1331
set(SW_INC_INSTALL "${CMAKE_BINARY_DIR}/zilkworm-install/include")
1432

1533

16-
1734
# Make Conan package configs from the external build visible here
1835
if (EXISTS "${SW_CONAN_DIR}/conandeps_legacy.cmake")
1936
list(APPEND CMAKE_MODULE_PATH "${SW_CONAN_DIR}")
2037
list(APPEND CMAKE_PREFIX_PATH "${SW_CONAN_DIR}")
2138
include("${SW_CONAN_DIR}/conandeps_legacy.cmake")
2239
endif()
2340

24-
add_executable(z6m_debug src/sys_getentropy.c src/cppextern.cpp src/main.cpp src/start.S src/sys_sbrk_wrap.c)
41+
add_executable(z6m_debug src/sys_getentropy.c src/cppextern.cpp src/main.cpp src/${START_ASM} src/sys_sbrk_wrap.c)
42+
2543

2644

2745
add_library(silkworm_core STATIC IMPORTED GLOBAL)
@@ -127,7 +145,7 @@ if(TESTS_DIR)
127145
file(APPEND "${TEST_SCRIPT}" "set -e\n")
128146
file(APPEND "${TEST_SCRIPT}" "N=$(wc -c < '${TEST_JSON}')\n")
129147
file(APPEND "${TEST_SCRIPT}" "{ printf \"1 %u\\n\" $N; cat '${TEST_JSON}'; } > stdin_payload.bin\n")
130-
file(APPEND "${TEST_SCRIPT}" "exec qemu-system-riscv32 -M virt -m 2G -display none -bios '${CMAKE_CURRENT_BINARY_DIR}/z6m_debug' -monitor none -serial none -chardev file,id=shlog,path=semihost.log -semihosting-config enable=on,target=native,chardev=shlog\n")
148+
file(APPEND "${TEST_SCRIPT}" "exec ${QEMU_SYSTEM} -M virt -m 2G -display none -bios '${CMAKE_CURRENT_BINARY_DIR}/z6m_debug' -monitor none -serial none -chardev file,id=shlog,path=semihost.log -semihosting-config enable=on,target=native,chardev=shlog\n")
131149
file(CHMOD "${TEST_SCRIPT}" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE)
132150

133151
add_test(

qemu_runner/Makefile

Lines changed: 55 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,24 @@
1-
BUILD_DIR := $(CURDIR)/build
2-
ELF := $(BUILD_DIR)/z6m_debug
1+
# ========== Architecture selection ==========
2+
# Default to riscv32im, can be overridden: make ARCH=rv64
3+
ARCH ?= rv32
4+
5+
ifeq ($(ARCH),rv64)
6+
BUILD_DIR := $(CURDIR)/build64
7+
CONAN_PROFILE := $(CURDIR)/conan/profiles/riscv64im.conan.profile
8+
CMAKE_TOOLCHAIN := $(CURDIR)/cmake/riscv64im.cmake
9+
LINKER_SCRIPT := $(CURDIR)/qemu-xpack-64.ld
10+
QEMU_SYSTEM := qemu-system-riscv64
11+
START_ASM := start64.S
12+
else
13+
BUILD_DIR := $(CURDIR)/build
14+
CONAN_PROFILE := $(CURDIR)/conan/profiles/riscv32im.conan.profile
15+
CMAKE_TOOLCHAIN := $(CURDIR)/cmake/riscv32im.cmake
16+
LINKER_SCRIPT := $(CURDIR)/qemu-xpack.ld
17+
QEMU_SYSTEM := qemu-system-riscv32
18+
START_ASM := start.S
19+
endif
320

4-
CONAN_PROFILE = $(CURDIR)/conan/profiles/riscv32im.conan.profile
5-
CMAKE_TOOLCHAIN = $(CURDIR)/cmake/riscv32im.cmake
21+
ELF := $(BUILD_DIR)/z6m_debug
622

723
.PHONY: xpack-elf
824
xpack-elf: xpack-zilkworm
@@ -15,7 +31,8 @@ xpack-elf: xpack-zilkworm
1531
-DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE \
1632
-DCMAKE_VERBOSE_MAKEFILE=ON \
1733
-G "Unix Makefiles" \
18-
-DCMAKE_EXE_LINKER_FLAGS="-T$(CURDIR)/qemu-xpack.ld -z norelro" \
34+
-DCMAKE_EXE_LINKER_FLAGS="-T$(LINKER_SCRIPT) -z norelro" \
35+
-DSTART_ASM=$(START_ASM) \
1936
-Wno-dev
2037
cmake --build $(BUILD_DIR) -j --verbose
2138

@@ -46,7 +63,7 @@ rlp-qemu: xpack-elf
4663
@echo "QEMU waiting for GDB on :1234..."
4764
@N=$$(wc -c <"$(file-name)"); \
4865
{ printf "123456789_123456789_123456789_123"; printf "%u\n" $$N; cat "$(file-name)"; } | \
49-
qemu-system-riscv32 -M virt -m 2G -nographic \
66+
$(QEMU_SYSTEM) -M virt -m 2G -nographic \
5067
-bios $(ELF) -S -gdb tcp::1234 \
5168
-chardev stdio,mux=on,id=stdio0 \
5269
-serial chardev:stdio0 \
@@ -81,7 +98,9 @@ xpack-elf-eest: xpack-zilkworm-eest
8198
-DCMAKE_MESSAGE_LOG_LEVEL=VERBOSE \
8299
-DCMAKE_VERBOSE_MAKEFILE=ON \
83100
-G "Unix Makefiles" \
84-
-DCMAKE_EXE_LINKER_FLAGS="-T$(CURDIR)/qemu-xpack.ld -z norelro" \
101+
-DCMAKE_EXE_LINKER_FLAGS="-T$(LINKER_SCRIPT) -z norelro" \
102+
-DSTART_ASM=$(START_ASM) \
103+
-DQEMU_SYSTEM=$(QEMU_SYSTEM) \
85104
-DBUILD_TESTING=ON \
86105
-DTESTS_DIR=$(CURDIR)/../third_party/eest-fixtures/blockchain_tests \
87106
-Wno-dev
@@ -93,18 +112,18 @@ qemu-eest: xpack-elf-eest
93112
@if [ -z "$(file-name)" ]; then echo "Usage: make qemu-eest file-name=path/to.json"; exit 1; fi
94113
@N=$$(wc -c <"$(file-name)"); \
95114
{ printf "123456789_123456789_123456789_123"; printf "1 %u\n" $$N; cat "$(file-name)"; } | \
96-
qemu-system-riscv32 -M virt -m 2G -nographic \
115+
$(QEMU_SYSTEM) -M virt -m 2G -nographic \
97116
-bios $(BUILD_DIR)/z6m_debug \
98117
-chardev stdio,mux=on,id=stdio0 \
99118
-serial chardev:stdio0 \
100119
-semihosting-config enable=on,chardev=stdio0 \
101120
-mon chardev=stdio0,mode=readline
102121

103-
rv32im_eest_blockchain_tests: xpack-elf-eest
104-
ctest --test-dir build --parallel --output-on-failure
122+
eest-blockchain-tests: xpack-elf-eest
123+
ctest --test-dir $(BUILD_DIR) --parallel --output-on-failure
105124

106-
rerun_ctest:
107-
ctest --test-dir build --parallel --output-on-failure -V --timeout 7200
125+
rerun-ctest:
126+
ctest --test-dir $(BUILD_DIR) --parallel --output-on-failure -V --timeout 7200
108127

109128
# rerun-qemu-eest:
110129
# @if [ -z "$(file-name)" ]; then echo "Usage: make qemu-eest file-name=path/to.json"; exit 1; fi
@@ -149,15 +168,35 @@ rerun-qemu-eest:
149168
@N=$$(wc -c <"$(file-name)"); \
150169
rm -f semihost.log serial.log; \
151170
{ printf "1 %u\n" $$N; cat "$(file-name)"; } > stdin_payload.bin; \
152-
qemu-system-riscv32 -M virt -m 2G -display none \
171+
$(QEMU_SYSTEM) -M virt -m 2G -display none \
153172
-bios $(BUILD_DIR)/z6m_debug \
154173
-monitor none \
155174
-serial none \
156175
-chardev file,id=shlog,path=semihost.log \
157176
-semihosting-config enable=on,target=native,chardev=shlog
158177

159178

160-
# # Clean build artifacts
161-
.PHONY: clean
179+
# ========== Convenience targets for specific architectures ==========
180+
.PHONY: xpack-elf-eest-rv32 xpack-elf-eest-rv64 eest-rv32 eest-rv64
181+
182+
# RV32 specific targets
183+
xpack-elf-eest-rv32:
184+
$(MAKE) ARCH=rv32 xpack-elf-eest
185+
186+
eest-rv32:
187+
$(MAKE) ARCH=rv32 eest-blockchain-tests
188+
189+
# RV64 specific targets
190+
xpack-elf-eest-rv64:
191+
$(MAKE) ARCH=rv64 xpack-elf-eest
192+
193+
eest-rv64:
194+
$(MAKE) ARCH=rv64 eest-blockchain-tests
195+
196+
# Clean build artifacts
197+
.PHONY: clean clean-all
162198
clean:
163-
rm -rf $(BUILD_DIR)
199+
rm -rf $(BUILD_DIR)
200+
201+
clean-all:
202+
rm -rf $(CURDIR)/build $(CURDIR)/build64

qemu_runner/cmake/riscv64im.cmake

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# riscv64im-toolchain.cmake
2+
set(CMAKE_SYSTEM_NAME Generic) # No OS (bare-metal target)
3+
set(CMAKE_SYSTEM_PROCESSOR riscv64) # Target CPU architecture
4+
5+
# Cross-compiler executables
6+
set(CMAKE_C_COMPILER riscv-none-elf-gcc)
7+
set(CMAKE_CXX_COMPILER riscv-none-elf-g++)
8+
set(CMAKE_ASM_COMPILER riscv-none-elf-gcc)
9+
10+
11+
# set(GMP_LIBRARY "${CMAKE_SOURCE_DIR}/../prelibs/gmp")
12+
# set(GMP_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/../prelibs/gmp")
13+
set(BUILD_SHARED_LIBS "OFF")
14+
15+
# set(debug_flags "-Os")
16+
set(debug_flags "-O0 -g3")
17+
set(common_flags "-march=rv64im -mabi=lp64 -mcmodel=medany -ffunction-sections -fdata-sections -fPIC") #"-ffreestanding"
18+
set(CMAKE_C_FLAGS "${common_flags} -D_GLIBCXX_HAS_GTHREADS=0")
19+
set(CMAKE_CXX_FLAGS "${common_flags} ${debug_flags} -fno-exceptions -fno-rtti -fno-threadsafe-statics ") # "-nostdlib"
20+
set(CMAKE_ASM_FLAGS "${common_flags} ${debug_flags}")
21+
22+
23+
set(BUILD_TESTING OFF CACHE BOOL "Disable Silkworm tests")
24+
set(SILKWORM_WASM_API OFF CACHE BOOL "No WASM for bare-metal")
25+
26+
set(LIBFF_WITH_GMP "OFF")
27+
set(CATCH_BUILD_TESTING "OFF")
28+
set(SILKWORM_CORE_USE_ABSEIL "OFF")
29+
set(CMAKE_PREFIX_PATH "${CONAN_INSTALL_FOLDER}")
30+
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
31+
# It clashes with double inclusion if declared here
32+
# set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -T${CMAKE_SOURCE_DIR}/qemu-xpack.ld -z norelro") # -nostartfiles"
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
[settings]
2+
os=baremetal
3+
arch=riscv64
4+
compiler=gcc
5+
compiler.version=15
6+
compiler.libcxx=libstdc++11
7+
compiler.cppstd=gnu23
8+
build_type=Release
9+
10+
[conf]
11+
tools.build:compiler_executables={"c": "riscv-none-elf-gcc","cpp": "riscv-none-elf-g++", "ar":"riscv-none-elf-ar"}
12+
tools.build:cflags=["-march=rv64im","-mabi=lp64","-mcmodel=medany"]
13+
tools.build:cxxflags=["-march=rv64im","-mabi=lp64","-mcmodel=medany"]
14+
tools.build:sharedlinkflags=["-march=rv64im","-mabi=lp64","-Wl,--gc-sections"]
15+
16+
[buildenv]
17+
CC=riscv-none-elf-gcc
18+
CXX=riscv-none-elf-g++
19+
AR=riscv-none-elf-ar
20+
RANLIB=riscv-none-elf-ranlib
21+
22+
[options]
23+
*:shared=False

0 commit comments

Comments
 (0)