implementation of all remaining C extension

This commit is contained in:
mariusmonton 2018-11-19 15:56:08 +01:00
parent e67e8b2c08
commit ed7be704f9
7 changed files with 385 additions and 42 deletions

View File

@ -71,6 +71,14 @@ typedef enum {
C_LI = 0b010,
C_ADDI16SP = 0b011,
C_SRLI = 0b100,
C_2_SRLI = 0b00,
C_2_SRAI = 0b01,
C_2_ANDI = 0b10,
C_2_SUB = 0b11,
C_3_SUB = 0b00,
C_3_XOR = 0b01,
C_3_OR = 0b10,
C_3_AND = 0b11,
C_J = 0b101,
C_BEQZ = 0b110,
C_BNEZ = 0b111,
@ -118,7 +126,7 @@ public:
}
inline int32_t get_rdp() {
return m_instr.range(4, 2);
return m_instr.range(4, 2) + 8;
}
/**
@ -135,7 +143,7 @@ public:
inline int32_t get_rs1p() {
return m_instr.range(9, 7);
return m_instr.range(9, 7) + 8;
}
/**
@ -150,6 +158,9 @@ public:
m_instr.range(6,2) = value;
}
inline int32_t get_rs2p() {
return m_instr.range(4, 2) + 8;
}
inline int32_t get_funct3() {
return m_instr.range(15, 13);
@ -259,7 +270,7 @@ public:
aux |= m_instr[6] << 7;
aux |= m_instr.range(5,3) << 1;
aux |= m_instr[2] << 5;
if (m_instr[12] == 1) {
aux |= 0b1111 << 12;
}
@ -362,6 +373,19 @@ public:
return aux;
}
inline int32_t get_imm_LUI() {
int32_t aux = 0;
aux = m_instr[12] << 17;
aux |= m_instr.range(6,2) << 12;
if (m_instr[12] == 1) {
aux |= 0b111111111111111 << 17;
}
return aux;
}
inline int32_t get_csr() {
return get_imm_I();
}

View File

@ -46,7 +46,7 @@ public:
void AUIPC(Instruction &inst);
void JAL(Instruction &inst, bool c_extension = false, int m_rd = 1);
void JALR(Instruction &inst);
void JALR(Instruction &inst, bool c_extension = false);
void BEQ(Instruction &inst);
void BNE(Instruction &inst);
@ -63,7 +63,7 @@ public:
void SB(Instruction &inst);
void SH(Instruction &inst);
void SW(Instruction &inst);
void SW(Instruction &inst, bool c_extension = false);
void SBU(Instruction &inst);
void SHU(Instruction &inst);
@ -99,18 +99,29 @@ public:
void CSRRSI(Instruction &inst);
void CSRRCI(Instruction &inst);
/*********************** Privileged Instructions ******************************/
void MRET(Instruction &inst);
void WFI(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_SLLI(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 C_SRLI(Instruction &inst);
void C_SRAI(Instruction &inst);
void C_ANDI(Instruction &inst);
void C_ADD(Instruction &inst);
void C_SUB(Instruction &inst);
void C_XOR(Instruction &inst);
void C_OR(Instruction &inst);
void C_AND(Instruction &inst);
/* M Extensinos */
void M_MUL(Instruction &inst);

View File

@ -89,6 +89,7 @@ OP_CSRRCI,
OP_URET,
OP_SRET,
OP_MRET,
OP_WFI,
OP_ERROR
} opCodes;
@ -156,6 +157,7 @@ typedef enum {
URET_F = 0b000000000010,
SRET_F = 0b000100000010,
MRET_F = 0b001100000010,
WFI_F = 0b000100000101,
ECALL_F3= 0b000,
CSRRW = 0b001,
CSRRS = 0b010,
@ -182,7 +184,6 @@ public:
* @return return opcode field
*/
inline int32_t opcode() {
// cout << "OP: " << m_instr << endl;
return m_instr.range(6,0);
}

View File

@ -33,6 +33,9 @@ bool CPU::process_c_instruction(Instruction &inst) {
case OP_C_LW:
exec->LW(inst, true);
break;
case OP_C_SW:
exec->SW(inst, true);
break;
case OP_C_ADDI:
exec->ADDI(inst, true);
break;
@ -47,6 +50,9 @@ bool CPU::process_c_instruction(Instruction &inst) {
case OP_C_LI:
exec->C_LI(inst);
break;
case OP_C_SLLI:
exec->C_SLLI(inst);
break;
case OP_C_LWSP:
exec->C_LWSP(inst);
break;
@ -57,6 +63,13 @@ bool CPU::process_c_instruction(Instruction &inst) {
case OP_C_MV:
exec->C_MV(inst);
break;
case OP_C_JALR:
exec->JALR(inst, true);
PC_not_affected = false;
break;
case OP_C_ADD:
exec->C_ADD(inst);
break;
case OP_C_SWSP:
exec->C_SWSP(inst);
break;
@ -71,6 +84,27 @@ bool CPU::process_c_instruction(Instruction &inst) {
exec->C_BNEZ(inst);
PC_not_affected = false;
break;
case OP_C_SRLI:
exec->C_SRLI(inst);
break;
case OP_C_SRAI:
exec->C_SRAI(inst);
break;
case OP_C_ANDI:
exec->C_ANDI(inst);
break;
case OP_C_SUB:
exec->C_SUB(inst);
break;
case OP_C_XOR:
exec->C_XOR(inst);
break;
case OP_C_OR:
exec->C_OR(inst);
break;
case OP_C_AND:
exec->C_AND(inst);
break;
default:
std::cout << "C instruction not implemented yet" << endl;
inst.dump();
@ -286,6 +320,9 @@ bool CPU::process_base_instruction(Instruction &inst) {
exec->MRET(inst);
PC_not_affected = false;
break;
case OP_WFI:
exec->WFI(inst);
break;
default:
std::cout << "Wrong instruction" << endl;
inst.dump();
@ -317,7 +354,7 @@ void CPU::CPU_thread(void) {
trans->set_dmi_allowed( false ); // Mandatory initial value
trans->set_response_status( tlm::TLM_INCOMPLETE_RESPONSE );
register_bank->dump();
//register_bank->dump();
while(1) {
/* Get new PC value */

View File

@ -53,7 +53,32 @@ op_C_Codes C_Instruction::decode() {
return OP_C_ADDI16SP;
break;
case C_SRLI:
return OP_C_SRLI;
switch(m_instr.range(11,10)) {
case C_2_SRLI:
return OP_C_SRLI;
break;
case C_2_SRAI:
return OP_C_SRAI;
break;
case C_2_ANDI:
return OP_C_ANDI;
break;
case C_2_SUB:
switch(m_instr.range(6,5)) {
case C_3_SUB:
return OP_C_SUB;
break;
case C_3_XOR:
return OP_C_XOR;
break;
case C_3_OR:
return OP_C_OR;
break;
case C_3_AND:
return OP_C_AND;
break;
}
}
break;
case C_J:
return OP_C_J;
@ -73,6 +98,8 @@ op_C_Codes C_Instruction::decode() {
case 0b10:
switch(get_funct3()) {
case C_SLLI:
return OP_C_SLLI;
break;
case C_FLDSP:
case C_LWSP:
return OP_C_LWSP;
@ -81,10 +108,20 @@ op_C_Codes C_Instruction::decode() {
return OP_C_FLWSP;
break;
case C_JR:
if (m_instr.range(6,2) == 0) {
return OP_C_JR;
if (m_instr[12] == 0) {
if (m_instr.range(6,2) == 0) {
return OP_C_JR;
} else {
return OP_C_MV;
}
} else {
return OP_C_MV;
if (m_instr.range(11,2) == 0) {
return OP_C_EBREAK;
} else if (m_instr.range(6,2) == 0) {
return OP_C_JALR;
} else {
return OP_C_ADD;
}
}
break;
case C_FDSP:

View File

@ -73,24 +73,42 @@ void Execute::JAL(Instruction &inst, bool c_extension, int m_rd) {
<< hex << new_pc << ")" << endl;
}
void Execute::JALR(Instruction &inst) {
void Execute::JALR(Instruction &inst, bool c_extension) {
uint32_t mem_addr = 0;
int rd, rs1;
int new_pc, old_pc;
rd = inst.get_rd();
rs1 = inst.get_rs1();
mem_addr = inst.get_imm_I();
if (c_extension == false) {
rd = inst.get_rd();
rs1 = inst.get_rs1();
mem_addr = inst.get_imm_I();
old_pc = regs->getPC();
regs->setValue(rd, old_pc + 4);
old_pc = regs->getPC();
regs->setValue(rd, old_pc + 4);
new_pc = (regs->getValue(rs1) + mem_addr) & 0xFFFFFFFE;
regs->setPC(new_pc);
new_pc = (regs->getValue(rs1) + mem_addr) & 0xFFFFFFFE;
regs->setPC(new_pc);
log->SC_log(Log::INFO) << dec << "JALR: x"
<< rd << " <- 0x" << hex << old_pc + 4
<< " PC <- 0x" << hex << new_pc << endl;
log->SC_log(Log::INFO) << dec << "JALR: x"
<< rd << " <- 0x" << hex << old_pc + 4
<< " PC <- 0x" << hex << new_pc << endl;
} else {
C_Instruction c_inst(inst.getInstr());
rd = 1;
rs1 = c_inst.get_rs1();
old_pc = regs->getPC();
regs->setValue(rd, old_pc + 2);
new_pc = (regs->getValue(rs1) + mem_addr) & 0xFFFFFFFE;
regs->setPC(new_pc);
log->SC_log(Log::INFO) << dec << "C.JALR: x"
<< rd << " <- 0x" << hex << old_pc + 4
<< " PC <- 0x" << hex << new_pc << endl;
}
}
void Execute::BEQ(Instruction &inst) {
@ -364,15 +382,22 @@ void Execute::SH(Instruction &inst) {
<< mem_addr << dec << ")" << endl;
}
void Execute::SW(Instruction &inst) {
void Execute::SW(Instruction &inst, bool c_extension) {
uint32_t mem_addr = 0;
int rs1, rs2;
int32_t imm = 0;
uint32_t data;
rs1 = inst.get_rs1();
rs2 = inst.get_rs2();
imm = inst.get_imm_S();
if (c_extension == false) {
rs1 = inst.get_rs1();
rs2 = inst.get_rs2();
imm = inst.get_imm_S();
} else {
C_Instruction c_inst(inst.getInstr());
rs1 = c_inst.get_rs1p();
rs2 = c_inst.get_rs2p();
imm = c_inst.get_imm_L();
}
mem_addr = imm + regs->getValue(rs1);
data = regs->getValue(rs2);
@ -519,6 +544,10 @@ void Execute::SLLI(Instruction &inst) {
rs1 = inst.get_rs1();
rs2 = inst.get_rs2();
if (rs2 >= 0x20) {
// raise an exception, but how?
}
shift = rs2 & 0x1F;
calc = ((uint32_t)regs->getValue(rs1)) << shift;
@ -599,7 +628,7 @@ void Execute::SUB(Instruction &inst) {
log->SC_log(Log::INFO) << "SUB: x"
<< rs1 << " - x"
<< rs2 << " -> x"
<< rd << endl;
<< rd << "("<< calc << ")" << endl;
}
void Execute::SLL(Instruction &inst) {
@ -788,7 +817,7 @@ void Execute::CSRRW(Instruction &inst) {
void Execute::CSRRS(Instruction &inst) {
int rd, rs1;
int csr;
uint32_t bitmask, aux;
uint32_t bitmask, aux, aux2;
rd = inst.get_rd();
rs1 = inst.get_rs1();
@ -803,11 +832,11 @@ void Execute::CSRRS(Instruction &inst) {
regs->setValue(rd, aux);
bitmask = regs->getValue(rs1);
aux = aux | bitmask;
regs->setCSR(csr, aux);
aux2 = aux | bitmask;
regs->setCSR(csr, aux2);
log->SC_log(Log::INFO) << "CSRRS: CSR #"
<< csr << " -> x" << rd
<< csr << "(" << aux << ") -> x" << dec << rd
<< ". x" << rs1 << " & CSR #" << csr << endl;
}
@ -912,6 +941,8 @@ void Execute::CSRRCI(Instruction &inst) {
<< ". x" << rs1 << " & CSR #" << csr << endl;
}
/*********************** Privileged Instructions ******************************/
void Execute::MRET(Instruction &inst) {
uint32_t new_pc = 0;
@ -921,6 +952,13 @@ void Execute::MRET(Instruction &inst) {
log->SC_log(Log::INFO) << "MRET: PC <- 0x" << hex << new_pc << endl;
}
void Execute::WFI(Instruction &inst) {
log->SC_log(Log::INFO) << "WFI" << endl;
}
/**************************** C Instructions **********************************/
void Execute::C_JR(Instruction &inst) {
uint32_t mem_addr = 0;
int rs1;
@ -952,12 +990,31 @@ void Execute::C_MV(Instruction &inst) {
calc = regs->getValue(rs1) + regs->getValue(rs2);
regs->setValue(rd, calc);
log->SC_log(Log::INFO) << "MV: x" << dec
log->SC_log(Log::INFO) << "C.MV: x" << dec
<< rs1 << "(" << regs->getValue(rs1) << ") + x"
<< rs2 << "(" << regs->getValue(rs2) << ") -> x"
<< rd << "(" << calc << ")" << endl;
}
void Execute::C_ADD(Instruction &inst) {
int rd, rs1, rs2;
uint32_t calc;
C_Instruction c_inst(inst.getInstr());
rd = c_inst.get_rs1();
rs1 = c_inst.get_rs1();
rs2 = c_inst.get_rs2();
calc = regs->getValue(rs1) + regs->getValue(rs2);
regs->setValue(rd, calc);
log->SC_log(Log::INFO) << "C.ADD: x"
<< dec << rs1 << " + x"
<< rs2 << " -> x"
<< rd << endl;
}
void Execute::C_LWSP(Instruction &inst) {
uint32_t mem_addr = 0;
int rd, rs1;
@ -1010,17 +1067,27 @@ void Execute::C_ADDI16SP(Instruction &inst) {
C_Instruction c_inst(inst.getInstr());
rd = 2;
rs1 = 2;
imm = c_inst.get_imm_ADDI16SP();
if (c_inst.get_rd() == 2) {
rd = 2;
rs1 = 2;
imm = c_inst.get_imm_ADDI16SP();
calc = regs->getValue(rs1) + imm;
regs->setValue(rd, calc);
calc = regs->getValue(rs1) + imm;
regs->setValue(rd, calc);
log->SC_log(Log::INFO) << dec << "ADDI16SP: x"
<< rs1 << " + "
<< dec << imm << " -> x"
<< rd << "(0x" << hex << calc << ")" << endl;
log->SC_log(Log::INFO) << dec << "ADDI16SP: x"
<< rs1 << " + "
<< dec << imm << " -> x"
<< rd << "(0x" << hex << calc << ")" << endl;
} else {
/* C.LUI OPCODE */
rd = c_inst.get_rd();
imm = c_inst.get_imm_LUI();
regs->setValue(rd, imm);
log->SC_log(Log::INFO) << dec << "C.LUI x"
<< rd << " <- 0x" << hex << imm << endl;
}
}
void Execute::C_SWSP(Instruction &inst) {
@ -1092,7 +1159,6 @@ void Execute::C_BNEZ(Instruction &inst) {
}
void Execute::C_LI(Instruction &inst) {
int rd, rs1;
int32_t imm = 0;
int32_t calc;
@ -1111,6 +1177,171 @@ void Execute::C_LI(Instruction &inst) {
<< imm << " -> x" << rd << "(" << calc << ")" << endl;
}
void Execute::C_SRLI(Instruction &inst) {
int rd, rs1, rs2;
uint32_t shift;
uint32_t calc;
C_Instruction c_inst(inst.getInstr());
rd = c_inst.get_rs1p();
rs1 = c_inst.get_rs1p();
rs2 = c_inst.get_rs2();
shift = rs2 & 0x1F;
calc = ((uint32_t)regs->getValue(rs1)) >> shift;
regs->setValue(rd, calc);
log->SC_log(Log::INFO) << "C.SRLI: x"
<< rs1 << " >> " << shift << " -> x"
<< rd << endl;
}
void Execute::C_SRAI(Instruction &inst) {
int rd, rs1, rs2;
uint32_t shift;
int32_t calc;
C_Instruction c_inst(inst.getInstr());
rd = c_inst.get_rs1p();
rs1 = c_inst.get_rs1p();
rs2 = c_inst.get_rs2();
shift = rs2 & 0x1F;
calc = (int32_t)regs->getValue(rs1) >> shift;
regs->setValue(rd, calc);
log->SC_log(Log::INFO) << "C.SRAI: x"
<< rs1 << " >> " << dec << shift << " -> x"
<< rd << "("<< calc << ")" << endl;
}
void Execute::C_SLLI(Instruction &inst) {
int rd, rs1, rs2;
uint32_t shift;
uint32_t calc;
C_Instruction c_inst(inst.getInstr());
rd = c_inst.get_rs1p();
rs1 = c_inst.get_rs1p();
rs2 = c_inst.get_imm_ADDI();
shift = rs2 & 0x1F;
calc = ((uint32_t)regs->getValue(rs1)) << shift;
regs->setValue(rd, calc);
log->SC_log(Log::INFO) << "C.SLLI: x"
<< dec << rs1 << " << "
<< shift << " -> x"
<< rd << endl;
}
void Execute::C_ANDI(Instruction &inst) {
int rd, rs1;
int32_t imm;
uint32_t calc;
C_Instruction c_inst(inst.getInstr());
rd = c_inst.get_rs1p();
rs1 = c_inst.get_rs1p();
imm = c_inst.get_imm_ADDI();
calc = regs->getValue(rs1) & imm;
regs->setValue(rd, calc);
log->SC_log(Log::INFO) << "C.ANDI: x"
<< rs1 << " AND "
<< imm << " -> x"
<< rd << endl;
}
void Execute::C_SUB(Instruction &inst) {
int rd, rs1, rs2;
uint32_t calc;
C_Instruction c_inst(inst.getInstr());
rd = c_inst.get_rs1p();
rs1 = c_inst.get_rs1p();
rs2 = c_inst.get_rs2p();
calc = regs->getValue(rs1) - regs->getValue(rs2);
regs->setValue(rd, calc);
/* Can insert some arbitrary execution time */
//wait(sc_time(10, SC_NS));
log->SC_log(Log::INFO) << "C.SUB: x"
<< dec << rs1 << " - x"
<< rs2 << " -> x"
<< rd << endl;
}
void Execute::C_XOR(Instruction &inst) {
int rd, rs1, rs2;
uint32_t calc;
C_Instruction c_inst(inst.getInstr());
rd = c_inst.get_rs1p();
rs1 = c_inst.get_rs1p();
rs2 = c_inst.get_rs2p();
calc = regs->getValue(rs1) ^ regs->getValue(rs2);
regs->setValue(rd, calc);
log->SC_log(Log::INFO) << "C.XOR: x"
<< dec << rs1 << " XOR x"
<< rs2 << "-> x"
<< rd << endl;
}
void Execute::C_OR(Instruction &inst) {
int rd, rs1, rs2;
uint32_t calc;
C_Instruction c_inst(inst.getInstr());
rd = c_inst.get_rs1p();
rs1 = c_inst.get_rs1p();
rs2 = c_inst.get_rs2p();
calc = regs->getValue(rs1) | regs->getValue(rs2);
regs->setValue(rd, calc);
log->SC_log(Log::INFO) << "C_OR: x"
<< dec << rs1 << " OR x"
<< rs2 << "-> x"
<< rd << endl;
}
void Execute::C_AND(Instruction &inst) {
int rd, rs1, rs2;
uint32_t calc;
C_Instruction c_inst(inst.getInstr());
rd = c_inst.get_rs1p();
rs1 = c_inst.get_rs1p();
rs2 = c_inst.get_rs2p();
calc = regs->getValue(rs1) & regs->getValue(rs2);
regs->setValue(rd, calc);
log->SC_log(Log::INFO) << "C.AND: x"
<< dec << rs1 << " AND x"
<< rs2 << "-> x"
<< rd << endl;
}
/******************************************************************************/
/* M Extensions */
/******************************************************************************/

View File

@ -128,6 +128,8 @@ opCodes Instruction::decode() {
return OP_SRET;
case MRET_F:
return OP_MRET;
case WFI_F:
return OP_WFI;
}
break;
case CSRRW: