Skip to content

Commit 833fc0a

Browse files
authored
Merge pull request #1037 from pq-code-package/rv64v-dev
Add RISCV64 RVV backend
2 parents b555f31 + 50d4992 commit 833fc0a

File tree

24 files changed

+1701
-11
lines changed

24 files changed

+1701
-11
lines changed

.clang-format

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ IncludeBlocks: Preserve
1717
# as "attributes" so they don't get increasingly indented line after line
1818
BreakBeforeBraces: Allman
1919
InsertBraces: true
20-
WhitespaceSensitiveMacros: ['__contract__', '__loop__' ]
20+
WhitespaceSensitiveMacros: ['__contract__', '__loop__', 'MLK_RV64V_ABS_BOUNDS16' ]
2121
Macros:
2222
# Make this artifically long to avoid function bodies after short contracts
2323
- __contract__(x)={ void a; void b; void c; void d; void e; void f; } void abcdefghijklmnopqrstuvw()

.github/actions/multi-functest/action.yml

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ runs:
150150
check_namespace: ${{ inputs.check_namespace }}
151151
stack: ${{ inputs.stack }}
152152
extra_args: ${{ inputs.extra_args }}
153-
- name: Cross riscv64 Tests
153+
- name: Cross riscv64 Tests (RVV, VLEN=128)
154154
if: ${{ (inputs.compile_mode == 'all' || inputs.compile_mode == 'cross-riscv64') && (success() || failure()) }}
155155
uses: ./.github/actions/functest
156156
with:
@@ -161,7 +161,67 @@ runs:
161161
custom_shell: ${{ inputs.custom_shell }}
162162
cflags: "${{ inputs.cflags }} -DMLK_FORCE_RISCV64"
163163
cross_prefix: riscv64-unknown-linux-gnu-
164-
exec_wrapper: qemu-riscv64
164+
exec_wrapper: "qemu-riscv64 -cpu rv64,v=true,vlen=128"
165+
opt: ${{ inputs.opt }}
166+
func: ${{ inputs.func }}
167+
kat: ${{ inputs.kat }}
168+
acvp: ${{ inputs.acvp }}
169+
examples: ${{ inputs.examples }}
170+
check_namespace: ${{ inputs.check_namespace }}
171+
stack: ${{ inputs.stack }}
172+
extra_args: ${{ inputs.extra_args }}
173+
- name: Cross riscv64 Tests (RVV, VLEN=256)
174+
if: ${{ (inputs.compile_mode == 'all' || inputs.compile_mode == 'cross-riscv64') && (success() || failure()) }}
175+
uses: ./.github/actions/functest
176+
with:
177+
nix-shell: ${{ inputs.nix-shell }}
178+
nix-cache: ${{ inputs.nix-cache }}
179+
nix-verbose: ${{ inputs.nix-verbose }}
180+
gh_token: ${{ inputs.gh_token }}
181+
custom_shell: ${{ inputs.custom_shell }}
182+
cflags: "${{ inputs.cflags }} -DMLK_FORCE_RISCV64"
183+
cross_prefix: riscv64-unknown-linux-gnu-
184+
exec_wrapper: "qemu-riscv64 -cpu rv64,v=true,vlen=256"
185+
opt: ${{ inputs.opt }}
186+
func: ${{ inputs.func }}
187+
kat: ${{ inputs.kat }}
188+
acvp: ${{ inputs.acvp }}
189+
examples: ${{ inputs.examples }}
190+
check_namespace: ${{ inputs.check_namespace }}
191+
stack: ${{ inputs.stack }}
192+
extra_args: ${{ inputs.extra_args }}
193+
- name: Cross riscv64 Tests (RVV, VLEN=512)
194+
if: ${{ (inputs.compile_mode == 'all' || inputs.compile_mode == 'cross-riscv64') && (success() || failure()) }}
195+
uses: ./.github/actions/functest
196+
with:
197+
nix-shell: ${{ inputs.nix-shell }}
198+
nix-cache: ${{ inputs.nix-cache }}
199+
nix-verbose: ${{ inputs.nix-verbose }}
200+
gh_token: ${{ inputs.gh_token }}
201+
custom_shell: ${{ inputs.custom_shell }}
202+
cflags: "${{ inputs.cflags }} -DMLK_FORCE_RISCV64"
203+
cross_prefix: riscv64-unknown-linux-gnu-
204+
exec_wrapper: "qemu-riscv64 -cpu rv64,v=true,vlen=512"
205+
opt: ${{ inputs.opt }}
206+
func: ${{ inputs.func }}
207+
kat: ${{ inputs.kat }}
208+
acvp: ${{ inputs.acvp }}
209+
examples: ${{ inputs.examples }}
210+
check_namespace: ${{ inputs.check_namespace }}
211+
stack: ${{ inputs.stack }}
212+
extra_args: ${{ inputs.extra_args }}
213+
- name: Cross riscv64 Tests (RVV, VLEN=1024)
214+
if: ${{ (inputs.compile_mode == 'all' || inputs.compile_mode == 'cross-riscv64') && (success() || failure()) }}
215+
uses: ./.github/actions/functest
216+
with:
217+
nix-shell: ${{ inputs.nix-shell }}
218+
nix-cache: ${{ inputs.nix-cache }}
219+
nix-verbose: ${{ inputs.nix-verbose }}
220+
gh_token: ${{ inputs.gh_token }}
221+
custom_shell: ${{ inputs.custom_shell }}
222+
cflags: "${{ inputs.cflags }} -DMLK_FORCE_RISCV64"
223+
cross_prefix: riscv64-unknown-linux-gnu-
224+
exec_wrapper: "qemu-riscv64 -cpu rv64,v=true,vlen=1024"
165225
opt: ${{ inputs.opt }}
166226
func: ${{ inputs.func }}
167227
kat: ${{ inputs.kat }}

