From b9e26e4deaba4a8899b859d511a14e121a77b662 Mon Sep 17 00:00:00 2001 From: mariusmonton Date: Thu, 22 Nov 2018 14:38:31 +0100 Subject: [PATCH] first implementation supporting exceptions --- inc/Execute.h | 5 ++++- inc/Instruction.h | 7 +++++++ inc/Registers.h | 11 +++++++++++ src/CPU.cpp | 2 +- src/Execute.cpp | 30 ++++++++++++++++++++++++++++-- 5 files changed, 51 insertions(+), 4 deletions(-) diff --git a/inc/Execute.h b/inc/Execute.h index fcd17ed..1a0dd02 100644 --- a/inc/Execute.h +++ b/inc/Execute.h @@ -73,7 +73,7 @@ public: void XORI(Instruction &inst); void ORI(Instruction &inst); void ANDI(Instruction &inst); - void SLLI(Instruction &inst); + bool SLLI(Instruction &inst); void SRLI(Instruction &inst); void SRAI(Instruction &inst); @@ -138,6 +138,9 @@ public: private: uint32_t readDataMem(uint32_t addr, int size); void writeDataMem(uint32_t addr, uint32_t data, int size); + + void RaiseException(uint32_t cause); + Registers *regs; Performance *perf; Log *log; diff --git a/inc/Instruction.h b/inc/Instruction.h index 4c646c5..4358992 100644 --- a/inc/Instruction.h +++ b/inc/Instruction.h @@ -167,6 +167,13 @@ typedef enum { CSRRCI = 0b111, } Codes; +#define EXCEPTION_CAUSE_INSTRUCTION_MISALIGN 0 +#define EXCEPTION_CAUSE_INSTRUCTION_ACCESS 1 +#define EXCEPTION_CAUSE_ILLEGAL_INSTRUCTION 2 +#define EXCEPTION_CAUSE_BREAKPOINT 3 +#define EXCEPTION_CAUSE_LOAD_ADDR_MISALIGN 4 +#define EXCEPTION_CAUSE_LOAD_ACCESS_FAULT 5 + /** * @brief Instruction decoding and fields access */ diff --git a/inc/Registers.h b/inc/Registers.h index 2d7a61f..5f2eb22 100644 --- a/inc/Registers.h +++ b/inc/Registers.h @@ -22,6 +22,11 @@ #define WARL_MXL (1 << 30) +#define CSR_MVENDORID (0xF11) +#define CSR_MARCHID (0xF12) +#define CSR_MIMPID (0xF13) +#define CSR_MHARTID (0xF14) + #define CSR_MSTATUS (0x300) #define CSR_MISA (0x301) #define CSR_MEDELEG (0x302) @@ -30,6 +35,12 @@ #define CSR_MTVEC (0x305) #define CSR_MCOUNTEREN (0x306) +#define CSR_MSCRATCH (0x340) +#define CSR_MEPC (0x341) +#define CSR_MCAUSE (0x342) +#define CSR_MTVAL (0x343) +#define CSR_MIP (0x344) + using namespace sc_core; using namespace sc_dt; diff --git a/src/CPU.cpp b/src/CPU.cpp index 5d51e32..3ccb748 100644 --- a/src/CPU.cpp +++ b/src/CPU.cpp @@ -242,7 +242,7 @@ bool CPU::process_base_instruction(Instruction &inst) { exec->ANDI(inst); break; case OP_SLLI: - exec->SLLI(inst); + PC_not_affected = exec->SLLI(inst); break; case OP_SRLI: exec->SRLI(inst); diff --git a/src/Execute.cpp b/src/Execute.cpp index 9839a23..1fa5e69 100644 --- a/src/Execute.cpp +++ b/src/Execute.cpp @@ -535,7 +535,7 @@ void Execute::ANDI(Instruction &inst) { << rd << endl; } -void Execute::SLLI(Instruction &inst) { +bool Execute::SLLI(Instruction &inst) { int rd, rs1, rs2; uint32_t shift; uint32_t calc; @@ -547,6 +547,9 @@ void Execute::SLLI(Instruction &inst) { if (rs2 >= 0x20) { // raise an exception, but how? cout << "ILEGAL INSTRUCTION, shamt[5] != 0" << endl; + RaiseException(EXCEPTION_CAUSE_ILLEGAL_INSTRUCTION); + + return false; } shift = rs2 & 0x1F; @@ -557,6 +560,8 @@ void Execute::SLLI(Instruction &inst) { log->SC_log(Log::INFO) << "SLLI: x" << rs1 << " << " << shift << " -> x" << rd << "(0x" << hex << calc << ")" << endl; + + return true; } void Execute::SRLI(Instruction &inst) { @@ -951,7 +956,7 @@ void Execute::CSRRCI(Instruction &inst) { void Execute::MRET(Instruction &inst) { uint32_t new_pc = 0; - new_pc = regs->getCSR(0x341); + new_pc = regs->getCSR(CSR_MEPC); regs->setPC(new_pc); log->SC_log(Log::INFO) << "MRET: PC <- 0x" << hex << new_pc << endl; @@ -1611,3 +1616,24 @@ void Execute::writeDataMem(uint32_t addr, uint32_t data, int size) { data_bus->b_transport( trans, delay); } + + +void Execute::RaiseException(uint32_t cause) { + uint32_t new_pc, current_pc, m_cause; + + current_pc = regs->getPC(); + m_cause = regs->getCSR(CSR_MSTATUS); + m_cause |= cause; + + new_pc = regs->getCSR(CSR_MTVEC); + + regs->setCSR(CSR_MEPC, current_pc ); + regs->setCSR(CSR_MTVAL, current_pc ); + regs->setCSR(CSR_MCAUSE, cause); + regs->setCSR(CSR_MSTATUS, m_cause); + + regs->setPC( new_pc); + + log->SC_log(Log::INFO) << "Exception! new PC " << hex << new_pc << endl; + +}