Skip to content

Commit

Permalink
Support RV32FC
Browse files Browse the repository at this point in the history
This patch is aimed at supporting RV32FC-only instructions.
* The following instructions are implemented: C.FSW, C.FLW, C.FSWSP, C.FLWSP.
* Update README.md for the corresponding extension description.
* Add corresponding RISC-V architectural tests suites

Close sysprog21#315
  • Loading branch information
fourcolor committed Jan 6, 2024
1 parent 8391ae2 commit ffca3fe
Show file tree
Hide file tree
Showing 12 changed files with 1,745 additions and 15 deletions.
1 change: 1 addition & 0 deletions .ci/riscv-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ make clean
make arch-test RISCV_DEVICE=I || exit 1
make arch-test RISCV_DEVICE=IM || exit 1
make arch-test RISCV_DEVICE=IC || exit 1
make arch-test RISCV_DEVICE=FCZicsr || exit 1
make arch-test RISCV_DEVICE=IZifencei || exit 1
make arch-test RISCV_DEVICE=IZicsr || exit 1
make arch-test RISCV_DEVICE=FZicsr || exit 1
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ The image containing all the necessary tools for development and testing can be
`rv32emu` is configurable, and you can override the below variable(s) to fit your expectations:
* `ENABLE_EXT_M`: Standard Extension for Integer Multiplication and Division
* `ENABLE_EXT_A`: Standard Extension for Atomic Instructions
* `ENABLE_EXT_C`: Standard Extension for Compressed Instructions (RV32C.F excluded)
* `ENABLE_EXT_C`: Standard Extension for Compressed Instructions (RV32C.D excluded)
* `ENABLE_EXT_F`: Standard Extension for Single-Precision Floating Point Instructions
* `ENABLE_Zicsr`: Control and Status Register (CSR)
* `ENABLE_Zifencei`: Instruction-Fetch Fence
Expand Down
9 changes: 7 additions & 2 deletions mk/riscv-arch-test.mk
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
ARCH_TEST_DIR ?= tests/riscv-arch-test
ARCH_TEST_SUITE ?= $(ARCH_TEST_DIR)/riscv-test-suite
export RISCV_TARGET := tests/arch-test-target
export TARGETDIR := $(shell pwd)
export WORK := $(TARGETDIR)/build/arch-test
export RISCV_DEVICE ?= IMCZicsrZifencei

ifeq ($(RISCV_DEVICE),FCZicsr)
ARCH_TEST_SUITE := tests/rv32fc-test-suite
endif

arch-test: $(BIN)
ifeq ($(CROSS_COMPILE),)
$(error GNU Toolchain for RISC-V is required to build architecture tests. Please check package installation)
Expand All @@ -12,5 +17,5 @@ endif
$(Q)python3 -B $(RISCV_TARGET)/setup.py --riscv_device=$(RISCV_DEVICE)
$(Q)riscof run --work-dir=$(WORK) \
--config=$(RISCV_TARGET)/config.ini \
--suite=$(ARCH_TEST_DIR)/riscv-test-suite \
--env=$(ARCH_TEST_DIR)/riscv-test-suite/env
--suite=$(ARCH_TEST_SUITE) \
--env=$(ARCH_TEST_DIR)/riscv-test-suite/env
97 changes: 87 additions & 10 deletions src/decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1668,15 +1668,92 @@ static inline bool op_cbnez(rv_insn_t *ir, const uint32_t insn)
#define op_cbnez OP_UNIMP
#endif /* RV32_HAS(EXT_C) */

/* TODO: RV32C.F support */
#define op_cfldsp OP_UNIMP
#define op_cflwsp OP_UNIMP
#define op_cfswsp OP_UNIMP
#define op_cfsdsp OP_UNIMP
#define op_cfld OP_UNIMP
#define op_cflw OP_UNIMP
#if RV32_HAS(EXT_C) && RV32_HAS(EXT_F)
/* C.FLWSP: CI-format
* 15 13 12 11 7 6 2 1 0
* | funct3 | imm | rd | imm | op |
*/
static inline bool op_cflwsp(rv_insn_t *ir, const uint32_t insn)
{
/* inst funct3 imm rd imm op
* -------+------+-------+-----+-------------+--
* C.FLWSP 001 uimm[5] rd uimm[4:2|7:6] 10
*/
uint16_t tmp = 0;
tmp |= (insn & 0x70) >> 2;
tmp |= (insn & 0x0c) << 4;
tmp |= (insn & 0x1000) >> 7;
ir->imm = tmp;
ir->rd = c_decode_rd(insn);
ir->opcode = rv_insn_cflwsp;
return true;
}