.github/workflows/ci.yml

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,23 +134,43 @@ jobs:
134134
runs-on: ${{ matrix.target.runner }}
135135
steps:
136136
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
137-
- name: build + test
137+
- name: build + test (no-opt)
138138
uses: ./.github/actions/multi-functest
139139
with:
140140
nix-shell: ${{ matrix.target.nix_shell }}
141141
nix-cache: ${{ matrix.target.mode == 'native' && 'false' || 'true' }}
142142
gh_token: ${{ secrets.GITHUB_TOKEN }}
143143
compile_mode: ${{ matrix.target.mode }}
144-
# There is no native code yet on PPC64LE, R-V or AArch64_be, so no point running opt tests
145-
opt: ${{ (matrix.target.arch != 'ppc64le' && matrix.target.arch != 'riscv64' && matrix.target.arch != 'riscv32' && matrix.target.arch != 'aarch64_be') && 'all' || 'no_opt' }}
146-
- name: build + test (+debug+memsan+ubsan)
144+
opt: 'no_opt'
145+
- name: build + test (+debug+memsan+ubsan, native)
147146
uses: ./.github/actions/multi-functest
148147
if: ${{ matrix.target.mode == 'native' }}
149148
with:
150149
gh_token: ${{ secrets.GITHUB_TOKEN }}
151150
compile_mode: native
152151
cflags: "-DMLKEM_DEBUG -fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all"
153152
check_namespace: 'false'
153+
- name: build + test (cross, opt)
154+
uses: ./.github/actions/multi-functest
155+
# There is no native code yet on PPC64LE, riscv32 or AArch64_be, so no point running opt tests
156+
if: ${{ matrix.target.mode != 'native' && (matrix.target.arch != 'ppc64le' && matrix.target.arch != 'riscv32' && matrix.target.arch != 'aarch64_be') }}
157+
with:
158+
nix-shell: ${{ matrix.target.nix_shell }}
159+
nix-cache: ${{ matrix.target.mode == 'native' && 'false' || 'true' }}
160+
gh_token: ${{ secrets.GITHUB_TOKEN }}
161+
compile_mode: ${{ matrix.target.mode }}
162+
opt: 'opt'
163+
- name: build + test (cross, opt, +debug)
164+
uses: ./.github/actions/multi-functest
165+
# There is no native code yet on PPC64LE, riscv32 or AArch64_be, so no point running opt tests
166+
if: ${{ matrix.target.mode != 'native' && (matrix.target.arch != 'ppc64le' && matrix.target.arch != 'riscv32' && matrix.target.arch != 'aarch64_be') }}
167+
with:
168+
nix-shell: ${{ matrix.target.nix_shell }}
169+
nix-cache: ${{ matrix.target.mode == 'native' && 'false' || 'true' }}
170+
gh_token: ${{ secrets.GITHUB_TOKEN }}
171+
compile_mode: ${{ matrix.target.mode }}
172+
cflags: "-DMLKEM_DEBUG"
173+
opt: 'opt'
154174
backend_tests:
155175
name: AArch64 FIPS202 backends (${{ matrix.backend }})
156176
strategy:

