adding M extensions to simulator
This commit is contained in:
parent
bdf261cbc6
commit
d449ea5502
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
44
src/CPU.cpp
44
src/CPU.cpp
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
Loading…
Reference in New Issue