From d449ea5502b04b6b0d40ccf5b664a1d8457027cd Mon Sep 17 00:00:00 2001 From: mariusmonton Date: Mon, 12 Nov 2018 17:41:17 +0100 Subject: [PATCH] adding M extensions to simulator --- inc/CPU.h | 2 + inc/Execute.h | 11 ++++ inc/M_Instruction.h | 122 ++++++++++++++++++++++++++++++++++++++++++ src/CPU.cpp | 44 +++++++++++++++ src/Execute.cpp | 50 +++++++++++++++++ src/M_Instruction.cpp | 42 +++++++++++++++ 6 files changed, 271 insertions(+) create mode 100644 inc/M_Instruction.h create mode 100644 src/M_Instruction.cpp diff --git a/inc/CPU.h b/inc/CPU.h index 5843109..55abf53 100644 --- a/inc/CPU.h +++ b/inc/CPU.h @@ -20,6 +20,7 @@ #include "Log.h" #include "Instruction.h" #include "C_Instruction.h" +#include "M_Instruction.h" using namespace sc_core; using namespace sc_dt; @@ -57,6 +58,7 @@ private: bool process_c_instruction(Instruction &inst); + bool process_m_instruction(Instruction &inst); void CPU_thread(void); }; diff --git a/inc/Execute.h b/inc/Execute.h index 53de892..804b06c 100644 --- a/inc/Execute.h +++ b/inc/Execute.h @@ -17,6 +17,7 @@ #include "memory.h" #include "Instruction.h" #include "C_Instruction.h" +#include "M_Instruction.h" #include "Registers.h" #include "Log.h" @@ -111,6 +112,16 @@ public: void C_BNEZ(Instruction &inst); void C_LI(Instruction &inst); + /* M Extensinos */ + void M_MUL(Instruction &inst); + void M_MULH(Instruction &inst); + void M_MULHSU(Instruction &inst); + void M_MULHU(Instruction &inst); + void M_DIV(Instruction &inst); + void M_DIVU(Instruction &inst); + void M_REM(Instruction &inst); + void M_REMU(Instruction &inst); + void NOP(Instruction &inst); private: diff --git a/inc/M_Instruction.h b/inc/M_Instruction.h new file mode 100644 index 0000000..8beebd4 --- /dev/null +++ b/inc/M_Instruction.h @@ -0,0 +1,122 @@ +/*! + \file M_Instruction.h + \brief Decode M extensions part of the RISC-V + \author Màrius Montón + \date November 2018 +*/ + +#ifndef M_INSTRUCTION__H +#define M_INSTRUCTION__H + +#include "systemc" + +using namespace sc_core; +using namespace sc_dt; +using namespace std; + +typedef enum { +OP_M_MUL, +OP_M_MULH, +OP_M_MULHSU, +OP_M_MULHU, +OP_M_DIV, +OP_M_DIVU, +OP_M_REM, +OP_M_REMU, + +OP_M_ERROR +} op_M_Codes; + + +typedef enum { + M_MUL = 0b000, + M_MULH = 0b001, + M_MULHSU = 0b010, + M_MULHU = 0b011, + M_DIV = 0b100, + M_DIVU = 0b101, + M_REM = 0b110, + M_REMU = 0b111, +} M_Codes; + +/** + * @brief Instruction decoding and fields access + */ +class M_Instruction{ +public: + + /** + * @brief Constructor + * @param instr Instruction to decode + */ + M_Instruction(sc_uint<32> instr); + + /** + * @brief Access to opcode field + * @return return opcode field + */ + inline int32_t opcode() { + return m_instr.range(14,12); + } + + /** + * @brief Access to rd field + * @return rd field + */ + inline int32_t get_rd() { + return m_instr.range(11, 7); + } + + inline void set_rd(int32_t value) { + m_instr.range(11,7) = value; + } + + + /** + * @brief Access to rs1 field + * @return rs1 field + */ + inline int32_t get_rs1() { + return m_instr.range(19, 5); + } + + inline void set_rs1(int32_t value) { + m_instr.range(19,15) = value; + } + + + /** + * @brief Access to rs2 field + * @return rs2 field + */ + inline int32_t get_rs2() { + return m_instr.range(24, 20); + } + + inline void set_rs2(int32_t value) { + m_instr.range(24,20) = value; + } + + + inline int32_t get_funct3() { + return m_instr.range(14, 12); + } + + inline void set_funct3(int32_t value) { + m_instr.range(14,12) = value; + } + + /** + * @brief Decodes opcode of instruction + * @return opcode of instruction + */ + op_M_Codes decode(); + + inline void dump() { + cout << hex << "0x" << m_instr << dec << endl; + } +private: + sc_uint<32> m_instr; +}; + +#endif diff --git a/src/CPU.cpp b/src/CPU.cpp index 523f918..8141b1b 100644 --- a/src/CPU.cpp +++ b/src/CPU.cpp @@ -83,6 +83,46 @@ bool CPU::process_c_instruction(Instruction &inst) { return PC_not_affected; } +bool CPU::process_m_instruction(Instruction &inst) { + bool PC_not_affected = true; + + M_Instruction m_inst(inst.getInstr()); + + switch(m_inst.decode()) { + case OP_M_MUL: + exec->M_MUL(inst); + break; + case OP_M_MULH: + exec->M_MULH(inst); + break; + case OP_M_MULHSU: + exec->M_MULHSU(inst); + break; + case OP_M_MULHU: + exec->M_MULHU(inst); + break; + case OP_M_DIV: + exec->M_DIV(inst); + break; + case OP_M_DIVU: + exec->M_DIV(inst); + break; + case OP_M_REM: + exec->M_REM(inst); + break; + case OP_M_REMU: + exec->M_REMU(inst); + break; + default: + std::cout << "M instruction not implemented yet" << endl; + inst.dump(); + exec->NOP(inst); + break; + } + + return PC_not_affected; +} + bool CPU::process_base_instruction(Instruction &inst) { bool PC_not_affected = true; @@ -304,6 +344,10 @@ void CPU::CPU_thread(void) { PC_not_affected = process_c_instruction(inst); incPCby2 = true; break; + case M_EXTENSION: + PC_not_affected = process_m_instruction(inst); + incPCby2 = false; + break; default: std::cout << "Extension not implemented yet" << std::endl; inst.dump(); diff --git a/src/Execute.cpp b/src/Execute.cpp index 25b4435..f9505e9 100644 --- a/src/Execute.cpp +++ b/src/Execute.cpp @@ -1112,7 +1112,57 @@ void Execute::C_LI(Instruction &inst) { << imm << " -> x" << rd << "(" << calc << ")" << endl; } +/******************************************************************************/ +/* M Extensions */ +/******************************************************************************/ +void Execute::M_MUL(Instruction &inst) { + int rd, rs1, rs2; + int32_t multiplier, multiplicand; + int64_t result; + M_Instruction m_inst(inst.getInstr()); + + rd = m_inst.get_rd(); + rs1 = m_inst.get_rs1(); + rs2 = m_inst.get_rs2(); + + multiplier = regs->getValue(rs1); + multiplicand = regs->getValue(rs2); + + result = multiplier * multiplicand; + regs->setValue(rd, result & 0x00000000FFFFFFFF); + + log->SC_log(Log::INFO) << dec << "MUL: x" << rs1 << " * x" << rs2 + << " -> x" << rd << "(" << result << ")" << endl; +} + +void Execute::M_MULH(Instruction &inst) { + +} + +void Execute::M_MULHSU(Instruction &inst) { + +} + +void Execute::M_MULHU(Instruction &inst) { + +} + +void Execute::M_DIV(Instruction &inst) { + +} + +void Execute::M_DIVU(Instruction &inst) { + +} + +void Execute::M_REM(Instruction &inst) { + +} + +void Execute::M_REMU(Instruction &inst) { + +} void Execute::NOP(Instruction &inst) { cout << endl; diff --git a/src/M_Instruction.cpp b/src/M_Instruction.cpp new file mode 100644 index 0000000..7bc22b8 --- /dev/null +++ b/src/M_Instruction.cpp @@ -0,0 +1,42 @@ +#include "M_Instruction.h" + + +M_Instruction::M_Instruction(sc_uint<32> instr) { + m_instr = instr; +} + +op_M_Codes M_Instruction::decode() { + + switch (opcode()) { + case M_MUL: + return OP_M_MUL; + break; + case M_MULH: + return OP_M_MULH; + break; + case M_MULHSU: + return OP_M_MULHSU; + break; + case M_MULHU: + return OP_M_MULHU; + break; + case M_DIV: + return OP_M_DIV; + break; + case M_DIVU: + return OP_M_DIVU; + break; + case M_REM: + return OP_M_REM; + break; + case M_REMU: + return OP_M_REMU; + break; + default: + return OP_M_ERROR; + break; + + } + + return OP_M_ERROR; +}