From 0619c749041f411cc7370bab942186085c025b73 Mon Sep 17 00:00:00 2001 From: Jingqing3948 <2351290287@qq.com> Date: Mon, 6 May 2024 19:49:52 +0800 Subject: [PATCH 1/3] Add float instruction map --- src/machine/core.cpp | 7 ++- src/machine/instruction.cpp | 110 +++++++++++++++++++++++++++++++++--- src/machine/instruction.h | 5 ++ src/machine/registers.cpp | 15 +++++ src/machine/registers.h | 13 +++++ 5 files changed, 141 insertions(+), 9 deletions(-) diff --git a/src/machine/core.cpp b/src/machine/core.cpp index 250c70b5..39d32aff 100644 --- a/src/machine/core.cpp +++ b/src/machine/core.cpp @@ -19,6 +19,8 @@ static InstructionFlags unsupported_inst_flags_to_check(Xlen xlen, flags_to_check |= IMF_AMO; if (!isa_word.contains('M')) flags_to_check |= IMF_MUL; + if(!isa_word.contains('F')) + flags_to_check |= (IMF_ALU_REQ_RD_F | IMF_ALU_REQ_RS_F | IMF_ALU_REQ_RT_F); return InstructionFlags(flags_to_check); } @@ -321,8 +323,9 @@ DecodeState Core::decode(const FetchInterstage &dt) { // When instruction does not specify register, it is set to x0 as operations on x0 have no // side effects (not even visualization). RegisterValue val_rs - = (flags & IMF_ALU_RS_ID) ? uint64_t(size_t(num_rs)) : regs->read_gp(num_rs); - RegisterValue val_rt = regs->read_gp(num_rt); + = (flags & IMF_ALU_RS_ID) ? uint64_t(size_t(num_rs)) : (flags & IMF_ALU_REQ_RS_F) ? regs->read_fp(num_rs) : regs->read_gp(num_rs); + RegisterValue val_rt + = (flags & IMF_ALU_REQ_RT_F) ? regs->read_fp(num_rt) : regs->read_gp(num_rt); RegisterValue immediate_val = dt.inst.immediate(); const bool regwrite = flags & IMF_REGWRITE; diff --git a/src/machine/instruction.cpp b/src/machine/instruction.cpp index becaa2e9..e13b1bd6 100644 --- a/src/machine/instruction.cpp +++ b/src/machine/instruction.cpp @@ -65,6 +65,12 @@ static const ArgumentDesc arg_desc_list[] = { ArgumentDesc('s', 'g', 0, 0x1f, { { { 5, 15 } }, 0 }), // Source register 2 (rs2/rt) ArgumentDesc('t', 'g', 0, 0x1f, { { { 5, 20 } }, 0 }), + // Float destination register (rd) + ArgumentDesc('D', 'f', 0, 0x1f, { { { 5, 7 } }, 0 }), + // Float source register 1 (rs1/rs) + ArgumentDesc('S', 'f', 0, 0x1f, { { { 5, 15 } }, 0 }), + // Float source register 1 (rs1/rs) + ArgumentDesc('T', 'f', 0, 0x1f, { { { 5, 20 } }, 0 }), // I-type immediate for arithmetic instructions (12bits) ArgumentDesc('j', 'n', -0x800, 0x7ff, { { { 12, 20 } }, 0 }), // Shift for bit shift instructions (5bits) @@ -368,6 +374,13 @@ static const struct InstructionMap LOAD_map[] = { IM_UNKNOWN, }; +static const struct InstructionMap F_LOAD_map[] = { + IM_UNKNOWN, + IM_UNKNOWN, + {"flw", IT_I, { .alu_op=AluOp::ADD }, AC_I32, nullptr, {"D", "o(s)"}, 0x2007, 0x707f, { .flags = FLAGS_ALU_I_LOAD | IMF_ALU_REQ_RD_F }, nullptr}, + {"fld", IT_I, { .alu_op=AluOp::ADD }, AC_I64, nullptr, {"D", "o(s)"}, 0x3007, 0x707f, { .flags = FLAGS_ALU_I_LOAD | IMF_ALU_REQ_RD_F }, nullptr}, +}; + static const struct InstructionMap SRI_map[] = { // 0xfe00707f mask changed to 0xfc00707f to support RV64I {"srli", IT_I, { .alu_op=AluOp::SR }, NOMEM, nullptr, {"d", "s", ">"}, 0x00005013,0xfc00707f, { .flags = FLAGS_ALU_I }, nullptr}, // SRLI {"srai", IT_I, { .alu_op=AluOp::SR }, NOMEM, nullptr, {"d", "s", ">"}, 0x40005013,0xfc00707f, { .flags = (FLAGS_ALU_I | IMF_ALU_MOD) }, nullptr}, // SRAI @@ -395,6 +408,13 @@ static const struct InstructionMap STORE_map[] = { IM_UNKNOWN, }; +static const struct InstructionMap F_STORE_map[] = { + IM_UNKNOWN, + IM_UNKNOWN, + {"fsw", IT_I, { .alu_op=AluOp::ADD }, AC_U32, nullptr, {"T", "q(s)"}, 0x2027, 0x707f, { .flags = FLAGS_ALU_I_STORE | IMF_ALU_REQ_RT_F }, nullptr}, // FSW + {"fsd", IT_I, { .alu_op=AluOp::ADD }, AC_U64, nullptr, {"T", "q(s)"}, 0x3027, 0x707f, { .flags = FLAGS_ALU_I_STORE | IMF_ALU_REQ_RT_F }, nullptr}, // FSD +}; + static const struct InstructionMap ADD_map[] = { {"add", IT_R, { .alu_op=AluOp::ADD }, NOMEM, nullptr, {"d", "s", "t"}, 0x00000033, 0xfe00707f, { .flags = FLAGS_ALU_T_R_STD }, nullptr}, {"sub", IT_R, { .alu_op=AluOp::ADD }, NOMEM, nullptr, {"d", "s", "t"}, 0x40000033, 0xfe00707f, { .flags = FLAGS_ALU_T_R_STD | IMF_ALU_MOD }, inst_aliases_sub}, @@ -578,9 +598,77 @@ static const struct InstructionMap OP_32_map[] = { // Full, uncomprese, instructions top level map +static const struct InstructionMap F_sgnj_map[] = { + {"fsgnj.s",IT_I, NOALU, NOMEM, nullptr, {}, 0x20000053, 0xfe00707f, {}, nullptr}, + {"fsgnjn.s",IT_I, NOALU, NOMEM, nullptr, {}, 0x20001053, 0xfe00707f, {}, nullptr}, + {"fsgnjx.s",IT_I, NOALU, NOMEM, nullptr, {}, 0x20002053, 0xfe00707f, {}, nullptr}, + IM_UNKNOWN, + IM_UNKNOWN, + IM_UNKNOWN, + IM_UNKNOWN, + IM_UNKNOWN, +}; + +static const struct InstructionMap F_ex_map[] = { + {"fmin.s",IT_I, NOALU, NOMEM, nullptr, {}, 0x28000053, 0xfe00707f, {}, nullptr}, + {"fmax.s",IT_I, NOALU, NOMEM, nullptr, {}, 0x28001053, 0xfe00707f, {}, nullptr}, +}; + +static const struct InstructionMap F_cvt_w_s_map[] = { + {"fcvt.w.s",IT_I, NOALU, NOMEM, nullptr, {}, 0xc0000053, 0xfff0007f, {}, nullptr}, + {"fcvt.wu.s",IT_I, NOALU, NOMEM, nullptr, {}, 0xc0100053, 0xfff0007f, {}, nullptr}, +}; + +static const struct InstructionMap F_cp_map[] = { + {"fle.s",IT_I, NOALU, NOMEM, nullptr, {}, 0xa0002053, 0xfe00707f, {}, nullptr}, + {"flt.s",IT_I, NOALU, NOMEM, nullptr, {}, 0xa0001053, 0xfe00707f, {}, nullptr}, + {"feq.s",IT_I, NOALU, NOMEM, nullptr, {}, 0xa0000053, 0xfe00707f, {}, nullptr}, + IM_UNKNOWN, +}; + +static const struct InstructionMap F_cvt_s_w_map[] = { + {"fcvt.s.w",IT_I, NOALU, NOMEM, nullptr, {}, 0xd0000053, 0xfff0007f, {}, nullptr}, + {"fcvt.s.wu",IT_I, NOALU, NOMEM, nullptr, {}, 0xd0100053, 0xfff0007f, {}, nullptr}, +}; + +static const struct InstructionMap F_inst_map[] = { + {"fadd.s",IT_I, { .alu_op=AluOp::ADD }, NOMEM, nullptr, {"D", "S", "T"}, 0x53, 0xfe00007f, { .flags = FLAGS_ALU_T_R_STD | IMF_ALU_REQ_RT_F | IMF_ALU_REQ_RS_F | IMF_ALU_REQ_RD_F }, nullptr}, + {"fsub.s",IT_I, NOALU, NOMEM, nullptr, {"D", "S", "T"}, 0x8000053, 0xfe00007f, { .flags = FLAGS_ALU_T_R_STD | IMF_ALU_REQ_RT_F | IMF_ALU_REQ_RS_F | IMF_ALU_REQ_RD_F | IMF_ALU_MOD}, nullptr}, + {"fmul.s",IT_I, NOALU, NOMEM, nullptr, {}, 0x10000053, 0xfe00007f, {}, nullptr}, + {"fdiv.s",IT_I, NOALU, NOMEM, nullptr, {}, 0x18000053, 0xfe00007f, {}, nullptr}, + {"fsgnj",IT_I, NOALU, NOMEM, F_sgnj_map, {}, 0x20000053, 0xfe00007f, { .subfield = {3, 12} }, nullptr}, + {"f-ex.s",IT_I, NOALU, NOMEM, F_ex_map, {}, 0x28000053, 0xfe00007f, { .subfield = {1, 12} }, nullptr}, + IM_UNKNOWN, + IM_UNKNOWN, + IM_UNKNOWN, + IM_UNKNOWN, + IM_UNKNOWN, + {"fsqrt.s",IT_I, NOALU, NOMEM, nullptr, {}, 0x58000053, 0xfe00007f, {}, nullptr}, + IM_UNKNOWN, + IM_UNKNOWN, + IM_UNKNOWN, + IM_UNKNOWN, + IM_UNKNOWN, + IM_UNKNOWN, + IM_UNKNOWN, + IM_UNKNOWN, + {"f-cp",IT_I, NOALU, NOMEM, F_cp_map, {}, 0xa0000053, 0xfe00007f, { .subfield = {2, 12} }, nullptr}, + IM_UNKNOWN, + IM_UNKNOWN, + IM_UNKNOWN, + {"fcvt-w-s",IT_I, NOALU, NOMEM, F_cvt_w_s_map, {}, 0xc0000053, 0xfe00007f, { .subfield = {1, 20} }, nullptr}, + IM_UNKNOWN, + {"fcvt-s-w",IT_I, NOALU, NOMEM, F_cvt_s_w_map, {}, 0xd0000053, 0xfe00007f, { .subfield = {1, 20} }, nullptr}, + IM_UNKNOWN, + {"fmv.x.w",IT_I, { .alu_op=AluOp::ADD }, AC_I32, nullptr, {"d", "S"}, 0xe0000053, 0xfe00007f, {}, nullptr}, + IM_UNKNOWN, + {"fmv.w.x",IT_I, { .alu_op=AluOp::ADD }, AC_I32, nullptr, {"D", "s"}, 0xf0000053, 0xfe00007f, {}, nullptr}, + IM_UNKNOWN, +}; + static const struct InstructionMap I_inst_map[] = { {"load", IT_I, NOALU, NOMEM, LOAD_map, {}, 0x03, 0x7f, { .subfield = {3, 12} }, nullptr}, // LOAD - IM_UNKNOWN, // LOAD-FP + {"load-fp", IT_I, NOALU, NOMEM, F_LOAD_map, {}, 0x07, 0x7f, { .subfield = {2, 12} }, nullptr}, // LOAD-FP IM_UNKNOWN, // custom-0 {"misc-mem", IT_I, NOALU, NOMEM, MISC_MEM_map, {}, 0x0f, 0x7f, { .subfield = {3, 12} }, nullptr}, // MISC-MEM {"op-imm", IT_I, NOALU, NOMEM, OP_IMM_map, {}, 0x13, 0x7f, { .subfield = {3, 12} }, nullptr}, // OP-IMM @@ -588,18 +676,18 @@ static const struct InstructionMap I_inst_map[] = { {"op-imm-32", IT_I, NOALU, NOMEM, OP_IMM_32_map, {}, 0x1b, 0x7f, { .subfield = {3, 12} }, nullptr}, // OP-IMM-32 IM_UNKNOWN, // OP-IMM-32 IM_UNKNOWN, // 48b {"store", IT_I, NOALU, NOMEM, STORE_map, {}, 0x23, 0x7f, { .subfield = {3, 12} }, nullptr}, // STORE - IM_UNKNOWN, // STORE-FP + {"store-fp", IT_I, NOALU, NOMEM, F_STORE_map, {}, 0x27, 0x7f, { .subfield = {2, 12} }, nullptr}, // STORE-FP IM_UNKNOWN, // custom-1 {"amo", IT_R, NOALU, NOMEM, AMO_map, {}, 0x2f, 0x7f, { .subfield = {3, 12} }, nullptr}, // OP-32 {"op", IT_R, NOALU, NOMEM, OP_map, {}, 0x33, 0x7f, { .subfield = {1, 25} }, nullptr}, // OP {"lui", IT_U, { .alu_op=AluOp::ADD }, NOMEM, nullptr, {"d", "u"}, 0x37, 0x7f, { .flags = IMF_SUPPORTED | IMF_ALUSRC | IMF_REGWRITE }, nullptr}, // LUI {"op-32", IT_R, NOALU, NOMEM, OP_32_map, {}, 0x3b, 0x7f, { .subfield = {1, 25} }, nullptr}, // OP-32 IM_UNKNOWN, // 64b - IM_UNKNOWN, // MADD - IM_UNKNOWN, // MSUB - IM_UNKNOWN, // NMSUB - IM_UNKNOWN, // NMADD - IM_UNKNOWN, // OP-FP + {"fmadd.s", IT_I, NOALU, NOMEM, nullptr, {}, 0x43, 0x7f, {}, nullptr}, // FMADD.S + {"fmsub.s", IT_I, NOALU, NOMEM, nullptr, {}, 0x47, 0x7f, {}, nullptr}, // FMSUB.S + {"fnmsub.s", IT_I, NOALU, NOMEM, nullptr, {}, 0x4b, 0x7f, {}, nullptr}, // FNMSUB.S + {"fnmadd.s", IT_I, NOALU, NOMEM, nullptr, {}, 0x4f, 0x7f, {}, nullptr}, // FNMADD.S + {"op-fp",IT_I, NOALU, NOMEM, F_inst_map, {}, 0x600007f, 0x7f, { .subfield={5,27} }, nullptr}, // OP-FP IM_UNKNOWN, // reserved IM_UNKNOWN, // custom-2/rv128 IM_UNKNOWN, // 48b @@ -804,6 +892,14 @@ QString Instruction::to_str(Address inst_addr) const { } break; } + case 'f': { + if (symbolic_registers_enabled) { + res += QString(Rv_regnames[field]); + } else { + res += "f" + QString::number(field); + } + break; + } case 'p': case 'a': { field += (int32_t)inst_addr.get_raw(); diff --git a/src/machine/instruction.h b/src/machine/instruction.h index 3719d877..6c608cfe 100644 --- a/src/machine/instruction.h +++ b/src/machine/instruction.h @@ -60,6 +60,11 @@ enum InstructionFlags : unsigned { // TODO do we want to add those signals to the visualization? IMF_RV64 = 1L << 24, /**< Mark instructions which are available in 64-bit mode only. */ + + // RV64/32F + IMF_ALU_REQ_RS_F = 1L << 25, /** < Execution phase/ALU/mem requires RS value in Float Reg*/ + IMF_ALU_REQ_RT_F = 1L << 26, /**< Execution phase/ALU/mem requires RT value in Float Reg*/ + IMF_ALU_REQ_RD_F = 1L << 27, /**< Execution phase/ALU/mem requires RD value in Float Reg*/ }; /** diff --git a/src/machine/registers.cpp b/src/machine/registers.cpp index 5cd53525..c19d888a 100644 --- a/src/machine/registers.cpp +++ b/src/machine/registers.cpp @@ -19,6 +19,7 @@ Registers::Registers() : QObject() { Registers::Registers(const Registers &orig) : QObject() { this->pc = orig.read_pc(); this->gp = orig.gp; + this->fp = orig.fp; } Address Registers::read_pc() const { @@ -54,6 +55,17 @@ void Registers::write_gp(RegisterId reg, RegisterValue value) { emit gp_update(reg, value); } +RegisterValue Registers::read_fp(RegisterId reg) const { + RegisterValue value = this->fp.at(reg); + emit gp_read(reg, value); + return value; +} + +void Registers::write_fp(RegisterId reg, RegisterValue value) { + this->fp.at(reg) = value; + emit fp_update(reg, value); +} + bool Registers::operator==(const Registers &c) const { if (read_pc() != c.read_pc()) { return false; } if (this->gp != c.gp) { return false; } @@ -69,6 +81,9 @@ void Registers::reset() { for (int i = 1; i < 32; i++) { write_gp(i, 0); } + for (int i = 1; i < 32; i++) { + write_fp(i, 0); + } write_gp(2_reg, SP_INIT.get_raw()); // initialize to safe RAM area - // corresponds to Linux } diff --git a/src/machine/registers.h b/src/machine/registers.h index d56c242a..a367a26c 100644 --- a/src/machine/registers.h +++ b/src/machine/registers.h @@ -16,6 +16,11 @@ namespace machine { */ constexpr size_t REGISTER_COUNT = 32; +/** + * Float register count + */ +constexpr size_t FLOAT_REGISTER_COUNT = 32; + /** * General-purpose register identifier */ @@ -63,6 +68,9 @@ class Registers : public QObject { void write_gp(RegisterId reg, RegisterValue value); // Write general-purpose // register + RegisterValue read_fp(RegisterId reg) const; // Read floating-point register + void write_fp(RegisterId reg, RegisterValue value); // Write floating-point register + bool operator==(const Registers &c) const; bool operator!=(const Registers &c) const; @@ -72,6 +80,7 @@ class Registers : public QObject { void pc_update(Address val); void gp_update(RegisterId reg, RegisterValue val); void gp_read(RegisterId reg, RegisterValue val) const; + void fp_update(RegisterId reg, RegisterValue val); private: /** @@ -81,6 +90,10 @@ class Registers : public QObject { * Getters and setters will never try to read or write zero register. */ std::array gp {}; + /** + * Float registers + */ + std::array fp {}; Address pc {}; // program counter }; From 432daf66cbd289c24aea594f300309c8bec669db Mon Sep 17 00:00:00 2001 From: trdthg Date: Tue, 7 May 2024 08:40:59 +0000 Subject: [PATCH 2/3] update testcase --- tests/cli/stalls/stdout.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cli/stalls/stdout.txt b/tests/cli/stalls/stdout.txt index d63a1a66..561c370d 100644 --- a/tests/cli/stalls/stdout.txt +++ b/tests/cli/stalls/stdout.txt @@ -2,4 +2,4 @@ Machine stopped on BREAK exception. Machine state report: PC:0x00000244 R0:0x00000000 R1:0x00000011 R2:0x00000022 R3:0x00000033 R4:0x00000000 R5:0x00000055 R6:0x00000000 R7:0x00000000 R8:0x00000000 R9:0x00000000 R10:0x00000000 R11:0x00000000 R12:0x00000000 R13:0x00000000 R14:0x00000000 R15:0x00000000 R16:0x00000000 R17:0x00000000 R18:0x00000000 R19:0x00000000 R20:0x00000000 R21:0x00000011 R22:0x00000022 R23:0x00000033 R24:0x00000044 R25:0x00000055 R26:0x00000000 R27:0x00000000 R28:0x00000000 R29:0x00000000 R30:0x00000000 R31:0x00000000 -cycle: 0x0000000c mvendorid: 0x00000000 marchid: 0x00000000 mimpid: 0x00000000 mhardid: 0x00000000 mstatus: 0x00000000 misa: 0x40001111 mie: 0x00000000 mtvec: 0x00000000 mscratch: 0x00000000 mepc: 0x00000240 mcause: 0x00000003 mtval: 0x00000000 mip: 0x00000000 mtinst: 0x00000000 mtval2: 0x00000000 mcycle: 0x0000000c minstret: 0x0000000b +cycle: 0x0000000c mvendorid: 0x00000000 marchid: 0x00000000 mimpid: 0x00000000 mhardid: 0x00000000 mstatus: 0x00000000 misa: 0x40001131 mie: 0x00000000 mtvec: 0x00000000 mscratch: 0x00000000 mepc: 0x00000240 mcause: 0x00000003 mtval: 0x00000000 mip: 0x00000000 mtinst: 0x00000000 mtval2: 0x00000000 mcycle: 0x0000000c minstret: 0x0000000b From 971ac6120b0bf09ed6bd5f76736444098d9f8075 Mon Sep 17 00:00:00 2001 From: Jingqing3948 <2351290287@qq.com> Date: Tue, 7 May 2024 23:44:09 +0800 Subject: [PATCH 3/3] implement flw, fsw, fadd.s, fsub.s --- src/machine/core.cpp | 11 +++++++++-- src/machine/execute/alu.cpp | 14 ++++++++++++++ src/machine/execute/alu.h | 17 +++++++++++++++++ src/machine/machineconfig.h | 2 +- src/machine/pipeline.h | 5 +++++ src/machine/register_value.h | 6 +++++- 6 files changed, 51 insertions(+), 4 deletions(-) diff --git a/src/machine/core.cpp b/src/machine/core.cpp index 39d32aff..de11b998 100644 --- a/src/machine/core.cpp +++ b/src/machine/core.cpp @@ -366,7 +366,9 @@ DecodeState Core::decode(const FetchInterstage &dt) { .ff_rs = FORWARD_NONE, .ff_rt = FORWARD_NONE, .alu_component = (flags & IMF_AMO) ? AluComponent::PASS : - (flags & IMF_MUL) ? AluComponent::MUL : AluComponent::ALU, + (flags & IMF_MUL) ? AluComponent::MUL : + // AluComponent::ALU, + (flags & (IMF_ALU_REQ_RD_F | IMF_ALU_REQ_RS_F | IMF_ALU_REQ_RT_F)) == (IMF_ALU_REQ_RD_F | IMF_ALU_REQ_RS_F | IMF_ALU_REQ_RT_F) ? AluComponent::FALU : AluComponent::ALU, .aluop = alu_op, .memctl = mem_ctl, .num_rs = num_rs, @@ -376,8 +378,10 @@ DecodeState Core::decode(const FetchInterstage &dt) { .memwrite = bool(flags & IMF_MEMWRITE), .alusrc = bool(flags & IMF_ALUSRC), .regwrite = regwrite, + .regwrite_fp = bool(flags & IMF_ALU_REQ_RD_F), .alu_req_rs = bool(flags & IMF_ALU_REQ_RS), .alu_req_rt = bool(flags & IMF_ALU_REQ_RT), + .alu_fp = bool(flags & (IMF_ALU_REQ_RD_F | IMF_ALU_REQ_RS_F | IMF_ALU_REQ_RT_F)), // maybe not correct .branch_bxx = bool(flags & IMF_BRANCH), .branch_jal = bool(flags & IMF_JUMP), .branch_val = bool(flags & IMF_BJ_NOT), @@ -451,6 +455,8 @@ ExecuteState Core::execute(const DecodeInterstage &dt) { .memread = dt.memread, .memwrite = dt.memwrite, .regwrite = dt.regwrite, + .regwrite_fp = dt.regwrite_fp, + .alu_fp = dt.alu_fp, .is_valid = dt.is_valid, .branch_bxx = dt.branch_bxx, .branch_jal = dt.branch_jal, @@ -546,13 +552,14 @@ MemoryState Core::memory(const ExecuteInterstage &dt) { .num_rd = dt.num_rd, .memtoreg = memread, .regwrite = regwrite, + .regwrite_fp = dt.regwrite_fp, .is_valid = dt.is_valid, .csr_written = csr_written, } }; } WritebackState Core::writeback(const MemoryInterstage &dt) { - if (dt.regwrite) { regs->write_gp(dt.num_rd, dt.towrite_val); } + if (dt.regwrite) { (dt.regwrite_fp) ? regs->write_fp(dt.num_rd, dt.towrite_val) : regs->write_gp(dt.num_rd, dt.towrite_val); } return WritebackState { WritebackInternalState { .inst = (dt.excause == EXCAUSE_NONE)? dt.inst: Instruction::NOP, diff --git a/src/machine/execute/alu.cpp b/src/machine/execute/alu.cpp index 27364e25..7beb19e9 100644 --- a/src/machine/execute/alu.cpp +++ b/src/machine/execute/alu.cpp @@ -17,6 +17,9 @@ RegisterValue alu_combined_operate( : alu64_operate(op.alu_op, modified, a, b); case AluComponent::MUL: return (w_operation) ? mul32_operate(op.mul_op, a, b) : mul64_operate(op.mul_op, a, b); + case AluComponent::FALU: + // return (w_operation) ? alu32f_operate(op.alu_op, modified, a, b) : alu64f_operate(op.alu_op, modified, a, b); + return alu32f_operate(op.alu_op, modified, a, b); case AluComponent::PASS: return a; default: qDebug("ERROR, unknown alu component: %hhx", uint8_t(component)); return 0; @@ -74,6 +77,17 @@ int32_t alu32_operate(AluOp op, bool modified, RegisterValue a, RegisterValue b) } } +int32_t alu32f_operate(AluOp op, bool modified, RegisterValue a, RegisterValue b) { + return alu32_operate(op, modified, a, b); + // switch (op) { + // case AluOp::ADD: { + // float result = (a.as_f32()) + ((modified) ? - (b.as_f32()) : (b.as_f32())); + // return *reinterpret_cast(&result); + // } + // default: qDebug("ERROR, unknown alu operation: %hhx", uint8_t(op)); return 0; + // } +} + int64_t mul64_operate(MulOp op, RegisterValue a, RegisterValue b) { switch (op) { case MulOp::MUL: return a.as_u64() * b.as_u64(); diff --git a/src/machine/execute/alu.h b/src/machine/execute/alu.h index e787f173..96943e76 100644 --- a/src/machine/execute/alu.h +++ b/src/machine/execute/alu.h @@ -15,6 +15,7 @@ namespace machine { enum class AluComponent { ALU, //> RV32/64I MUL, //> RV32/64M + FALU, //> RV32/64F PASS, //> Pass operand A without change (used for AMO) }; @@ -74,6 +75,22 @@ union AluCombinedOp { */ [[gnu::const]] int32_t alu32_operate(AluOp op, bool modified, RegisterValue a, RegisterValue b); +/** + * RV32F for OP and OP-IMM instructions and RV64F OP-32 and OP-IMM-32 + * + * ALU conforming to Base Integer Instruction Set, Version 2.0. + * + * @param op operation specifier (funct3 in instruction) + * @param modified modifies behavior of ADD (to SUB) and SRL (to SRA) + * encoded by bit 30 if applicable + * @param a operand 1 + * @param b operand 2 + * @return result of specified ALU operation (always, no traps) + * integer type is returned to ensure correct signe extension + * to arbitrary implementation of RegisterValue + */ +[[gnu::const]] int32_t alu32f_operate(AluOp op, bool modified, RegisterValue a, RegisterValue b); + /** * RV64 "M" for OP instructions * diff --git a/src/machine/machineconfig.h b/src/machine/machineconfig.h index 74254494..5e589a79 100644 --- a/src/machine/machineconfig.h +++ b/src/machine/machineconfig.h @@ -27,7 +27,7 @@ enum ConfigPresets { }; constexpr ConfigIsaWord config_isa_word_default = ConfigIsaWord::byChar('E') | ConfigIsaWord::byChar('I') | - ConfigIsaWord::byChar('A') |ConfigIsaWord::byChar('M'); + ConfigIsaWord::byChar('A') | ConfigIsaWord::byChar('M') | ConfigIsaWord::byChar('F'); constexpr ConfigIsaWord config_isa_word_fixed = ConfigIsaWord::byChar('E') | ConfigIsaWord::byChar('I'); diff --git a/src/machine/pipeline.h b/src/machine/pipeline.h index 92b1a74b..230447d8 100644 --- a/src/machine/pipeline.h +++ b/src/machine/pipeline.h @@ -102,8 +102,10 @@ struct DecodeInterstage { bool memwrite = false; // If memory should write input bool alusrc = false; // If second value to alu is immediate value (rt used otherwise) bool regwrite = false; // If output should be written back to register + bool regwrite_fp = false; // If output should be written back to floating point register bool alu_req_rs = false; // requires rs value for ALU bool alu_req_rt = false; // requires rt value for ALU or SW + bool alu_fp = false; // ALU operation is floating point bool branch_bxx = false; // branch instruction bool branch_jal = false; // jump bool branch_val = false; // negate branch condition @@ -170,6 +172,8 @@ struct ExecuteInterstage { bool memread = false; bool memwrite = false; bool regwrite = false; + bool regwrite_fp = false; + bool alu_fp = false; bool is_valid = false; bool branch_bxx = false; bool branch_jal = false; @@ -243,6 +247,7 @@ struct MemoryInterstage { RegisterId num_rd = 0; bool memtoreg = false; bool regwrite = false; + bool regwrite_fp = false; bool is_valid = false; bool csr_written = false; diff --git a/src/machine/register_value.h b/src/machine/register_value.h index 531fae80..d53b71bb 100644 --- a/src/machine/register_value.h +++ b/src/machine/register_value.h @@ -79,7 +79,9 @@ class RegisterValue { [[nodiscard]] constexpr inline int32_t as_i32() const { return (int32_t)data; }; - [[nodiscard]] constexpr inline uint32_t as_u32() const { return (uint32_t)data; }; + [[nodiscard]] constexpr inline uint32_t as_u32() const { return (uint32_t)data; }; + + [[nodiscard]] constexpr inline float as_f32() const { union { uint32_t u; float f; } u = {(uint32_t)data}; return u.f; }; [[nodiscard]] constexpr inline int64_t as_i64() const { return (int64_t)data; }; @@ -97,6 +99,8 @@ class RegisterValue { constexpr explicit operator uint32_t() const { return as_u32(); }; + constexpr explicit operator float() const { return as_f32(); }; + constexpr explicit operator int64_t() const { return as_i64(); }; constexpr explicit operator uint64_t() const { return as_u64(); };