Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support RV32FC #316

Merged
merged 1 commit into from
Jan 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)) \
) \
fourcolor marked this conversation as resolved.
Show resolved Hide resolved
)
/* 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
Loading