examples/monolithic_build_multilevel_native/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ else ifneq ($(findstring aarch64_be, $(CROSS_PREFIX)),)
7777
else ifneq ($(findstring aarch64, $(CROSS_PREFIX)),)
7878
CFLAGS += -DMLK_FORCE_AARCH64
7979
else ifneq ($(findstring riscv64, $(CROSS_PREFIX)),)
80+
CFLAGS += -march=rv64gcv
8081
CFLAGS += -DMLK_FORCE_RISCV64
8182
else ifneq ($(findstring riscv32, $(CROSS_PREFIX)),)
8283
CFLAGS += -DMLK_FORCE_RISCV32

examples/monolithic_build_native/Makefile

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,41 @@ LIB1024=libmlkem1024.a
6060

6161
MLK_OBJS=$(BUILD_DIR)/mlkem_native.c.o $(BUILD_DIR)/mlkem_native.S.o
6262

63+
# Automatically detect system architecture and set preprocessor etc accordingly
64+
HOST_PLATFORM := $(shell uname -s)-$(shell uname -m)
65+
66+
# linux x86_64
67+
ifeq ($(HOST_PLATFORM),Linux-x86_64)
68+
CFLAGS += -z noexecstack
69+
endif
70+
71+
# Native compilation
72+
ifeq ($(CROSS_PREFIX),)
73+
ifeq ($(HOST_PLATFORM),Linux-x86_64)
74+
CFLAGS += -mavx2 -mbmi2 -mpopcnt -maes
75+
CFLAGS += -DMLK_FORCE_X86_64
76+
else ifeq ($(HOST_PLATFORM),Linux-aarch64)
77+
CFLAGS += -DMLK_FORCE_AARCH64
78+
else ifeq ($(HOST_PLATFORM),Darwin-arm64)
79+
CFLAGS += -DMLK_FORCE_AARCH64
80+
endif
81+
# Cross compilation
82+
else ifneq ($(findstring x86_64, $(CROSS_PREFIX)),)
83+
CFLAGS += -mavx2 -mbmi2 -mpopcnt -maes
84+
CFLAGS += -DMLK_FORCE_X86_64
85+
else ifneq ($(findstring aarch64_be, $(CROSS_PREFIX)),)
86+
CFLAGS += -DMLK_FORCE_AARCH64_EB
87+
else ifneq ($(findstring aarch64, $(CROSS_PREFIX)),)
88+
CFLAGS += -DMLK_FORCE_AARCH64
89+
else ifneq ($(findstring riscv64, $(CROSS_PREFIX)),)
90+
CFLAGS += -march=rv64gcv
91+
CFLAGS += -DMLK_FORCE_RISCV64
92+
else ifneq ($(findstring riscv32, $(CROSS_PREFIX)),)
93+
CFLAGS += -DMLK_FORCE_RISCV32
94+
else ifneq ($(findstring powerpc64le, $(CROSS_PREFIX)),)
95+
CFLAGS += -DMLK_FORCE_PPC64LE
96+
endif
97+
6398
CFLAGS := \
6499
-Wall \
65100
-Wextra \

examples/multilevel_build_native/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ else ifneq ($(findstring aarch64_be, $(CROSS_PREFIX)),)
4444
else ifneq ($(findstring aarch64, $(CROSS_PREFIX)),)
4545
CFLAGS += -DMLK_FORCE_AARCH64
4646
else ifneq ($(findstring riscv64, $(CROSS_PREFIX)),)
47+
CFLAGS += -march=rv64gcv
4748
CFLAGS += -DMLK_FORCE_RISCV64
4849
else ifneq ($(findstring riscv32, $(CROSS_PREFIX)),)
4950
CFLAGS += -DMLK_FORCE_RISCV32