/* C.FSWSP: CSS-Format
* 15 13 12 7 6 2 1 0
* | funct3 | imm | rs2 | op |
*/
static inline bool op_cfswsp(rv_insn_t *ir, const uint32_t insn)
{
/* inst funct3 imm rs2 op
* -------+------+-------------+---+--
* C.FSWSP 111 uimm[5:2|7:6] rs2 10
*/
ir->imm = (insn & 0x1e00) >> 7 | (insn & 0x180) >> 1;
ir->rs2 = c_decode_rs2(insn);
ir->opcode = rv_insn_cfswsp;
return true;
}

/* C.FLW: CL-format
* 15 13 12 10 9 7 6 5 4 2 1 0
* | funct3 | imm | rs1' | imm | rd' | op |
*/
static inline bool op_cflw(rv_insn_t *ir, const uint32_t insn)
{
/* inst funct3 imm rs1' imm rd' op
* -----+------+---------+----+---------+---+--
* C.FLW 010 uimm[5:3] rs1' uimm[7:6] rd' 00
*/
uint16_t tmp = 0;
tmp |= (insn & 0b0000000001000000) >> 4;
tmp |= (insn & FC_IMM_12_10) >> 7;
tmp |= (insn & 0b0000000000100000) << 1;
ir->imm = tmp;
ir->rd = c_decode_rdc(insn) | 0x08;
ir->rs1 = c_decode_rs1c(insn) | 0x08;
ir->opcode = rv_insn_cflw;
return true;
}

/* C.FSW: CS-format
* 15 13 12 10 9 7 6 5 4 2 1 0
* | funct3 | imm | rs1' | imm | rs2' | op |
*/
static inline bool op_cfsw(rv_insn_t *ir, const uint32_t insn)
{
/* inst funct3 imm rs1' imm rs2' op
* -----+------+---------+----+---------+----+--
* C.FSW 110 uimm[5:3] rs1' uimm[2|6] rs2' 00
*/
uint32_t tmp = 0;
/* ....xxxx....xxxx */
tmp |= (insn & 0b0000000001000000) >> 4;
tmp |= (insn & FC_IMM_12_10) >> 7;
tmp |= (insn & 0b0000000000100000) << 1;
ir->imm = tmp;
ir->rs1 = c_decode_rs1c(insn) | 0x08;
ir->rs2 = c_decode_rs2c(insn) | 0x08;
ir->opcode = rv_insn_cfsw;
return true;
}

#else /* !(RV32_HAS(EXT_C) && RV32_HAS(EXT_F)) */
#define op_cfsw OP_UNIMP
#define op_cfsd OP_UNIMP
#define op_cflw OP_UNIMP
#define op_cfswsp OP_UNIMP
#define op_cflwsp OP_UNIMP
#endif /* RV32_HAS(EXT_C) && RV32_HAS(EXT_F) */

