Added instructions to pass riscv-tests
This commit is contained in:
parent
f17b3b75d5
commit
aa526943b9
|
@ -15,10 +15,11 @@
|
|||
#include "tlm_utils/simple_initiator_socket.h"
|
||||
|
||||
#include "memory.h"
|
||||
#include "Instruction.h"
|
||||
#include "Execute.h"
|
||||
#include "Registers.h"
|
||||
#include "Log.h"
|
||||
#include "Instruction.h"
|
||||
#include "C_Instruction.h"
|
||||
|
||||
using namespace sc_core;
|
||||
using namespace sc_dt;
|
||||
|
@ -52,10 +53,11 @@ private:
|
|||
* @param inst instruction to execute
|
||||
* @return true if PC is affected by instruction
|
||||
*/
|
||||
bool process_default_instruction(Instruction &inst);
|
||||
bool process_base_instruction(Instruction &inst);
|
||||
|
||||
bool process_c_instruction(Instruction &inst);
|
||||
|
||||
|
||||
|
||||
void CPU_thread(void);
|
||||
};
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "memory.h"
|
||||
#include "Instruction.h"
|
||||
#include "C_Instruction.h"
|
||||
#include "Registers.h"
|
||||
#include "Log.h"
|
||||
|
||||
|
@ -43,7 +44,7 @@ public:
|
|||
void LUI(Instruction &inst);
|
||||
void AUIPC(Instruction &inst);
|
||||
|
||||
void JAL(Instruction &inst);
|
||||
void JAL(Instruction &inst, bool c_extension = false, int m_rd = 1);
|
||||
void JALR(Instruction &inst);
|
||||
|
||||
void BEQ(Instruction &inst);
|
||||
|
@ -55,7 +56,7 @@ public:
|
|||
|
||||
void LB(Instruction &inst);
|
||||
void LH(Instruction &inst);
|
||||
void LW(Instruction &inst);
|
||||
void LW(Instruction &inst, bool c_extension = false);
|
||||
void LBU(Instruction &inst);
|
||||
void LHU(Instruction &inst);
|
||||
|
||||
|
@ -65,7 +66,7 @@ public:
|
|||
void SBU(Instruction &inst);
|
||||
void SHU(Instruction &inst);
|
||||
|
||||
void ADDI(Instruction &inst);
|
||||
void ADDI(Instruction &inst, bool c_extension = false);
|
||||
void SLTI(Instruction &inst);
|
||||
void SLTIU(Instruction &inst);
|
||||
void XORI(Instruction &inst);
|
||||
|
@ -87,6 +88,9 @@ public:
|
|||
void OR(Instruction &inst);
|
||||
void AND(Instruction &inst);
|
||||
|
||||
void FENCE(Instruction &inst);
|
||||
void ECALL(Instruction &inst);
|
||||
|
||||
void CSRRW(Instruction &inst);
|
||||
void CSRRS(Instruction &inst);
|
||||
void CSRRC(Instruction &inst);
|
||||
|
@ -94,6 +98,19 @@ public:
|
|||
void CSRRSI(Instruction &inst);
|
||||
void CSRRCI(Instruction &inst);
|
||||
|
||||
void MRET(Instruction &inst);
|
||||
|
||||
/* C Extensions */
|
||||
void C_JR(Instruction &inst);
|
||||
void C_MV(Instruction &inst);
|
||||
void C_LWSP(Instruction &inst);
|
||||
void C_ADDI4SPN(Instruction &inst);
|
||||
void C_ADDI16SP(Instruction &inst);
|
||||
void C_SWSP(Instruction &inst);
|
||||
void C_BEQZ(Instruction &inst);
|
||||
void C_BNEZ(Instruction &inst);
|
||||
void C_LI(Instruction &inst);
|
||||
|
||||
void NOP(Instruction &inst);
|
||||
|
||||
private:
|
||||
|
|
|
@ -14,6 +14,23 @@ using namespace sc_core;
|
|||
using namespace sc_dt;
|
||||
using namespace std;
|
||||
|
||||
typedef enum {
|
||||
BASE_EXTENSION,
|
||||
M_EXTENSION,
|
||||
A_EXTENSION,
|
||||
F_EXTENSION,
|
||||
D_EXTENSION,
|
||||
Q_EXTENSION,
|
||||
L_EXTENSION,
|
||||
C_EXTENSION,
|
||||
R_EXTENSION,
|
||||
J_EXTENSION,
|
||||
P_EXTENSION,
|
||||
V_EXTENSION,
|
||||
N_EXTENSION,
|
||||
UNKNOWN_EXTENSION
|
||||
} extension_t;
|
||||
|
||||
typedef enum {
|
||||
OP_LUI,
|
||||
OP_AUIPC,
|
||||
|
@ -58,6 +75,21 @@ OP_SRA,
|
|||
OP_OR,
|
||||
OP_AND,
|
||||
|
||||
OP_FENCE,
|
||||
OP_ECALL,
|
||||
OP_EBREAK,
|
||||
|
||||
OP_CSRRW,
|
||||
OP_CSRRS,
|
||||
OP_CSRRC,
|
||||
OP_CSRRWI,
|
||||
OP_CSRRSI,
|
||||
OP_CSRRCI,
|
||||
|
||||
OP_URET,
|
||||
OP_SRET,
|
||||
OP_MRET,
|
||||
|
||||
OP_ERROR
|
||||
} opCodes;
|
||||
|
||||
|
@ -116,6 +148,21 @@ typedef enum {
|
|||
SRA_F7 = 0b0100000,
|
||||
OR_F = 0b110,
|
||||
AND_F = 0b111,
|
||||
|
||||
FENCE = 0b0001111,
|
||||
ECALL = 0b1110011,
|
||||
ECALL_F = 0b000000000000,
|
||||
EBREAK_F= 0b000000000001,
|
||||
URET_F = 0b000000000010,
|
||||
SRET_F = 0b000100000010,
|
||||
MRET_F = 0b001100000010,
|
||||
ECALL_F3= 0b000,
|
||||
CSRRW = 0b001,
|
||||
CSRRS = 0b010,
|
||||
CSRRC = 0b011,
|
||||
CSRRWI = 0b101,
|
||||
CSRRSI = 0b110,
|
||||
CSRRCI = 0b111,
|
||||
} Codes;
|
||||
|
||||
/**
|
||||
|
@ -311,7 +358,11 @@ public:
|
|||
}
|
||||
|
||||
inline int32_t get_csr() {
|
||||
return get_imm_I();
|
||||
int32_t aux = 0;
|
||||
|
||||
aux = m_instr.range(31, 20);
|
||||
|
||||
return aux;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -320,6 +371,18 @@ public:
|
|||
*/
|
||||
opCodes decode();
|
||||
|
||||
/**
|
||||
* @brief returns what instruction extension
|
||||
* @return extension
|
||||
*/
|
||||
extension_t check_extension();
|
||||
|
||||
|
||||
uint32_t getInstr() {
|
||||
return m_instr;
|
||||
}
|
||||
|
||||
|
||||
inline void dump() {
|
||||
cout << hex << "0x" << m_instr << dec << endl;
|
||||
}
|
||||
|
|
|
@ -48,14 +48,12 @@ public:
|
|||
// *********************************************
|
||||
// TLM-2 forward DMI method
|
||||
// *********************************************
|
||||
|
||||
virtual bool get_direct_mem_ptr(tlm::tlm_generic_payload& trans,
|
||||
tlm::tlm_dmi& dmi_data);
|
||||
|
||||
// *********************************************
|
||||
// TLM-2 debug transport method
|
||||
// *********************************************
|
||||
|
||||
virtual unsigned int transport_dbg(tlm::tlm_generic_payload& trans);
|
||||
|
||||
private:
|
||||
|
|
117
src/CPU.cpp
117
src/CPU.cpp
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "CPU.h"
|
||||
|
||||
SC_HAS_PROCESS(CPU);
|
||||
|
@ -22,7 +21,69 @@ CPU::~CPU() {
|
|||
cout << "*********************************************" << endl;
|
||||
}
|
||||
|
||||
bool CPU::process_default_instruction(Instruction &inst) {
|
||||
bool CPU::process_c_instruction(Instruction &inst) {
|
||||
bool PC_not_affected = true;
|
||||
|
||||
C_Instruction c_inst(inst.getInstr());
|
||||
|
||||
switch(c_inst.decode()) {
|
||||
case OP_C_ADDI4SPN:
|
||||
exec->C_ADDI4SPN(inst);
|
||||
break;
|
||||
case OP_C_LW:
|
||||
exec->LW(inst, true);
|
||||
break;
|
||||
case OP_C_ADDI:
|
||||
exec->ADDI(inst, true);
|
||||
break;
|
||||
case OP_C_JAL:
|
||||
exec->JAL(inst, true, 1);
|
||||
PC_not_affected = false;
|
||||
break;
|
||||
case OP_C_J:
|
||||
exec->JAL(inst, true, 0);
|
||||
PC_not_affected = false;
|
||||
break;
|
||||
case OP_C_LI:
|
||||
exec->C_LI(inst);
|
||||
break;
|
||||
case OP_C_LWSP:
|
||||
exec->C_LWSP(inst);
|
||||
break;
|
||||
case OP_C_JR:
|
||||
exec->C_JR(inst);
|
||||
PC_not_affected = false;
|
||||
break;
|
||||
case OP_C_MV:
|
||||
exec->C_MV(inst);
|
||||
break;
|
||||
case OP_C_SWSP:
|
||||
exec->C_SWSP(inst);
|
||||
break;
|
||||
case OP_C_ADDI16SP:
|
||||
exec->C_ADDI16SP(inst);
|
||||
break;
|
||||
case OP_C_BEQZ:
|
||||
exec->C_BEQZ(inst);
|
||||
PC_not_affected = false;
|
||||
break;
|
||||
case OP_C_BNEZ:
|
||||
exec->C_BNEZ(inst);
|
||||
PC_not_affected = false;
|
||||
break;
|
||||
default:
|
||||
std::cout << "C instruction not implemented yet" << endl;
|
||||
inst.dump();
|
||||
exec->NOP(inst);
|
||||
//sc_stop();
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return PC_not_affected;
|
||||
}
|
||||
|
||||
bool CPU::process_base_instruction(Instruction &inst) {
|
||||
bool PC_not_affected = true;
|
||||
|
||||
switch(inst.decode()) {
|
||||
|
@ -156,7 +217,40 @@ bool CPU::process_default_instruction(Instruction &inst) {
|
|||
exec->CSRRC(inst);
|
||||
break;
|
||||
#endif
|
||||
case OP_FENCE:
|
||||
exec->FENCE(inst);
|
||||
break;
|
||||
case OP_ECALL:
|
||||
exec->ECALL(inst);
|
||||
break;
|
||||
case OP_CSRRW:
|
||||
exec->CSRRW(inst);
|
||||
break;
|
||||
case OP_CSRRS:
|
||||
exec->CSRRS(inst);
|
||||
break;
|
||||
case OP_CSRRC:
|
||||
exec->CSRRC(inst);
|
||||
break;
|
||||
case OP_CSRRWI:
|
||||
exec->CSRRWI(inst);
|
||||
break;
|
||||
case OP_CSRRSI:
|
||||
exec->CSRRSI(inst);
|
||||
break;
|
||||
case OP_CSRRCI:
|
||||
exec->CSRRCI(inst);
|
||||
break;
|
||||
|
||||
case OP_MRET:
|
||||
exec->MRET(inst);
|
||||
PC_not_affected = false;
|
||||
break;
|
||||
default:
|
||||
std::cout << "Wrong instruction" << endl;
|
||||
inst.dump();
|
||||
exec->NOP(inst);
|
||||
//sc_stop();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -173,6 +267,7 @@ void CPU::CPU_thread(void) {
|
|||
uint32_t INSTR;
|
||||
sc_time delay = SC_ZERO_TIME;
|
||||
bool PC_not_affected;
|
||||
bool incPCby2 = false;
|
||||
|
||||
trans->set_command( tlm::TLM_READ_COMMAND );
|
||||
trans->set_data_ptr( reinterpret_cast<unsigned char*>(&INSTR) );
|
||||
|
@ -197,14 +292,26 @@ void CPU::CPU_thread(void) {
|
|||
log->SC_log(Log::INFO) << "PC: " << hex << register_bank->getPC()
|
||||
<< dec << endl;
|
||||
|
||||
|
||||
Instruction inst(INSTR);
|
||||
|
||||
/* check what type of instruction is and execute it */
|
||||
switch(inst.check_extension()) {
|
||||
case BASE_EXTENSION:
|
||||
PC_not_affected = process_base_instruction(inst);
|
||||
incPCby2 = false;
|
||||
break;
|
||||
case C_EXTENSION:
|
||||
PC_not_affected = process_c_instruction(inst);
|
||||
incPCby2 = true;
|
||||
break;
|
||||
default:
|
||||
std::cout << "Extension not implemented yet" << std::endl;
|
||||
inst.dump();
|
||||
exec->NOP(inst);
|
||||
}
|
||||
|
||||
|
||||
|
||||
PC_not_affected = process_default_instruction(inst);
|
||||
|
||||
|
||||
// default:
|
||||
|
@ -215,7 +322,7 @@ void CPU::CPU_thread(void) {
|
|||
perf->instructionsInc();
|
||||
|
||||
if (PC_not_affected == true) {
|
||||
register_bank->incPC();
|
||||
register_bank->incPC(incPCby2);
|
||||
}
|
||||
} // while(1)
|
||||
} // CPU_thread
|
||||
|
|
348
src/Execute.cpp
348
src/Execute.cpp
|
@ -30,28 +30,39 @@ void Execute::AUIPC(Instruction &inst) {
|
|||
imm = inst.get_imm_U() << 12;
|
||||
new_pc = regs->getPC() + imm;
|
||||
|
||||
regs->setPC(new_pc);
|
||||
regs->setValue(rd, new_pc);
|
||||
|
||||
log->SC_log(Log::INFO) << "AUIPC x" << rd << " + PC -> PC (" << new_pc << ")" << endl;
|
||||
}
|
||||
|
||||
void Execute::JAL(Instruction &inst) {
|
||||
void Execute::JAL(Instruction &inst, bool c_extension, int m_rd) {
|
||||
int32_t mem_addr = 0;
|
||||
int rd;
|
||||
int new_pc, old_pc;
|
||||
|
||||
rd = inst.get_rd();
|
||||
mem_addr = inst.get_imm_J();
|
||||
if (c_extension == false) {
|
||||
rd = inst.get_rd();
|
||||
mem_addr = inst.get_imm_J();
|
||||
old_pc = regs->getPC();
|
||||
new_pc = old_pc + mem_addr;
|
||||
|
||||
old_pc = regs->getPC();
|
||||
regs->setPC(new_pc);
|
||||
|
||||
old_pc = old_pc + 4;
|
||||
regs->setValue(rd, old_pc);
|
||||
} else {
|
||||
C_Instruction c_inst(inst.getInstr());
|
||||
|
||||
new_pc = old_pc + mem_addr;
|
||||
regs->setPC(new_pc);
|
||||
rd = m_rd;
|
||||
mem_addr = c_inst.get_imm_J();
|
||||
old_pc = regs->getPC();
|
||||
|
||||
old_pc = old_pc + 4;
|
||||
regs->setValue(rd, old_pc);
|
||||
new_pc = old_pc + mem_addr;
|
||||
regs->setPC(new_pc);
|
||||
|
||||
old_pc = old_pc + 2;
|
||||
regs->setValue(rd, old_pc);
|
||||
}
|
||||
|
||||
log->SC_log(Log::INFO) << dec << "JAL: x" << rd << " <- 0x" << hex << old_pc
|
||||
<< dec << " PC + " << mem_addr << " -> PC (0x"
|
||||
|
@ -226,21 +237,29 @@ void Execute::LH(Instruction &inst) {
|
|||
<< hex <<mem_addr << dec << ") -> x" << rd << endl;
|
||||
}
|
||||
|
||||
void Execute::LW(Instruction &inst) {
|
||||
void Execute::LW(Instruction &inst, bool c_extension) {
|
||||
uint32_t mem_addr = 0;
|
||||
int rd, rs1;
|
||||
int32_t imm = 0;
|
||||
uint32_t data;
|
||||
|
||||
rd = inst.get_rd();
|
||||
rs1 = inst.get_rs1();
|
||||
imm = inst.get_imm_I();
|
||||
if (c_extension == false) {
|
||||
rd = inst.get_rd();
|
||||
rs1 = inst.get_rs1();
|
||||
imm = inst.get_imm_I();
|
||||
} else {
|
||||
C_Instruction c_inst(inst.getInstr());
|
||||
|
||||
rd = c_inst.get_rdp();
|
||||
rs1 = c_inst.get_rs1p();
|
||||
imm = c_inst.get_imm_L();
|
||||
}
|
||||
|
||||
mem_addr = imm + regs->getValue(rs1);
|
||||
data = readDataMem(mem_addr, 4);
|
||||
regs->setValue(rd, data);
|
||||
|
||||
log->SC_log(Log::INFO) << "LW: x" << rs1 << " + " << imm << " (@0x"
|
||||
log->SC_log(Log::INFO) << "C.LW: x" << rs1 << " + " << imm << " (@0x"
|
||||
<< hex <<mem_addr << dec << ") -> x" << rd << endl;
|
||||
}
|
||||
|
||||
|
@ -338,14 +357,22 @@ void Execute::SW(Instruction &inst) {
|
|||
<< " (@0x" << hex << mem_addr << dec << ")" << endl;
|
||||
}
|
||||
|
||||
void Execute::ADDI(Instruction &inst) {
|
||||
void Execute::ADDI(Instruction &inst, bool c_extension) {
|
||||
int rd, rs1;
|
||||
int32_t imm = 0;
|
||||
int32_t calc;
|
||||
|
||||
rd = inst.get_rd();
|
||||
rs1 = inst.get_rs1();
|
||||
imm = inst.get_imm_I();
|
||||
if (c_extension == false) {
|
||||
rd = inst.get_rd();
|
||||
rs1 = inst.get_rs1();
|
||||
imm = inst.get_imm_I();
|
||||
} else {
|
||||
C_Instruction c_inst(inst.getInstr());
|
||||
|
||||
rd = c_inst.get_rd();
|
||||
rs1 = rd;
|
||||
imm = c_inst.get_imm_I();
|
||||
}
|
||||
|
||||
calc = regs->getValue(rs1) + imm;
|
||||
regs->setValue(rd, calc);
|
||||
|
@ -658,6 +685,20 @@ void Execute::AND(Instruction &inst) {
|
|||
<< "-> x" << rd << endl;
|
||||
}
|
||||
|
||||
void Execute::FENCE(Instruction &inst) {
|
||||
log->SC_log(Log::INFO) << "FENCE" << endl;
|
||||
}
|
||||
|
||||
void Execute::ECALL(Instruction &inst) {
|
||||
|
||||
log->SC_log(Log::INFO) << "ECALL" << endl;
|
||||
std::cout << "ECALL Instruction called, stopping simulation" << endl;
|
||||
regs->dump();
|
||||
cout << "Simulation time " << sc_time_stamp() << endl;
|
||||
perf->dump();
|
||||
|
||||
SC_REPORT_ERROR("Execute", "ECALL");
|
||||
}
|
||||
void Execute::CSRRW(Instruction &inst) {
|
||||
int rd, rs1;
|
||||
int csr;
|
||||
|
@ -667,13 +708,11 @@ void Execute::CSRRW(Instruction &inst) {
|
|||
rs1 = inst.get_rs1();
|
||||
csr = inst.get_csr();
|
||||
|
||||
if (rd == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* These operations must be atomical */
|
||||
aux = regs->getCSR(csr);
|
||||
regs->setValue(rd, aux);
|
||||
if (rd != 0) {
|
||||
aux = regs->getCSR(csr);
|
||||
regs->setValue(rd, aux);
|
||||
}
|
||||
aux = regs->getValue(rs1);
|
||||
regs->setCSR(csr, aux);
|
||||
|
||||
|
@ -731,6 +770,267 @@ void Execute::CSRRC(Instruction &inst) {
|
|||
<< ". x" << rs1 << " & CSR #" << csr << endl;
|
||||
}
|
||||
|
||||
void Execute::CSRRWI(Instruction &inst) {
|
||||
int rd, rs1;
|
||||
int csr;
|
||||
uint32_t aux;
|
||||
|
||||
rd = inst.get_rd();
|
||||
rs1 = inst.get_rs1();
|
||||
csr = inst.get_csr();
|
||||
|
||||
|
||||
/* These operations must be atomical */
|
||||
if (rd != 0) {
|
||||
aux = regs->getCSR(csr);
|
||||
regs->setValue(rd, aux);
|
||||
}
|
||||
aux = rs1;
|
||||
regs->setCSR(csr, aux);
|
||||
|
||||
log->SC_log(Log::INFO) << "CSRRWI: CSR #" << csr << " -> x" << rd
|
||||
<< ". x" << rs1 << "-> CSR #" << csr << endl;
|
||||
}
|
||||
|
||||
void Execute::CSRRSI(Instruction &inst) {
|
||||
int rd, rs1;
|
||||
int csr;
|
||||
uint32_t bitmask, aux;
|
||||
|
||||
rd = inst.get_rd();
|
||||
rs1 = inst.get_rs1();
|
||||
csr = inst.get_csr();
|
||||
|
||||
if (rs1 == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* These operations must be atomical */
|
||||
aux = regs->getCSR(csr);
|
||||
regs->setValue(rd, aux);
|
||||
|
||||
bitmask = rs1;
|
||||
aux = aux | bitmask;
|
||||
regs->setCSR(csr, aux);
|
||||
|
||||
log->SC_log(Log::INFO) << "CSRRSI: CSR #" << csr << " -> x" << rd
|
||||
<< ". x" << rs1 << " & CSR #" << csr << endl;
|
||||
}
|
||||
|
||||
void Execute::CSRRCI(Instruction &inst) {
|
||||
int rd, rs1;
|
||||
int csr;
|
||||
uint32_t bitmask, aux;
|
||||
|
||||
rd = inst.get_rd();
|
||||
rs1 = inst.get_rs1();
|
||||
csr = inst.get_csr();
|
||||
|
||||
if (rs1 == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* These operations must be atomical */
|
||||
aux = regs->getCSR(csr);
|
||||
regs->setValue(rd, aux);
|
||||
|
||||
bitmask = rs1;
|
||||
aux = aux & ~bitmask;
|
||||
regs->setCSR(csr, aux);
|
||||
|
||||
log->SC_log(Log::INFO) << "CSRRCI: CSR #" << csr << " -> x" << rd
|
||||
<< ". x" << rs1 << " & CSR #" << csr << endl;
|
||||
}
|
||||
|
||||
void Execute::MRET(Instruction &inst) {
|
||||
uint32_t new_pc = 0;
|
||||
|
||||
new_pc = regs->getCSR(0x341);
|
||||
regs->setPC(new_pc);
|
||||
|
||||
log->SC_log(Log::INFO) << "MRET: PC <- 0x" << hex << new_pc << endl;
|
||||
}
|
||||
|
||||
void Execute::C_JR(Instruction &inst) {
|
||||
uint32_t mem_addr = 0;
|
||||
int rd, rs1;
|
||||
int new_pc, old_pc;
|
||||
|
||||
C_Instruction c_inst(inst.getInstr());
|
||||
|
||||
rd = 0;
|
||||
rs1 = c_inst.get_rs1();
|
||||
mem_addr = 0;
|
||||
|
||||
std::cout << "rs1 :" << rs1 << std::endl;
|
||||
old_pc = regs->getPC();
|
||||
regs->setValue(rd, old_pc + 4);
|
||||
|
||||
|
||||
new_pc = (regs->getValue(rs1) + mem_addr) & 0xFFFFFFFE;
|
||||
regs->setPC(new_pc);
|
||||
|
||||
log->SC_log(Log::INFO) << "JR: x" << dec << rd << " <- 0x" << hex << old_pc + 4
|
||||
<< " PC <- 0x" << hex << new_pc << endl;
|
||||
}
|
||||
|
||||
void Execute::C_MV(Instruction &inst) {
|
||||
int rd, rs1, rs2;
|
||||
uint32_t calc;
|
||||
|
||||
C_Instruction c_inst(inst.getInstr());
|
||||
|
||||
rd = c_inst.get_rd();
|
||||
rs1 = 0;
|
||||
rs2 = c_inst.get_rs2();
|
||||
|
||||
calc = regs->getValue(rs1) + regs->getValue(rs2);
|
||||
regs->setValue(rd, calc);
|
||||
|
||||
log->SC_log(Log::INFO) << "MV: x" << rs1 << " + x" << rs2 << " -> x" << rd << endl;
|
||||
}
|
||||
|
||||
void Execute::C_LWSP(Instruction &inst) {
|
||||
uint32_t mem_addr = 0;
|
||||
int rd, rs1;
|
||||
int32_t imm = 0;
|
||||
uint32_t data;
|
||||
|
||||
C_Instruction c_inst(inst.getInstr());
|
||||
|
||||
rd = c_inst.get_rd();
|
||||
rs1 = c_inst.get_rs1();
|
||||
imm = c_inst.get_imm_LWSP();
|
||||
|
||||
mem_addr = imm + regs->getValue(rs1);
|
||||
data = readDataMem(mem_addr, 4);
|
||||
regs->setValue(rd, data);
|
||||
|
||||
log->SC_log(Log::INFO) << "C.LWSP: x" << rs1 << " + " << imm << " (@0x"
|
||||
<< hex <<mem_addr << dec << ") -> x" << rd << endl;
|
||||
}
|
||||
|
||||
void Execute::C_ADDI4SPN(Instruction &inst) {
|
||||
int rd, rs1;
|
||||
int32_t imm = 0;
|
||||
int32_t calc;
|
||||
|
||||
C_Instruction c_inst(inst.getInstr());
|
||||
|
||||
rd = c_inst.get_rdp();
|
||||
rs1 = 2;
|
||||
imm = c_inst.get_imm_ADDI4SPN();
|
||||
|
||||
calc = regs->getValue(rs1) + imm;
|
||||
regs->setValue(rd, calc);
|
||||
|
||||
log->SC_log(Log::INFO) << dec << "ADDI4SPN: x" << rs1 << " + " << imm << " -> x" << rd << endl;
|
||||
}
|
||||
|
||||
void Execute::C_ADDI16SP(Instruction &inst) {
|
||||
// addi x2, x2, nzimm[9:4]
|
||||
int rd, rs1;
|
||||
int32_t imm = 0;
|
||||
int32_t calc;
|
||||
|
||||
C_Instruction c_inst(inst.getInstr());
|
||||
|
||||
rd = 2;
|
||||
rs1 = 2;
|
||||
imm = c_inst.get_imm_ADDI16SP();
|
||||
|
||||
|
||||
calc = regs->getValue(rs1) + imm;
|
||||
regs->setValue(rd, calc);
|
||||
|
||||
log->SC_log(Log::INFO) << dec << "ADDI16SP: x" << rs1 << " + " << imm << " -> x" << rd << endl;
|
||||
}
|
||||
|
||||
void Execute::C_SWSP(Instruction &inst) {
|
||||
// sw rs2, offset(x2)
|
||||
uint32_t mem_addr = 0;
|
||||
int rs1, rs2;
|
||||
int32_t imm = 0;
|
||||
uint32_t data;
|
||||
|
||||
C_Instruction c_inst(inst.getInstr());
|
||||
|
||||
rs1 = 2;
|
||||
rs2 = 2;
|
||||
imm = c_inst.get_imm_CSS();
|
||||
|
||||
mem_addr = imm + regs->getValue(rs1);
|
||||
data = regs->getValue(rs2);
|
||||
|
||||
writeDataMem(mem_addr, data, 4);
|
||||
|
||||
log->SC_log(Log::INFO) << "SWSP: x" << dec << rs2 << "(0x" << hex << data
|
||||
<< ") -> x" << dec << rs1 << " + " << imm
|
||||
<< " (@0x" << hex << mem_addr << dec << ")" << endl;
|
||||
|
||||
}
|
||||
|
||||
void Execute::C_BEQZ(Instruction &inst) {
|
||||
int rs1;
|
||||
int new_pc = 0;
|
||||
uint32_t val1;
|
||||
C_Instruction c_inst(inst.getInstr());
|
||||
|
||||
rs1 = c_inst.get_rs1p();
|
||||
val1 = regs->getValue(rs1);
|
||||
|
||||
if (val1 == 0) {
|
||||
new_pc = regs->getPC() + c_inst.get_imm_CB();
|
||||
regs->setPC(new_pc);
|
||||
} else {
|
||||
regs->incPC(true); //PC <- PC +2
|
||||
}
|
||||
|
||||
log->SC_log(Log::INFO) << "C.BEQZ: x" << rs1 << "(" << val1
|
||||
<< ") == 0? -> PC (" << new_pc << ")" << endl;
|
||||
}
|
||||
|
||||
void Execute::C_BNEZ(Instruction &inst) {
|
||||
int rs1;
|
||||
int new_pc = 0;
|
||||
uint32_t val1;
|
||||
C_Instruction c_inst(inst.getInstr());
|
||||
|
||||
rs1 = c_inst.get_rs1p();
|
||||
val1 = regs->getValue(rs1);
|
||||
|
||||
if (val1 != 0) {
|
||||
new_pc = regs->getPC() + c_inst.get_imm_CB();
|
||||
regs->setPC(new_pc);
|
||||
} else {
|
||||
regs->incPC(true); //PC <- PC +2
|
||||
}
|
||||
|
||||
log->SC_log(Log::INFO) << "C.BNEZ: x" << rs1 << "(" << val1
|
||||
<< ") == 0? -> PC (" << new_pc << ")" << endl;
|
||||
}
|
||||
|
||||
void Execute::C_LI(Instruction &inst) {
|
||||
|
||||
int rd, rs1;
|
||||
int32_t imm = 0;
|
||||
int32_t calc;
|
||||
|
||||
C_Instruction c_inst(inst.getInstr());
|
||||
|
||||
rd = c_inst.get_rd();
|
||||
rs1 = 0;
|
||||
imm = c_inst.get_imm_ADDI();
|
||||
|
||||
calc = regs->getValue(rs1) + imm;
|
||||
regs->setValue(rd, calc);
|
||||
|
||||
log->SC_log(Log::INFO) << dec << "LI: x" << rs1 << " + " << imm << " -> x" << rd << endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Execute::NOP(Instruction &inst) {
|
||||
cout << endl;
|
||||
regs->dump();
|
||||
|
|
|
@ -112,8 +112,64 @@ opCodes Instruction::decode() {
|
|||
return OP_AND;
|
||||
}
|
||||
} /* ADD */
|
||||
return OP_ERROR;
|
||||
case FENCE:
|
||||
return OP_FENCE;
|
||||
case ECALL: {
|
||||
switch (get_funct3()) {
|
||||
case ECALL_F3:
|
||||
switch(get_csr()) {
|
||||
case ECALL_F:
|
||||
return OP_ECALL;
|
||||
case EBREAK_F:
|
||||
return OP_EBREAK;
|
||||
case URET_F:
|
||||
return OP_URET;
|
||||
case SRET_F:
|
||||
return OP_SRET;
|
||||
case MRET_F:
|
||||
return OP_MRET;
|
||||
}
|
||||
break;
|
||||
case CSRRW:
|
||||
return OP_CSRRW;
|
||||
break;
|
||||
case CSRRS:
|
||||
return OP_CSRRS;
|
||||
break;
|
||||
case CSRRC:
|
||||
return OP_CSRRC;
|
||||
break;
|
||||
case CSRRWI:
|
||||
return OP_CSRRWI;
|
||||
break;
|
||||
case CSRRSI:
|
||||
return OP_CSRRSI;
|
||||
break;
|
||||
case CSRRCI:
|
||||
return OP_CSRRCI;
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
return OP_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension_t Instruction::check_extension() {
|
||||
if (m_instr.range(1,0) == 0b11) {
|
||||
return BASE_EXTENSION;
|
||||
} else if (m_instr.range(1,0) == 0b00) {
|
||||
return C_EXTENSION;
|
||||
} else if (m_instr.range(1,0) == 0b01) {
|
||||
return C_EXTENSION;
|
||||
} else if (m_instr.range(1,0) == 0b10) {
|
||||
return C_EXTENSION;
|
||||
} else if (m_instr.range(6,0) == 0b0110011) {
|
||||
return M_EXTENSION;
|
||||
} else if (m_instr.range(6,0) == 0b0101111) {
|
||||
return A_EXTENSION;
|
||||
} else {
|
||||
return UNKNOWN_EXTENSION;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
Registers::Registers() {
|
||||
|
||||
memset(register_bank, 0, sizeof(int32_t)*32); // 32 registers of 32 bits each
|
||||
memset(register_bank, 0, sizeof(uint32_t)*32); // 32 registers of 32 bits each
|
||||
memset(CSR, 0, sizeof(uint32_t)*4096);
|
||||
perf = Performance::getInstance();
|
||||
|
||||
register_bank[sp] = 1024-1; // SP points to end of memory
|
||||
|
|
Loading…
Reference in New Issue