mlkem/mlkem_native.S

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@
8585
#include "mlkem/src/native/x86_64/src/rej_uniform_asm.S"
8686
#include "mlkem/src/native/x86_64/src/tomont.S"
8787
#endif /* MLK_SYS_X86_64 */
88+
#if defined(MLK_SYS_RISCV64)
89+
#endif
8890
#endif /* MLK_CONFIG_USE_NATIVE_BACKEND_ARITH */
8991

9092
#if defined(MLK_CONFIG_USE_NATIVE_BACKEND_FIPS202)
@@ -344,6 +346,7 @@
344346
#undef MLK_SYS_PPC64LE
345347
#undef MLK_SYS_RISCV32
346348
#undef MLK_SYS_RISCV64
349+
#undef MLK_SYS_RISCV64_RVV
347350
#undef MLK_SYS_WINDOWS
348351
#undef MLK_SYS_X86_64
349352
#undef MLK_SYS_X86_64_AVX2
@@ -552,5 +555,40 @@
552555
#undef MLK_NATIVE_X86_64_SRC_CONSTS_H
553556
#undef mlk_qdata
554557
#endif /* MLK_SYS_X86_64 */
558+
#if defined(MLK_SYS_RISCV64)
559+
/*
560+
* Undefine macros from native code (Arith, RISC-V 64)
561+
*/
562+
/* mlkem/src/native/riscv64/meta.h */
563+
#undef MLK_ARITH_BACKEND_RISCV64
564+
#undef MLK_NATIVE_RISCV64_META_H
565+
#undef MLK_USE_NATIVE_INTT
566+
#undef MLK_USE_NATIVE_NTT
567+
#undef MLK_USE_NATIVE_POLYVEC_BASEMUL_ACC_MONTGOMERY_CACHED
568+
#undef MLK_USE_NATIVE_POLY_MULCACHE_COMPUTE
569+
#undef MLK_USE_NATIVE_POLY_REDUCE
570+
#undef MLK_USE_NATIVE_POLY_TOMONT
571+
#undef MLK_USE_NATIVE_REJ_UNIFORM
572+
/* mlkem/src/native/riscv64/src/arith_native_riscv64.h */
573+
#undef MLK_NATIVE_RISCV64_SRC_ARITH_NATIVE_RISCV64_H
574+
#undef mlk_rv64v_poly_add
575+
#undef mlk_rv64v_poly_basemul_mont_add_k2
576+
#undef mlk_rv64v_poly_basemul_mont_add_k3
577+
#undef mlk_rv64v_poly_basemul_mont_add_k4
578+
#undef mlk_rv64v_poly_invntt_tomont
579+
#undef mlk_rv64v_poly_ntt
580+
#undef mlk_rv64v_poly_reduce
581+
#undef mlk_rv64v_poly_sub
582+
#undef mlk_rv64v_poly_tomont
583+
#undef mlk_rv64v_rej_uniform
584+
/* mlkem/src/native/riscv64/src/rv64v_debug.h */
585+
#undef MLK_NATIVE_RISCV64_SRC_RV64V_DEBUG_H
586+
#undef mlk_assert_abs_bound_int16m1
587+
#undef mlk_assert_abs_bound_int16m2
588+
#undef mlk_assert_bound_int16m1
589+
#undef mlk_assert_bound_int16m2
590+
#undef mlk_debug_check_bounds_int16m1
591+
#undef mlk_debug_check_bounds_int16m2
592+
#endif /* MLK_SYS_RISCV64 */
555593
#endif /* MLK_CONFIG_USE_NATIVE_BACKEND_ARITH */
556594
#endif /* !MLK_CONFIG_MONOBUILD_KEEP_SHARED_HEADERS */

mlkem/mlkem_native.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@
8484
#include "src/native/x86_64/src/consts.c"
8585
#include "src/native/x86_64/src/rej_uniform_table.c"
8686
#endif
87+
#if defined(MLK_SYS_RISCV64)
88+
#include "src/native/riscv64/src/rv64v_debug.c"
89+
#include "src/native/riscv64/src/rv64v_poly.c"
90+
#endif
8791
#endif /* MLK_CONFIG_USE_NATIVE_BACKEND_ARITH */
8892

