parent
1b93e7f569
commit
a2a9c95546
|
@ -0,0 +1,128 @@
|
|||
/*!
|
||||
\file A_Instruction.h
|
||||
\brief Decode A extensions part of the RISC-V
|
||||
\author Màrius Montón
|
||||
\date December 2018
|
||||
*/
|
||||
|
||||
#ifndef A_INSTRUCTION__H
|
||||
#define A_INSTRUCTION__H
|
||||
|
||||
#include "systemc"
|
||||
|
||||
using namespace sc_core;
|
||||
using namespace sc_dt;
|
||||
using namespace std;
|
||||
|
||||
typedef enum {
|
||||
OP_A_LR,
|
||||
OP_A_SC,
|
||||
OP_A_AMOSWAP,
|
||||
OP_A_AMOADD,
|
||||
OP_A_AMOXOR,
|
||||
OP_A_AMOAND,
|
||||
OP_A_AMOOR,
|
||||
OP_A_AMOMIN,
|
||||
OP_A_AMOMAX,
|
||||
OP_A_AMOMINU,
|
||||
OP_A_AMOMAXU,
|
||||
|
||||
OP_A_ERROR
|
||||
} op_A_Codes;
|
||||
|
||||
|
||||
typedef enum {
|
||||
A_LR = 0b00010,
|
||||
A_SC = 0b00011,
|
||||
A_AMOSWAP = 0b00001,
|
||||
A_AMOADD = 0b00000,
|
||||
A_AMOXOR = 0b00100,
|
||||
A_AMOAND = 0b01100,
|
||||
A_AMOOR = 0b01000,
|
||||
A_AMOMIN = 0b10000,
|
||||
A_AMOMAX = 0b10100,
|
||||
A_AMOMINU = 0b11000,
|
||||
A_AMOMAXU = 0b11100,
|
||||
} A_Codes;
|
||||
|
||||
/**
|
||||
* @brief Instruction decoding and fields access
|
||||
*/
|
||||
class A_Instruction{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param instr Instruction to decode
|
||||
*/
|
||||
A_Instruction(sc_uint<32> instr);
|
||||
|
||||
/**
|
||||
* @brief Access to opcode field
|
||||
* @return return opcode field
|
||||
*/
|
||||
inline int32_t opcode() {
|
||||
return a_instr.range(31,27);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Access to rd field
|
||||
* @return rd field
|
||||
*/
|
||||
inline int32_t get_rd() {
|
||||
return a_instr.range(11, 7);
|
||||
}
|
||||
|
||||
inline void set_rd(int32_t value) {
|
||||
a_instr.range(11,7) = value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Access to rs1 field
|
||||
* @return rs1 field
|
||||
*/
|
||||
inline int32_t get_rs1() {
|
||||
return a_instr.range(19, 15);
|
||||
}
|
||||
|
||||
inline void set_rs1(int32_t value) {
|
||||
a_instr.range(19,15) = value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Access to rs2 field
|
||||
* @return rs2 field
|
||||
*/
|
||||
inline int32_t get_rs2() {
|
||||
return a_instr.range(24, 20);
|
||||
}
|
||||
|
||||
inline void set_rs2(int32_t value) {
|
||||
a_instr.range(24,20) = value;
|
||||
}
|
||||
|
||||
|
||||
inline int32_t get_funct3() {
|
||||
return a_instr.range(14, 12);
|
||||
}
|
||||
|
||||
inline void set_funct3(int32_t value) {
|
||||
a_instr.range(14,12) = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decodes opcode of instruction
|
||||
* @return opcode of instruction
|
||||
*/
|
||||
op_A_Codes decode();
|
||||
|
||||
inline void dump() {
|
||||
cout << hex << "0x" << a_instr << dec << endl;
|
||||
}
|
||||
private:
|
||||
sc_uint<32> a_instr;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -21,6 +21,7 @@
|
|||
#include "Instruction.h"
|
||||
#include "C_Instruction.h"
|
||||
#include "M_Instruction.h"
|
||||
#include "A_Instruction.h"
|
||||
|
||||
using namespace sc_core;
|
||||
using namespace sc_dt;
|
||||
|
@ -60,6 +61,8 @@ private:
|
|||
|
||||
bool process_m_instruction(Instruction &inst);
|
||||
|
||||
bool process_a_instruction(Instruction inst);
|
||||
|
||||
void CPU_thread(void);
|
||||
};
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#define SC_INCLUDE_DYNAMIC_PROCESSES
|
||||
|
||||
#include "systemc"
|
||||
|
||||
#include <set>
|
||||
#include "tlm.h"
|
||||
#include "tlm_utils/simple_initiator_socket.h"
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
|||
#include "Instruction.h"
|
||||
#include "C_Instruction.h"
|
||||
#include "M_Instruction.h"
|
||||
#include "A_Instruction.h"
|
||||
#include "Registers.h"
|
||||
#include "Log.h"
|
||||
|
||||
|
@ -102,8 +103,10 @@ public:
|
|||
|
||||
/*********************** Privileged Instructions ******************************/
|
||||
bool MRET(Instruction &inst);
|
||||
bool SRET(Instruction &inst);
|
||||
bool WFI(Instruction &inst);
|
||||
|
||||
bool SFENCE(Instruction &inst);
|
||||
|
||||
/* C Extensions */
|
||||
bool C_JR(Instruction &inst);
|
||||
bool C_MV(Instruction &inst);
|
||||
|
@ -134,6 +137,19 @@ public:
|
|||
bool M_REM(Instruction &inst);
|
||||
bool M_REMU(Instruction &inst);
|
||||
|
||||
/* A Extensinos */
|
||||
bool A_LR(Instruction &inst);
|
||||
bool A_SC(Instruction &inst);
|
||||
bool A_AMOSWAP(Instruction &inst);
|
||||
bool A_AMOADD(Instruction &inst);
|
||||
bool A_AMOXOR(Instruction &inst);
|
||||
bool A_AMOAND(Instruction &inst);
|
||||
bool A_AMOOR(Instruction &inst);
|
||||
bool A_AMOMIN(Instruction &inst);
|
||||
bool A_AMOMAX(Instruction &inst);
|
||||
bool A_AMOMINU(Instruction &inst);
|
||||
bool A_AMOMAXU(Instruction &inst);
|
||||
|
||||
bool NOP(Instruction &inst);
|
||||
|
||||
private:
|
||||
|
@ -142,6 +158,11 @@ private:
|
|||
|
||||
void RaiseException(uint32_t cause, uint32_t inst = 0);
|
||||
|
||||
std::set<uint32_t> TLB_A_Entries;
|
||||
|
||||
void TLB_reserve(uint32_t address);
|
||||
bool TLB_reserved(uint32_t address);
|
||||
|
||||
Registers *regs;
|
||||
Performance *perf;
|
||||
Log *log;
|
||||
|
|
|
@ -90,6 +90,7 @@ OP_URET,
|
|||
OP_SRET,
|
||||
OP_MRET,
|
||||
OP_WFI,
|
||||
OP_SFENCE,
|
||||
|
||||
OP_ERROR
|
||||
} opCodes;
|
||||
|
@ -158,6 +159,8 @@ typedef enum {
|
|||
SRET_F = 0b000100000010,
|
||||
MRET_F = 0b001100000010,
|
||||
WFI_F = 0b000100000101,
|
||||
SFENCE_F = 0b0001001,
|
||||
|
||||
ECALL_F3= 0b000,
|
||||
CSRRW = 0b001,
|
||||
CSRRS = 0b010,
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
#include "A_Instruction.h"
|
||||
|
||||
|
||||
A_Instruction::A_Instruction(sc_uint<32> instr) {
|
||||
a_instr = instr;
|
||||
}
|
||||
|
||||
op_A_Codes A_Instruction::decode() {
|
||||
|
||||
switch (opcode()) {
|
||||
case A_LR:
|
||||
return OP_A_LR;
|
||||
break;
|
||||
case A_SC:
|
||||
return OP_A_SC;
|
||||
break;
|
||||
case A_AMOSWAP:
|
||||
return OP_A_AMOSWAP;
|
||||
break;
|
||||
case A_AMOADD:
|
||||
return OP_A_AMOADD;
|
||||
break;
|
||||
case A_AMOXOR:
|
||||
return OP_A_AMOXOR;
|
||||
break;
|
||||
case A_AMOAND:
|
||||
return OP_A_AMOAND;
|
||||
break;
|
||||
case A_AMOOR:
|
||||
return OP_A_AMOOR;
|
||||
break;
|
||||
case A_AMOMIN:
|
||||
return OP_A_AMOMIN;
|
||||
break;
|
||||
case A_AMOMAX:
|
||||
return OP_A_AMOMAX;
|
||||
break;
|
||||
case A_AMOMINU:
|
||||
return OP_A_AMOMINU;
|
||||
break;
|
||||
case A_AMOMAXU:
|
||||
return OP_A_AMOMAXU;
|
||||
break;
|
||||
default:
|
||||
return OP_A_ERROR;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return OP_A_ERROR;
|
||||
}
|
73
src/CPU.cpp
73
src/CPU.cpp
|
@ -157,6 +157,56 @@ bool CPU::process_m_instruction(Instruction &inst) {
|
|||
return PC_not_affected;
|
||||
}
|
||||
|
||||
|
||||
bool CPU::process_a_instruction(Instruction inst) {
|
||||
bool PC_not_affected = true;
|
||||
|
||||
A_Instruction a_inst(inst.getInstr());
|
||||
|
||||
switch(a_inst.decode()) {
|
||||
case OP_A_LR:
|
||||
exec->A_LR(inst);
|
||||
break;
|
||||
case OP_A_SC:
|
||||
exec->A_SC(inst);
|
||||
break;
|
||||
case OP_A_AMOSWAP:
|
||||
exec->A_AMOSWAP(inst);
|
||||
break;
|
||||
case OP_A_AMOADD:
|
||||
exec->A_AMOADD(inst);
|
||||
break;
|
||||
case OP_A_AMOXOR:
|
||||
exec->A_AMOXOR(inst);
|
||||
break;
|
||||
case OP_A_AMOAND:
|
||||
exec->A_AMOAND(inst);
|
||||
break;
|
||||
case OP_A_AMOOR:
|
||||
exec->A_AMOOR(inst);
|
||||
break;
|
||||
case OP_A_AMOMIN:
|
||||
exec->A_AMOMIN(inst);
|
||||
break;
|
||||
case OP_A_AMOMAX:
|
||||
exec->A_AMOMAX(inst);
|
||||
break;
|
||||
case OP_A_AMOMINU:
|
||||
exec->A_AMOMINU(inst);
|
||||
break;
|
||||
case OP_A_AMOMAXU:
|
||||
exec->A_AMOMAXU(inst);
|
||||
break;
|
||||
default:
|
||||
std::cout << "A 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;
|
||||
|
||||
|
@ -280,17 +330,6 @@ bool CPU::process_base_instruction(Instruction &inst) {
|
|||
case OP_AND:
|
||||
exec->AND(inst);
|
||||
break;
|
||||
#if 0
|
||||
case OP_CSRRW:
|
||||
exec->CSRRW(inst);
|
||||
break;
|
||||
case OP_CSRRS:
|
||||
exec->CSRRS(inst);
|
||||
break;
|
||||
case OP_CSRRC:
|
||||
exec->CSRRC(inst);
|
||||
break;
|
||||
#endif
|
||||
case OP_FENCE:
|
||||
exec->FENCE(inst);
|
||||
break;
|
||||
|
@ -323,9 +362,16 @@ bool CPU::process_base_instruction(Instruction &inst) {
|
|||
exec->MRET(inst);
|
||||
PC_not_affected = false;
|
||||
break;
|
||||
case OP_SRET:
|
||||
exec->SRET(inst);
|
||||
PC_not_affected = false;
|
||||
break;
|
||||
case OP_WFI:
|
||||
exec->WFI(inst);
|
||||
break;
|
||||
case OP_SFENCE:
|
||||
exec->SFENCE(inst);
|
||||
break;
|
||||
default:
|
||||
std::cout << "Wrong instruction" << endl;
|
||||
inst.dump();
|
||||
|
@ -361,6 +407,7 @@ void CPU::CPU_thread(void) {
|
|||
|
||||
while(1) {
|
||||
/* Get new PC value */
|
||||
//cout << "CPU: PC 0x" << hex << (uint32_t) register_bank->getPC() << endl;
|
||||
trans->set_address( register_bank->getPC() );
|
||||
instr_bus->b_transport( *trans, delay);
|
||||
|
||||
|
@ -388,6 +435,10 @@ void CPU::CPU_thread(void) {
|
|||
PC_not_affected = process_m_instruction(inst);
|
||||
incPCby2 = false;
|
||||
break;
|
||||
case A_EXTENSION:
|
||||
PC_not_affected = process_a_instruction(inst);
|
||||
incPCby2 = false;
|
||||
break;
|
||||
default:
|
||||
std::cout << "Extension not implemented yet" << std::endl;
|
||||
inst.dump();
|
||||
|
|
390
src/Execute.cpp
390
src/Execute.cpp
|
@ -322,8 +322,9 @@ bool Execute::LW(Instruction &inst, bool c_extension) {
|
|||
regs->setValue(rd, data);
|
||||
|
||||
log->SC_log(Log::INFO) << dec << "C.LW: x"
|
||||
<< rs1 << " + " << imm << " (@0x" << hex
|
||||
<< mem_addr << dec << ") -> x" << rd << endl;
|
||||
<< rs1 << "(0x" << hex << regs->getValue(rs1) << ") + "
|
||||
<< dec << imm << " (@0x" << hex << mem_addr << dec << ") -> x" << rd << hex
|
||||
<< " (0x" << data << ")"<< endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -565,20 +566,22 @@ bool Execute::ORI(Instruction &inst) {
|
|||
|
||||
bool Execute::ANDI(Instruction &inst) {
|
||||
int rd, rs1;
|
||||
int32_t imm;
|
||||
uint32_t imm;
|
||||
uint32_t calc;
|
||||
uint32_t aux;
|
||||
|
||||
rd = inst.get_rd();
|
||||
rs1 = inst.get_rs1();
|
||||
imm = inst.get_imm_I();
|
||||
|
||||
calc = regs->getValue(rs1) & imm;
|
||||
aux = regs->getValue(rs1);
|
||||
calc = aux & imm;
|
||||
regs->setValue(rd, calc);
|
||||
|
||||
log->SC_log(Log::INFO) << "ANDI: x"
|
||||
<< rs1 << " AND "
|
||||
<< rs1 << "(0x" << hex << aux << ") AND 0x"
|
||||
<< imm << " -> x"
|
||||
<< rd << endl;
|
||||
<< dec << rd << "(0x" << hex << calc << ")" << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -662,12 +665,16 @@ bool Execute::ADD(Instruction &inst) {
|
|||
rs2 = inst.get_rs2();
|
||||
|
||||
calc = regs->getValue(rs1) + regs->getValue(rs2);
|
||||
|
||||
// log->SC_log(Log::INFO) << "ADD 0x" << hex << regs->getValue(rs1)
|
||||
// << " + 0x" << regs->getValue(rs2) << " = " << calc << endl;
|
||||
|
||||
regs->setValue(rd, calc);
|
||||
|
||||
log->SC_log(Log::INFO) << "ADD: x"
|
||||
log->SC_log(Log::INFO) << "ADD: x" << dec
|
||||
<< rs1 << " + x"
|
||||
<< rs2 << " -> x"
|
||||
<< rd << endl;
|
||||
<< rd << hex << "(0x" << calc << ")"<< endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -922,6 +929,7 @@ bool Execute::CSRRS(Instruction &inst) {
|
|||
csr = inst.get_csr();
|
||||
|
||||
if (rd == 0) {
|
||||
log->SC_log(Log::INFO) << "CSRRS with rd1 == 0, doing nothing." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -952,6 +960,7 @@ bool Execute::CSRRC(Instruction &inst) {
|
|||
csr = inst.get_csr();
|
||||
|
||||
if (rd == 0) {
|
||||
log->SC_log(Log::INFO) << "CSRRC with rd1 == 0, doing nothing." << endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1048,7 +1057,8 @@ bool Execute::CSRRCI(Instruction &inst) {
|
|||
|
||||
log->SC_log(Log::INFO) << "CSRRCI: CSR #"
|
||||
<< csr << " -> x" << rd
|
||||
<< ". x" << rs1 << " & CSR #" << csr << endl;
|
||||
<< ". x" << rs1 << " & CSR #" << csr
|
||||
<< "(0x" << hex << aux << ")"<< endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1066,6 +1076,16 @@ bool Execute::MRET(Instruction &inst) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Execute::SRET(Instruction &inst) {
|
||||
uint32_t new_pc = 0;
|
||||
|
||||
new_pc = regs->getCSR(CSR_SEPC);
|
||||
regs->setPC(new_pc);
|
||||
|
||||
log->SC_log(Log::INFO) << "SRET: PC <- 0x" << hex << new_pc << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Execute::WFI(Instruction &inst) {
|
||||
log->SC_log(Log::INFO) << "WFI" << endl;
|
||||
|
@ -1073,6 +1093,12 @@ bool Execute::WFI(Instruction &inst) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Execute::SFENCE(Instruction &inst) {
|
||||
log->SC_log(Log::INFO) << "SFENCE" << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**************************** C Instructions **********************************/
|
||||
|
||||
bool Execute::C_JR(Instruction &inst) {
|
||||
|
@ -1390,7 +1416,8 @@ bool Execute::C_SLLI(Instruction &inst) {
|
|||
|
||||
bool Execute::C_ANDI(Instruction &inst) {
|
||||
int rd, rs1;
|
||||
int32_t imm;
|
||||
uint32_t imm;
|
||||
uint32_t aux;
|
||||
uint32_t calc;
|
||||
|
||||
C_Instruction c_inst(inst.getInstr());
|
||||
|
@ -1399,11 +1426,12 @@ bool Execute::C_ANDI(Instruction &inst) {
|
|||
rs1 = c_inst.get_rs1p();
|
||||
imm = c_inst.get_imm_ADDI();
|
||||
|
||||
calc = regs->getValue(rs1) & imm;
|
||||
aux = regs->getValue(rs1);
|
||||
calc = aux & imm;
|
||||
regs->setValue(rd, calc);
|
||||
|
||||
log->SC_log(Log::INFO) << "C.ANDI: x"
|
||||
<< rs1 << " AND "
|
||||
<< rs1 << "(" << aux << ") AND "
|
||||
<< imm << " -> x"
|
||||
<< rd << endl;
|
||||
|
||||
|
@ -1719,6 +1747,329 @@ bool Execute::M_REMU(Instruction &inst) {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Execute::A_LR(Instruction &inst) {
|
||||
uint32_t mem_addr = 0;
|
||||
int rd, rs1, rs2;
|
||||
uint32_t data;
|
||||
|
||||
A_Instruction a_inst(inst.getInstr());
|
||||
|
||||
rd = a_inst.get_rd();
|
||||
rs1 = a_inst.get_rs1();
|
||||
rs2 = a_inst.get_rs2();
|
||||
|
||||
if (rs2 != 0) {
|
||||
cout << "ILEGAL INSTRUCTION, LR.W: rs2 != 0" << endl;
|
||||
RaiseException(EXCEPTION_CAUSE_ILLEGAL_INSTRUCTION);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
mem_addr = regs->getValue(rs1);
|
||||
data = readDataMem(mem_addr, 4);
|
||||
regs->setValue(rd, data);
|
||||
|
||||
TLB_reserve(mem_addr);
|
||||
|
||||
log->SC_log(Log::INFO) << dec << "LR.W: x"
|
||||
<< rs1 << " (@0x" << hex << mem_addr
|
||||
<< dec << ") -> x" << rd << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Execute::A_SC(Instruction &inst) {
|
||||
uint32_t mem_addr = 0;
|
||||
int rd, rs1, rs2;
|
||||
uint32_t data;
|
||||
|
||||
A_Instruction a_inst(inst.getInstr());
|
||||
|
||||
rd = a_inst.get_rd();
|
||||
rs1 = a_inst.get_rs1();
|
||||
rs2 = a_inst.get_rs2();
|
||||
|
||||
mem_addr = regs->getValue(rs1);
|
||||
data = regs->getValue(rs2);
|
||||
|
||||
if (TLB_reserved(mem_addr) == true) {
|
||||
writeDataMem(mem_addr, data, 4);
|
||||
regs->setValue(rd, 0); // SC writes 0 to rd on success
|
||||
} else {
|
||||
regs->setValue(rd, 1); // SC writes nonzero on failure
|
||||
}
|
||||
|
||||
log->SC_log(Log::INFO) << dec << "SC.W: (@0x" <<
|
||||
hex << mem_addr << dec << ") <- x" << rs2 <<
|
||||
hex << "(0x" << data << ")" << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Execute::A_AMOSWAP(Instruction &inst) {
|
||||
uint32_t mem_addr = 0;
|
||||
int rd, rs1, rs2;
|
||||
uint32_t data;
|
||||
uint32_t aux;
|
||||
|
||||
A_Instruction a_inst(inst.getInstr());
|
||||
|
||||
/* These instructions must be atomic */
|
||||
|
||||
rd = a_inst.get_rd();
|
||||
rs1 = a_inst.get_rs1();
|
||||
rs2 = a_inst.get_rs2();
|
||||
|
||||
mem_addr = regs->getValue(rs1);
|
||||
data = readDataMem(mem_addr, 4);
|
||||
|
||||
regs->setValue(rd, data);
|
||||
|
||||
// swap
|
||||
aux = regs->getValue(rs2);
|
||||
regs->setValue(rs2, data);
|
||||
|
||||
writeDataMem(mem_addr, aux, 4);
|
||||
|
||||
log->SC_log(Log::INFO) << dec << "AMOSWAP " << endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Execute::A_AMOADD(Instruction &inst) {
|
||||
uint32_t mem_addr = 0;
|
||||
int rd, rs1, rs2;
|
||||
uint32_t data;
|
||||
|
||||
A_Instruction a_inst(inst.getInstr());
|
||||
|
||||
/* These instructions must be atomic */
|
||||
|
||||
rd = a_inst.get_rd();
|
||||
rs1 = a_inst.get_rs1();
|
||||
rs2 = a_inst.get_rs2();
|
||||
|
||||
mem_addr = regs->getValue(rs1);
|
||||
data = readDataMem(mem_addr, 4);
|
||||
|
||||
regs->setValue(rd, data);
|
||||
|
||||
// add
|
||||
data = data + regs->getValue(rs2);
|
||||
|
||||
writeDataMem(mem_addr, data, 4);
|
||||
|
||||
log->SC_log(Log::INFO) << dec << "AMOADD " << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Execute::A_AMOXOR(Instruction &inst) {
|
||||
uint32_t mem_addr = 0;
|
||||
int rd, rs1, rs2;
|
||||
uint32_t data;
|
||||
|
||||
A_Instruction a_inst(inst.getInstr());
|
||||
|
||||
/* These instructions must be atomic */
|
||||
|
||||
rd = a_inst.get_rd();
|
||||
rs1 = a_inst.get_rs1();
|
||||
rs2 = a_inst.get_rs2();
|
||||
|
||||
mem_addr = regs->getValue(rs1);
|
||||
data = readDataMem(mem_addr, 4);
|
||||
|
||||
regs->setValue(rd, data);
|
||||
|
||||
// add
|
||||
data = data ^ regs->getValue(rs2);
|
||||
|
||||
writeDataMem(mem_addr, data, 4);
|
||||
|
||||
log->SC_log(Log::INFO) << dec << "AMOXOR " << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
bool Execute::A_AMOAND(Instruction &inst) {
|
||||
uint32_t mem_addr = 0;
|
||||
int rd, rs1, rs2;
|
||||
uint32_t data;
|
||||
|
||||
A_Instruction a_inst(inst.getInstr());
|
||||
|
||||
/* These instructions must be atomic */
|
||||
|
||||
rd = a_inst.get_rd();
|
||||
rs1 = a_inst.get_rs1();
|
||||
rs2 = a_inst.get_rs2();
|
||||
|
||||
mem_addr = regs->getValue(rs1);
|
||||
data = readDataMem(mem_addr, 4);
|
||||
|
||||
regs->setValue(rd, data);
|
||||
|
||||
// add
|
||||
data = data & regs->getValue(rs2);
|
||||
|
||||
writeDataMem(mem_addr, data, 4);
|
||||
|
||||
log->SC_log(Log::INFO) << dec << "AMOAND " << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
bool Execute::A_AMOOR(Instruction &inst) {
|
||||
uint32_t mem_addr = 0;
|
||||
int rd, rs1, rs2;
|
||||
uint32_t data;
|
||||
|
||||
A_Instruction a_inst(inst.getInstr());
|
||||
|
||||
/* These instructions must be atomic */
|
||||
|
||||
rd = a_inst.get_rd();
|
||||
rs1 = a_inst.get_rs1();
|
||||
rs2 = a_inst.get_rs2();
|
||||
|
||||
mem_addr = regs->getValue(rs1);
|
||||
data = readDataMem(mem_addr, 4);
|
||||
|
||||
regs->setValue(rd, data);
|
||||
|
||||
// add
|
||||
data = data | regs->getValue(rs2);
|
||||
|
||||
writeDataMem(mem_addr, data, 4);
|
||||
|
||||
log->SC_log(Log::INFO) << dec << "AMOOR " << endl;
|
||||
return true;
|
||||
}
|
||||
bool Execute::A_AMOMIN(Instruction &inst) {
|
||||
uint32_t mem_addr = 0;
|
||||
int rd, rs1, rs2;
|
||||
uint32_t data;
|
||||
uint32_t aux;
|
||||
|
||||
A_Instruction a_inst(inst.getInstr());
|
||||
|
||||
/* These instructions must be atomic */
|
||||
|
||||
rd = a_inst.get_rd();
|
||||
rs1 = a_inst.get_rs1();
|
||||
rs2 = a_inst.get_rs2();
|
||||
|
||||
mem_addr = regs->getValue(rs1);
|
||||
data = readDataMem(mem_addr, 4);
|
||||
|
||||
regs->setValue(rd, data);
|
||||
|
||||
// min
|
||||
aux = regs->getValue(rs2);
|
||||
if ((int32_t)data < (int32_t)aux) {
|
||||
aux = data;
|
||||
}
|
||||
|
||||
writeDataMem(mem_addr, aux, 4);
|
||||
|
||||
log->SC_log(Log::INFO) << dec << "AMOMIN " << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
bool Execute::A_AMOMAX(Instruction &inst) {
|
||||
uint32_t mem_addr = 0;
|
||||
int rd, rs1, rs2;
|
||||
uint32_t data;
|
||||
uint32_t aux;
|
||||
|
||||
A_Instruction a_inst(inst.getInstr());
|
||||
|
||||
/* These instructions must be atomic */
|
||||
|
||||
rd = a_inst.get_rd();
|
||||
rs1 = a_inst.get_rs1();
|
||||
rs2 = a_inst.get_rs2();
|
||||
|
||||
mem_addr = regs->getValue(rs1);
|
||||
data = readDataMem(mem_addr, 4);
|
||||
|
||||
regs->setValue(rd, data);
|
||||
|
||||
// >
|
||||
aux = regs->getValue(rs2);
|
||||
if ((int32_t)data > (int32_t)aux) {
|
||||
aux = data;
|
||||
}
|
||||
|
||||
writeDataMem(mem_addr, aux, 4);
|
||||
|
||||
log->SC_log(Log::INFO) << dec << "AMOMAX " << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
bool Execute::A_AMOMINU(Instruction &inst) {
|
||||
uint32_t mem_addr = 0;
|
||||
int rd, rs1, rs2;
|
||||
uint32_t data;
|
||||
uint32_t aux;
|
||||
|
||||
A_Instruction a_inst(inst.getInstr());
|
||||
|
||||
/* These instructions must be atomic */
|
||||
|
||||
rd = a_inst.get_rd();
|
||||
rs1 = a_inst.get_rs1();
|
||||
rs2 = a_inst.get_rs2();
|
||||
|
||||
mem_addr = regs->getValue(rs1);
|
||||
data = readDataMem(mem_addr, 4);
|
||||
|
||||
regs->setValue(rd, data);
|
||||
|
||||
// min
|
||||
aux = regs->getValue(rs2);
|
||||
if (data < aux) {
|
||||
aux = data;
|
||||
}
|
||||
|
||||
writeDataMem(mem_addr, aux, 4);
|
||||
|
||||
log->SC_log(Log::INFO) << dec << "AMOMINU " << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
bool Execute::A_AMOMAXU(Instruction &inst) {
|
||||
uint32_t mem_addr = 0;
|
||||
int rd, rs1, rs2;
|
||||
uint32_t data;
|
||||
uint32_t aux;
|
||||
|
||||
A_Instruction a_inst(inst.getInstr());
|
||||
|
||||
/* These instructions must be atomic */
|
||||
|
||||
rd = a_inst.get_rd();
|
||||
rs1 = a_inst.get_rs1();
|
||||
rs2 = a_inst.get_rs2();
|
||||
|
||||
mem_addr = regs->getValue(rs1);
|
||||
data = readDataMem(mem_addr, 4);
|
||||
|
||||
regs->setValue(rd, data);
|
||||
|
||||
// max
|
||||
aux = regs->getValue(rs2);
|
||||
if (data > aux) {
|
||||
aux = data;
|
||||
}
|
||||
|
||||
writeDataMem(mem_addr, aux, 4);
|
||||
|
||||
log->SC_log(Log::INFO) << dec << "AMOMAXU " << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Execute::NOP(Instruction &inst) {
|
||||
cout << endl;
|
||||
regs->dump();
|
||||
|
@ -1805,3 +2156,18 @@ void Execute::RaiseException(uint32_t cause, uint32_t inst) {
|
|||
|
||||
log->SC_log(Log::INFO) << "Exception! new PC " << hex << new_pc << endl;
|
||||
}
|
||||
|
||||
|
||||
void Execute::TLB_reserve(uint32_t address) {
|
||||
TLB_A_Entries.insert(address);
|
||||
return;
|
||||
}
|
||||
|
||||
bool Execute::TLB_reserved(uint32_t address) {
|
||||
if (TLB_A_Entries.count(address) == 1) {
|
||||
TLB_A_Entries.erase(address);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,6 +130,11 @@ opCodes Instruction::decode() {
|
|||
return OP_MRET;
|
||||
case WFI_F:
|
||||
return OP_WFI;
|
||||
case SFENCE_F:
|
||||
return OP_SFENCE;
|
||||
}
|
||||
if (m_instr.range(31,25) == 0b0001001) {
|
||||
return OP_SFENCE;
|
||||
}
|
||||
break;
|
||||
case CSRRW:
|
||||
|
@ -162,6 +167,8 @@ extension_t Instruction::check_extension() {
|
|||
if ( (m_instr.range(6,0) == 0b0110011) &&
|
||||
(m_instr.range(31,25) == 0b0000001) ){
|
||||
return M_EXTENSION;
|
||||
} else if (m_instr.range(6,0) == 0b0101111) {
|
||||
return A_EXTENSION;
|
||||
} else if (m_instr.range(1,0) == 0b11) {
|
||||
return BASE_EXTENSION;
|
||||
} else if (m_instr.range(1,0) == 0b00) {
|
||||
|
@ -171,7 +178,6 @@ extension_t Instruction::check_extension() {
|
|||
} else if (m_instr.range(1,0) == 0b10) {
|
||||
return C_EXTENSION;
|
||||
} else if (m_instr.range(6,0) == 0b0101111) {
|
||||
cout << "check_extension A not yet implemented" << endl;
|
||||
return A_EXTENSION;
|
||||
} else {
|
||||
return UNKNOWN_EXTENSION;
|
||||
|
|
Loading…
Reference in New Issue