From 882996ab898415e44ec8ba806aad79c8a3cbe79e Mon Sep 17 00:00:00 2001 From: Yu-Chun Lin Date: Wed, 22 Jan 2025 20:50:05 +0800 Subject: [PATCH 1/4] Add support for the RV32E base ISA variant The RV32E variant reduces the general-purpose registers to 16, optimizing the architecture for resource-constrained embedded microcontrollers. This addition enhances compatibility with the RISC-V specification and targets low-power, minimal-complexity systems. --- Makefile | 4 ++++ src/feature.h | 5 +++++ src/riscv.c | 7 ++++++- src/riscv.h | 37 +++++++++++++++++++++---------------- src/syscall.c | 6 +++++- 5 files changed, 41 insertions(+), 18 deletions(-) diff --git a/Makefile b/Makefile index 9921389b..da5ef350 100644 --- a/Makefile +++ b/Makefile @@ -127,6 +127,10 @@ endif ENABLE_EXT_C ?= 1 $(call set-feature, EXT_C) +# RV32E Base Integer Instruction Set +ENABLE_RV32E ?= 0 +$(call set-feature, RV32E) + # Control and Status Register (CSR) ENABLE_Zicsr ?= 1 $(call set-feature, Zicsr) diff --git a/src/feature.h b/src/feature.h index c4a41939..8e8523b1 100644 --- a/src/feature.h +++ b/src/feature.h @@ -27,6 +27,11 @@ #define RV32_FEATURE_EXT_C 1 #endif +/* RV32E Base Integer Instruction Set */ +#ifndef RV32_FEATURE_RV32E +#define RV32_FEATURE_RV32E 0 +#endif + /* Control and Status Register (CSR) */ #ifndef RV32_FEATURE_Zicsr #define RV32_FEATURE_Zicsr 1 diff --git a/src/riscv.c b/src/riscv.c index 60fb1cac..9a4c7c75 100644 --- a/src/riscv.c +++ b/src/riscv.c @@ -769,10 +769,15 @@ void rv_reset(riscv_t *rv, riscv_word_t pc) rv->csr_mtvec = 0; rv->csr_cycle = 0; rv->csr_mstatus = 0; - rv->csr_misa |= MISA_SUPER | MISA_USER | MISA_I; + rv->csr_misa |= MISA_SUPER | MISA_USER; rv->csr_mvendorid = RV_MVENDORID; rv->csr_marchid = RV_MARCHID; rv->csr_mimpid = RV_MIMPID; +#if !RV32_HAS(RV32E) + rv->csr_misa |= MISA_I; +#else + rv->csr_misa |= MISA_E; +#endif #if RV32_HAS(EXT_A) rv->csr_misa |= MISA_A; #endif diff --git a/src/riscv.h b/src/riscv.h index f7122296..e333241e 100644 --- a/src/riscv.h +++ b/src/riscv.h @@ -33,6 +33,7 @@ extern "C" { #endif +/* clang-format off */ #define RV_REGS_LIST \ _(zero) /* hard-wired zero, ignoring any writes */ \ _(ra) /* return address */ \ @@ -50,22 +51,25 @@ extern "C" { _(a3) \ _(a4) \ _(a5) \ - _(a6) \ - _(a7) \ - _(s2) /* saved register */ \ - _(s3) \ - _(s4) \ - _(s5) \ - _(s6) \ - _(s7) \ - _(s8) \ - _(s9) \ - _(s10) \ - _(s11) \ - _(t3) /* temporary register */ \ - _(t4) \ - _(t5) \ - _(t6) + IIF(RV32_HAS(RV32E))(, \ + _(a6) \ + _(a7) \ + _(s2) /* saved register */ \ + _(s3) \ + _(s4) \ + _(s5) \ + _(s6) \ + _(s7) \ + _(s8) \ + _(s9) \ + _(s10) \ + _(s11) \ + _(t3) /* temporary register */ \ + _(t4) \ + _(t5) \ + _(t6) \ + ) +/* clang-format on */ /* RISC-V registers (mnemonics, ABI names) * @@ -117,6 +121,7 @@ enum SV32_PTE_PERM { #define MISA_SUPER (1 << ('S' - 'A')) #define MISA_USER (1 << ('U' - 'A')) #define MISA_I (1 << ('I' - 'A')) +#define MISA_E (1 << ('E' - 'A')) #define MISA_M (1 << ('M' - 'A')) #define MISA_A (1 << ('A' - 'A')) #define MISA_F (1 << ('F' - 'A')) diff --git a/src/syscall.c b/src/syscall.c index 36a5747f..86f9d2ca 100644 --- a/src/syscall.c +++ b/src/syscall.c @@ -466,8 +466,12 @@ static void syscall_sbi_rst(riscv_t *rv) void syscall_handler(riscv_t *rv) { - /* get the syscall number */ +/* get the syscall number */ +#if !RV32_HAS(RV32E) riscv_word_t syscall = rv_get_reg(rv, rv_reg_a7); +#else + riscv_word_t syscall = rv_get_reg(rv, rv_reg_t0); +#endif switch (syscall) { /* dispatch system call */ #define _(name, number) \ From 61859f11ff3635b259a691a746fd19a6973815c7 Mon Sep 17 00:00:00 2001 From: Yu-Chun Lin Date: Wed, 22 Jan 2025 22:14:01 +0800 Subject: [PATCH 2/4] Add RV32E support to README Add RV32E to the list of supported features, customization options, and riscv-arch-test progress in the README. --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1eb08b28..1fae4584 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ a focus on efficiency and readability. Features: * Fast interpreter for executing the RV32 ISA -* Comprehensive support for RV32I and M, A, F, C, Zba, Zbb, Zbc, Zbs extensions +* Comprehensive support for RV32I, RV32E and M, A, F, C, Zba, Zbb, Zbc, Zbs extensions * Memory-efficient design * Built-in ELF loader * Implementation of commonly used newlib system calls @@ -116,6 +116,7 @@ The image containing all the necessary tools for development and testing can be ### Customization `rv32emu` is configurable, and you can override the below variable(s) to fit your expectations: +* `ENABLE_RV32E`: RV32E Base Integer Instruction Set * `ENABLE_EXT_M`: Standard Extension for Integer Multiplication and Division * `ENABLE_EXT_A`: Standard Extension for Atomic Instructions * `ENABLE_EXT_F`: Standard Extension for Single-Precision Floating Point Instructions @@ -187,6 +188,7 @@ $ make arch-test RISCV_DEVICE=I Current progress of this emulator in riscv-arch-test (RV32): * Passed Tests - `I`: Base Integer Instruction Set + - `E`: RV32E Base Integer Instruction Set - `M`: Standard Extension for Integer Multiplication and Division - `A`: Standard Extension for Atomic Instructions - `F`: Standard Extension for Single-Precision Floating-Point From 781e14fa9887df1e29d2c724bed54348f2c2ea7d Mon Sep 17 00:00:00 2001 From: Yu-Chun Lin Date: Wed, 22 Jan 2025 22:19:52 +0800 Subject: [PATCH 3/4] Add support for RV32E in architecture tests Enable architecture tests for RV32E with appropriate handling of the reduced register set and ABI. With this change, users can run tests for RV32E using the following command: make arch-test RISCV_DEVICE=E --- tests/arch-test-target/constants.py | 2 ++ tests/arch-test-target/rv32emu/env/model_test.h | 7 +++++++ tests/arch-test-target/rv32emu/riscof_rv32emu.py | 6 +++++- tests/arch-test-target/sail_cSim/env/model_test.h | 8 ++++++++ tests/arch-test-target/sail_cSim/riscof_sail_cSim.py | 8 +++++++- tests/arch-test-target/setup.py | 10 ++++++++-- 6 files changed, 37 insertions(+), 4 deletions(-) diff --git a/tests/arch-test-target/constants.py b/tests/arch-test-target/constants.py index 71777152..3761270e 100644 --- a/tests/arch-test-target/constants.py +++ b/tests/arch-test-target/constants.py @@ -8,7 +8,9 @@ misa_A = (1 << 0) misa_C = (1 << 2) +misa_E = (1 << 4) misa_F = (1 << 5) +misa_I = (1 << 8) misa_M = (1 << 12) config_temp = '''[RISCOF] diff --git a/tests/arch-test-target/rv32emu/env/model_test.h b/tests/arch-test-target/rv32emu/env/model_test.h index a75dc615..cd8a2541 100644 --- a/tests/arch-test-target/rv32emu/env/model_test.h +++ b/tests/arch-test-target/rv32emu/env/model_test.h @@ -13,10 +13,17 @@ /* clang-format on */ // RV_COMPLIANCE_HALT +#ifndef RV32E #define RVMODEL_HALT \ add a7, x0, 93; \ add a0, x0, 0; \ ecall +#else +#define RVMODEL_HALT \ + add t0, x0, 93; \ + add a0, x0, 0; \ + ecall +#endif #define RVMODEL_BOOT diff --git a/tests/arch-test-target/rv32emu/riscof_rv32emu.py b/tests/arch-test-target/rv32emu/riscof_rv32emu.py index c4e4ebc2..7a0fba68 100644 --- a/tests/arch-test-target/rv32emu/riscof_rv32emu.py +++ b/tests/arch-test-target/rv32emu/riscof_rv32emu.py @@ -86,7 +86,11 @@ def build(self, isa_yaml, platform_yaml): # will be useful in setting integer value in the compiler string (if not already hardcoded); self.xlen = ('64' if 64 in ispec['supported_xlen'] else '32') - self.compile_cmd = self.compile_cmd+' -mabi='+('lp64 ' if 64 in ispec['supported_xlen'] else 'ilp32 ') + if 'E' not in ispec['ISA']: + self.compile_cmd = self.compile_cmd+' -mabi='+('lp64 ' if 64 in ispec['supported_xlen'] else 'ilp32 ') + else: + self.compile_cmd = self.compile_cmd+' -mabi='+('lp64e ' if 64 in ispec['supported_xlen'] else 'ilp32e ') + self.compile_cmd += '-D RV32E ' def runTests(self, testList): # Delete Makefile if it already exists. diff --git a/tests/arch-test-target/sail_cSim/env/model_test.h b/tests/arch-test-target/sail_cSim/env/model_test.h index e9fec6f2..5b8536aa 100644 --- a/tests/arch-test-target/sail_cSim/env/model_test.h +++ b/tests/arch-test-target/sail_cSim/env/model_test.h @@ -13,11 +13,19 @@ /* clang-format on */ // RV_COMPLIANCE_HALT +#ifndef RV32E #define RVMODEL_HALT \ li x1, 1; \ write_tohost: \ sw x1, tohost, t5; \ j write_tohost; +#else +#define RVMODEL_HALT \ + li x1, 1; \ + write_tohost: \ + sw x1, tohost, x15; \ + j write_tohost; +#endif #define RVMODEL_BOOT diff --git a/tests/arch-test-target/sail_cSim/riscof_sail_cSim.py b/tests/arch-test-target/sail_cSim/riscof_sail_cSim.py index 45c3ac36..c1ae8e41 100644 --- a/tests/arch-test-target/sail_cSim/riscof_sail_cSim.py +++ b/tests/arch-test-target/sail_cSim/riscof_sail_cSim.py @@ -52,9 +52,15 @@ def build(self, isa_yaml, platform_yaml): ispec = utils.load_yaml(isa_yaml)['hart0'] self.xlen = ('64' if 64 in ispec['supported_xlen'] else '32') self.isa = 'rv' + self.xlen - self.compile_cmd = self.compile_cmd+' -mabi='+('lp64 ' if 64 in ispec['supported_xlen'] else 'ilp32 ') + if 'E' not in ispec['ISA']: + self.compile_cmd = self.compile_cmd+' -mabi='+('lp64 ' if 64 in ispec['supported_xlen'] else 'ilp32 ') + else: + self.compile_cmd = self.compile_cmd+' -mabi='+('lp64e ' if 64 in ispec['supported_xlen'] else 'ilp32e ') + self.compile_cmd += "-D RV32E " if "I" in ispec["ISA"]: self.isa += 'i' + if "E" in ispec["ISA"]: + self.isa += 'e' if "M" in ispec["ISA"]: self.isa += 'm' if "C" in ispec["ISA"]: diff --git a/tests/arch-test-target/setup.py b/tests/arch-test-target/setup.py index e7bd9e6e..81958d69 100644 --- a/tests/arch-test-target/setup.py +++ b/tests/arch-test-target/setup.py @@ -6,12 +6,18 @@ def setup_testlist(riscv_device): # ISA config file path ispec = constants.root + '/rv32emu/rv32emu_isa.yaml' - misa = 0x40000100 - ISA = 'RV32I' + misa = 0x40000000 + ISA = 'RV32' if not riscv_device: raise AssertionError('There is not any ISA.') + if 'E' in riscv_device: + misa |= constants.misa_E + ISA += 'E' + else: + misa |= constants.misa_I + ISA += 'I' if 'M' in riscv_device: misa |= constants.misa_M ISA += 'M' From 64ea138c99ecfa1a91a4a26e23226867ac857cb5 Mon Sep 17 00:00:00 2001 From: Yu-Chun Lin Date: Thu, 23 Jan 2025 11:12:37 +0800 Subject: [PATCH 4/4] CI: Add RV32E test to CI pipeline Add testing for the RV32E to the CI pipeline to ensure automatic validation during continuous integration. --- .ci/riscv-tests.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.ci/riscv-tests.sh b/.ci/riscv-tests.sh index ac1a4441..a1d8236a 100755 --- a/.ci/riscv-tests.sh +++ b/.ci/riscv-tests.sh @@ -22,3 +22,7 @@ make ENABLE_EXT_M=1 ENABLE_EXT_A=1 ENABLE_EXT_F=1 ENABLE_EXT_C=1 \ make arch-test RISCV_DEVICE=IMAFCZicsrZifencei $PARALLEL || exit 1 make arch-test RISCV_DEVICE=FCZicsr $PARALLEL || exit 1 make arch-test RISCV_DEVICE=IMZbaZbbZbcZbs $PARALLEL || exit 1 + +make distclean +make ENABLE_RV32E=1 ENABLE_FULL4G=1 $PARALLEL +make arch-test RISCV_DEVICE=E $PARALLEL || exit 1