8993
#if defined(MLK_CONFIG_USE_NATIVE_BACKEND_FIPS202)
@@ -331,6 +335,7 @@
331335
#undef MLK_SYS_PPC64LE
332336
#undef MLK_SYS_RISCV32
333337
#undef MLK_SYS_RISCV64
338+
#undef MLK_SYS_RISCV64_RVV
334339
#undef MLK_SYS_WINDOWS
335340
#undef MLK_SYS_X86_64
336341
#undef MLK_SYS_X86_64_AVX2
@@ -539,5 +544,40 @@
539544
#undef MLK_NATIVE_X86_64_SRC_CONSTS_H
540545
#undef mlk_qdata
541546
#endif /* MLK_SYS_X86_64 */
547+
#if defined(MLK_SYS_RISCV64)
548+
/*
549+
* Undefine macros from native code (Arith, RISC-V 64)
550+
*/
551+
/* mlkem/src/native/riscv64/meta.h */
552+
#undef MLK_ARITH_BACKEND_RISCV64
553+
#undef MLK_NATIVE_RISCV64_META_H
554+
#undef MLK_USE_NATIVE_INTT
555+
#undef MLK_USE_NATIVE_NTT
556+
#undef MLK_USE_NATIVE_POLYVEC_BASEMUL_ACC_MONTGOMERY_CACHED
557+
#undef MLK_USE_NATIVE_POLY_MULCACHE_COMPUTE
558+
#undef MLK_USE_NATIVE_POLY_REDUCE
559+
#undef MLK_USE_NATIVE_POLY_TOMONT
560+
#undef MLK_USE_NATIVE_REJ_UNIFORM
561+
/* mlkem/src/native/riscv64/src/arith_native_riscv64.h */
562+
#undef MLK_NATIVE_RISCV64_SRC_ARITH_NATIVE_RISCV64_H
563+
#undef mlk_rv64v_poly_add
564+
#undef mlk_rv64v_poly_basemul_mont_add_k2
565+
#undef mlk_rv64v_poly_basemul_mont_add_k3
566+
#undef mlk_rv64v_poly_basemul_mont_add_k4
567+
#undef mlk_rv64v_poly_invntt_tomont
568+
#undef mlk_rv64v_poly_ntt
569+
#undef mlk_rv64v_poly_reduce
570+
#undef mlk_rv64v_poly_sub
571+
#undef mlk_rv64v_poly_tomont
572+
#undef mlk_rv64v_rej_uniform
573+
/* mlkem/src/native/riscv64/src/rv64v_debug.h */
574+
#undef MLK_NATIVE_RISCV64_SRC_RV64V_DEBUG_H
575+
#undef mlk_assert_abs_bound_int16m1
576+
#undef mlk_assert_abs_bound_int16m2
577+
#undef mlk_assert_bound_int16m1
578+
#undef mlk_assert_bound_int16m2
579+
#undef mlk_debug_check_bounds_int16m1
580+
#undef mlk_debug_check_bounds_int16m2
581+
#endif /* MLK_SYS_RISCV64 */
542582
#endif /* MLK_CONFIG_USE_NATIVE_BACKEND_ARITH */
543583
#endif /* !MLK_CONFIG_MONOBUILD_KEEP_SHARED_HEADERS */

mlkem/src/native/meta.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,8 @@
1818
#include "x86_64/meta.h"
1919
#endif
2020

21+
#if defined(MLK_SYS_RISCV64_RVV)
22+
#include "riscv64/meta.h"
23+
#endif
24+
2125
#endif /* !MLK_NATIVE_META_H */

mlkem/src/native/riscv64/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[//]: # (SPDX-License-Identifier: CC-BY-4.0)
2+
3+
# RISC-V Vector Extension Backend
4+
5+
This is an arithmetic backend for CPUs implementing the RISC-V Vector Extension. The backend is functional for all physical `VLEN`, but the NTT and inverse NTT are so far only implemented for VLEN=256, falling back to the default C implementations for other VLENs.
6+
7+
## Requirements
8+
9+
- RISC-V 64-bit architecture
10+
- Vector extension (RVV) version 1.0
11+
- Standard "gc" extensions (integer and compressed instructions)

0 commit comments

Comments
 (0)