Added better PC control

This commit is contained in:
mariusmonton 2018-09-21 09:25:47 +02:00
parent dcd3a8c3fe
commit 4ba8b1bbb7
1 changed files with 55 additions and 24 deletions

View File

@ -39,36 +39,43 @@ void RISC_V_execute::AUIPC(Instruction &inst) {
void RISC_V_execute::JAL(Instruction &inst) { void RISC_V_execute::JAL(Instruction &inst) {
int32_t mem_addr = 0; int32_t mem_addr = 0;
int rd; int rd;
int new_pc; int new_pc, old_pc;
rd = inst.rd(); rd = inst.rd();
mem_addr = inst.imm_J(); mem_addr = inst.imm_J();
new_pc = regs->getPC(); old_pc = regs->getPC();
regs->setValue(rd, new_pc);
new_pc = new_pc + mem_addr - 4;
new_pc = old_pc + mem_addr;
regs->setPC(new_pc); regs->setPC(new_pc);
log->SC_log(Log::INFO) << "JAL: R" << rd << " PC + " << mem_addr old_pc = old_pc + 4;
<< " -> PC (0x" << hex << new_pc << ")" << endl; regs->setValue(rd, old_pc);
log->SC_log(Log::INFO) << dec << "JAL: R" << rd << " <- 0x" << hex << old_pc
<< dec << " PC + " << mem_addr << " -> PC (0x"
<< hex << new_pc << ")" << endl;
} }
void RISC_V_execute::JALR(Instruction &inst) { void RISC_V_execute::JALR(Instruction &inst) {
uint32_t mem_addr = 0; uint32_t mem_addr = 0;
int rd; int rd, rs1;
int new_pc; int new_pc, old_pc;
rd = inst.rd(); rd = inst.rd();
rs1 = inst.rs1();
mem_addr = inst.imm_I(); mem_addr = inst.imm_I();
new_pc = regs->getPC(); old_pc = regs->getPC();
regs->setValue(rd, new_pc); regs->setValue(rd, old_pc + 4);
new_pc = (new_pc + mem_addr - 4) & 0xFFFFFFFE;
new_pc = (regs->getValue(rs1) + mem_addr) & 0xFFFFFFFE;
regs->setPC(new_pc); regs->setPC(new_pc);
log->SC_log(Log::INFO) << "JALR PC <- 0x" << hex << new_pc << endl; log->SC_log(Log::INFO) << "JALR: R" << dec << rd << " <- 0x" << hex << old_pc + 4
<< " PC <- 0x" << hex << new_pc << endl;
} }
void RISC_V_execute::BEQ(Instruction &inst) { void RISC_V_execute::BEQ(Instruction &inst) {
@ -79,8 +86,10 @@ void RISC_V_execute::BEQ(Instruction &inst) {
rs2 = inst.rs2(); rs2 = inst.rs2();
if (regs->getValue(rs1) == regs->getValue(rs2)) { if (regs->getValue(rs1) == regs->getValue(rs2)) {
new_pc = regs->getPC() + inst.imm_B() - 4; new_pc = regs->getPC() + inst.imm_B();
regs->setPC(new_pc); regs->setPC(new_pc);
} else {
regs->incPC();
} }
log->SC_log(Log::INFO) << "BEQ R" << rs1 << " == R" << rs2 << "? -> PC (" << new_pc << ")" << endl; log->SC_log(Log::INFO) << "BEQ R" << rs1 << " == R" << rs2 << "? -> PC (" << new_pc << ")" << endl;
@ -90,16 +99,24 @@ void RISC_V_execute::BEQ(Instruction &inst) {
void RISC_V_execute::BNE(Instruction &inst) { void RISC_V_execute::BNE(Instruction &inst) {
int rs1, rs2; int rs1, rs2;
int new_pc = 0; int new_pc = 0;
uint32_t val1, val2;
rs1 = inst.rs1(); rs1 = inst.rs1();
rs2 = inst.rs2(); rs2 = inst.rs2();
if (regs->getValue(rs1) != regs->getValue(rs2)) { val1 = regs->getValue(rs1);
new_pc = regs->getPC() + inst.imm_B() - 4; val2 = regs->getValue(rs2);
if (val1 != val2) {
new_pc = regs->getPC() + inst.imm_B();
regs->setPC(new_pc); regs->setPC(new_pc);
} else {
regs->incPC();
} }
log->SC_log(Log::INFO) << "BNE R" << rs1 << " == R" << rs2 << "? -> PC (" << new_pc << ")" << endl; log->SC_log(Log::INFO) << "BNE: R" << rs1 << "(" << val1
<< ") == R" << rs2 << "(" << val2 << ")? -> PC ("
<< new_pc << ")" << endl;
} }
void RISC_V_execute::BLT(Instruction &inst) { void RISC_V_execute::BLT(Instruction &inst) {
@ -110,8 +127,10 @@ void RISC_V_execute::BLT(Instruction &inst) {
rs2 = inst.rs2(); rs2 = inst.rs2();
if ((int32_t)regs->getValue(rs1) < (int32_t)regs->getValue(rs2)) { if ((int32_t)regs->getValue(rs1) < (int32_t)regs->getValue(rs2)) {
new_pc = regs->getPC() + inst.imm_B() - 4; new_pc = regs->getPC() + inst.imm_B();
regs->setPC(new_pc); regs->setPC(new_pc);
} else {
regs->incPC();
} }
log->SC_log(Log::INFO) << "BLT R" << rs1 << " < R" << rs2 << "? -> PC (" << new_pc << ")" << endl; log->SC_log(Log::INFO) << "BLT R" << rs1 << " < R" << rs2 << "? -> PC (" << new_pc << ")" << endl;
@ -125,8 +144,10 @@ void RISC_V_execute::BGE(Instruction &inst) {
rs2 = inst.rs2(); rs2 = inst.rs2();
if ((int32_t)regs->getValue(rs1) >= (int32_t)regs->getValue(rs2)) { if ((int32_t)regs->getValue(rs1) >= (int32_t)regs->getValue(rs2)) {
new_pc = regs->getPC() + inst.imm_B() - 4; new_pc = regs->getPC() + inst.imm_B();
regs->setPC(new_pc); regs->setPC(new_pc);
} else {
regs->incPC();
} }
log->SC_log(Log::INFO) << "BGE R" << rs1 << "(" << log->SC_log(Log::INFO) << "BGE R" << rs1 << "(" <<
@ -143,8 +164,10 @@ void RISC_V_execute::BLTU(Instruction &inst) {
rs2 = inst.rs2(); rs2 = inst.rs2();
if (regs->getValue(rs1) < regs->getValue(rs2)) { if (regs->getValue(rs1) < regs->getValue(rs2)) {
new_pc = regs->getPC() + inst.imm_B() - 4; new_pc = regs->getPC() + inst.imm_B();
regs->setPC(new_pc); regs->setPC(new_pc);
} else {
regs->incPC();
} }
log->SC_log(Log::INFO) << "BLTU R" << rs1 << " < R" << rs2 << "? -> PC (" << new_pc << ")" << endl; log->SC_log(Log::INFO) << "BLTU R" << rs1 << " < R" << rs2 << "? -> PC (" << new_pc << ")" << endl;
@ -158,8 +181,10 @@ void RISC_V_execute::BGEU(Instruction &inst) {
rs2 = inst.rs2(); rs2 = inst.rs2();
if (regs->getValue(rs1) >= regs->getValue(rs2)) { if (regs->getValue(rs1) >= regs->getValue(rs2)) {
new_pc = regs->getPC() + inst.imm_B() - 4; new_pc = regs->getPC() + inst.imm_B();
regs->setPC(new_pc); regs->setPC(new_pc);
} else {
regs->incPC();
} }
log->SC_log(Log::INFO) << "BGEU R" << rs1 << " > R" << rs2 << "? -> PC (" << new_pc << ")" << endl; log->SC_log(Log::INFO) << "BGEU R" << rs1 << " > R" << rs2 << "? -> PC (" << new_pc << ")" << endl;
@ -716,9 +741,9 @@ void RISC_V_execute::NOP(Instruction &inst) {
} }
/** /**
* Access data memory to get data for LOAD & STORE OPs * Access data memory to get data for LOAD OPs
* @note NOT IMPLEMENTED YET
* @param addr address to access to * @param addr address to access to
* @param size size of the data to read in bytes
* @return data value read * @return data value read
*/ */
uint32_t RISC_V_execute::readDataMem(uint32_t addr, int size) { uint32_t RISC_V_execute::readDataMem(uint32_t addr, int size) {
@ -740,7 +765,13 @@ uint32_t RISC_V_execute::readDataMem(uint32_t addr, int size) {
return data; return data;
} }
/**
* Acces data memory to write data for STORE ops
* @brief
* @param addr addr address to access to
* @param data data to write
* @param size size of the data to write in bytes
*/
void RISC_V_execute::writeDataMem(uint32_t addr, uint32_t data, int size) { void RISC_V_execute::writeDataMem(uint32_t addr, uint32_t data, int size) {
tlm::tlm_generic_payload trans; tlm::tlm_generic_payload trans;
sc_time delay = SC_ZERO_TIME; sc_time delay = SC_ZERO_TIME;