/* handler for all unimplemented opcodes */
static inline bool op_unimp(rv_insn_t *ir UNUSED, uint32_t insn UNUSED)
Expand Down Expand Up @@ -1710,11 +1787,11 @@ bool rv_decode(rv_insn_t *ir, uint32_t insn)
static const decode_t rvc_jump_table[] = {
// 00 01 10 11
OP(caddi4spn), OP(caddi), OP(cslli), OP(unimp), // 000
OP(cfld), OP(cjal), OP(cfldsp), OP(unimp), // 001
OP(unimp), OP(cjal), OP(unimp), OP(unimp), // 001
OP(clw), OP(cli), OP(clwsp), OP(unimp), // 010
OP(cflw), OP(clui), OP(cflwsp), OP(unimp), // 011
OP(unimp), OP(cmisc_alu), OP(ccr), OP(unimp), // 100
OP(cfsd), OP(cj), OP(cfsdsp), OP(unimp), // 101
OP(unimp), OP(cj), OP(unimp), OP(unimp), // 101
OP(csw), OP(cbeqz), OP(cswsp), OP(unimp), // 110
OP(cfsw), OP(cbnez), OP(cfswsp), OP(unimp), // 111
};
Expand Down
7 changes: 7 additions & 0 deletions src/decode.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,13 @@ enum op_field {
_(cjalr, 1, 2, 1, ENC(rs1, rs2, rd)) \
_(cadd, 0, 2, 1, ENC(rs1, rs2, rd)) \
_(cswsp, 0, 2, 1, ENC(rs2)) \
/* RV32FC Instruction */ \
IIF(RV32_HAS(EXT_F))( \
_(cflwsp, 0, 2, 1, ENC(rd)) \
_(cfswsp, 0, 2, 1, ENC(rs2)) \
_(cflw, 0, 2, 1, ENC(rs1, rd)) \
_(cfsw, 0, 2, 1, ENC(rs1, rs2)) \
) \
)
/* clang-format on */

Expand Down
16 changes: 16 additions & 0 deletions src/rv32_constopt.c
Original file line number Diff line number Diff line change
Expand Up @@ -979,3 +979,19 @@ CONSTOPT(cadd, {
/* C.SWSP */
CONSTOPT(cswsp, {})
#endif

/* RV32FC Standard Extension */

#if RV32_HAS(EXT_F) && RV32_HAS(EXT_C)
/* C.FLWSP */
CONSTOPT(cflwsp, {})

/* C.FSWSP */
CONSTOPT(cfswsp, {})

/* C.FLW */
CONSTOPT(cflw, {})

/* C.FSW */
CONSTOPT(cfsw, {})
#endif
50 changes: 50 additions & 0 deletions src/rv32_template.c
Original file line number Diff line number Diff line change
Expand Up @@ -2272,3 +2272,53 @@ RVOP(
st, S32, TMP1, TMP0, 0;
}))
#endif

#if RV32_HAS(EXT_C) && RV32_HAS(EXT_F)
/* C.FLWSP */
RVOP(
cflwsp,
{
const uint32_t addr = rv->X[rv_reg_sp] + ir->imm;
RV_EXC_MISALIGN_HANDLER(3, load, false, 1);
rv->F[ir->rd].v = rv->io.mem_read_w(addr);
},
GEN({
assert; /* FIXME: Implement */
}))

/* C.FSWSP */
RVOP(
cfswsp,
{
const uint32_t addr = rv->X[rv_reg_sp] + ir->imm;
RV_EXC_MISALIGN_HANDLER(3, store, false, 1);
rv->io.mem_write_w(addr, rv->F[ir->rs2].v);
},
GEN({
assert; /* FIXME: Implement */
}))

/* C.FLW */
RVOP(
cflw,
{
const uint32_t addr = rv->X[ir->rs1] + (uint32_t) ir->imm;
RV_EXC_MISALIGN_HANDLER(3, load, false, 1);
rv->F[ir->rd].v = rv->io.mem_read_w(addr);
},
GEN({
assert; /* FIXME: Implement */
}))

/* C.FSW */
RVOP(
cfsw,
{
const uint32_t addr = rv->X[ir->rs1] + (uint32_t) ir->imm;
RV_EXC_MISALIGN_HANDLER(3, store, false, 1);
rv->io.mem_write_w(addr, rv->F[ir->rs2].v);
},
GEN({
assert; /* FIXME: Implement */
}))
#endif
4 changes: 2 additions & 2 deletions tests/arch-test-target/rv32emu/rv32emu_isa.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
hart0:
ISA: RV32IMCZicsr_Zifencei
ISA: RV32IFCZicsr
User_Spec_Version: '2.3'
misa:
reset-val: 1073746180
reset-val: 1073742116
rv32:
accessible: true
extensions:
Expand Down
Loading

0 comments on commit ffca3fe

Please sign in to comment.