adding M extensions to simulator

This commit is contained in:
mariusmonton 2018-11-12 17:41:17 +01:00
parent bdf261cbc6
commit d449ea5502
6 changed files with 271 additions and 0 deletions

View File

@ -20,6 +20,7 @@
#include "Log.h" #include "Log.h"
#include "Instruction.h" #include "Instruction.h"
#include "C_Instruction.h" #include "C_Instruction.h"
#include "M_Instruction.h"
using namespace sc_core; using namespace sc_core;
using namespace sc_dt; using namespace sc_dt;
@ -57,6 +58,7 @@ private:
bool process_c_instruction(Instruction &inst); bool process_c_instruction(Instruction &inst);
bool process_m_instruction(Instruction &inst);
void CPU_thread(void); void CPU_thread(void);
}; };

View File

@ -17,6 +17,7 @@
#include "memory.h" #include "memory.h"
#include "Instruction.h" #include "Instruction.h"
#include "C_Instruction.h" #include "C_Instruction.h"
#include "M_Instruction.h"
#include "Registers.h" #include "Registers.h"
#include "Log.h" #include "Log.h"
@ -111,6 +112,16 @@ public:
void C_BNEZ(Instruction &inst); void C_BNEZ(Instruction &inst);
void C_LI(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); void NOP(Instruction &inst);
private: private:

122
inc/M_Instruction.h Normal file
View File

@ -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

View File

@ -83,6 +83,46 @@ bool CPU::process_c_instruction(Instruction &inst) {
return PC_not_affected; 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 CPU::process_base_instruction(Instruction &inst) {
bool PC_not_affected = true; bool PC_not_affected = true;
@ -304,6 +344,10 @@ void CPU::CPU_thread(void) {
PC_not_affected = process_c_instruction(inst); PC_not_affected = process_c_instruction(inst);
incPCby2 = true; incPCby2 = true;
break; break;
case M_EXTENSION:
PC_not_affected = process_m_instruction(inst);
incPCby2 = false;
break;
default: default:
std::cout << "Extension not implemented yet" << std::endl; std::cout << "Extension not implemented yet" << std::endl;
inst.dump(); inst.dump();

View File

@ -1112,7 +1112,57 @@ void Execute::C_LI(Instruction &inst) {
<< imm << " -> x" << rd << "(" << calc << ")" << endl; << 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) { void Execute::NOP(Instruction &inst) {
cout << endl; cout << endl;

42
src/M_Instruction.cpp Normal file
View File

@ -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;
}