enhanced IRQ support
This commit is contained in:
parent
2c2cf3000b
commit
2c93492ab1
24
src/CPU.cpp
24
src/CPU.cpp
|
@ -11,12 +11,12 @@ CPU::CPU(sc_module_name name, uint32_t PC): sc_module(name)
|
||||||
|
|
||||||
register_bank->setPC(PC);
|
register_bank->setPC(PC);
|
||||||
|
|
||||||
register_bank->setValue(Registers::sp, (0xD0000 / 4) - 1);
|
//register_bank->setValue(Registers::sp, (0xD0000 / 4) - 1);
|
||||||
//register_bank->setValue(Registers::sp, (0x10000000 / 4) - 1);
|
register_bank->setValue(Registers::sp, (0x10000000 / 4) - 1);
|
||||||
|
|
||||||
irq_line_socket.register_b_transport(this, &CPU::call_interrupt);
|
irq_line_socket.register_b_transport(this, &CPU::call_interrupt);
|
||||||
interrupt = false;
|
interrupt = false;
|
||||||
|
|
||||||
SC_THREAD(CPU_thread);
|
SC_THREAD(CPU_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,11 +33,18 @@ bool CPU::cpu_process_IRQ() {
|
||||||
uint32_t new_pc, old_pc;
|
uint32_t new_pc, old_pc;
|
||||||
bool ret_value = false;
|
bool ret_value = false;
|
||||||
|
|
||||||
if (interrupt == true){
|
if (interrupt == true) {
|
||||||
|
csr_temp = register_bank->getCSR(CSR_MSTATUS);
|
||||||
|
if (csr_temp & MSTATUS_MIE) {
|
||||||
|
} else {
|
||||||
|
log->SC_log(Log::DEBUG) << "interrupt delayed" << endl;
|
||||||
|
return ret_value;
|
||||||
|
}
|
||||||
|
|
||||||
csr_temp = register_bank->getCSR(CSR_MIP);
|
csr_temp = register_bank->getCSR(CSR_MIP);
|
||||||
|
|
||||||
if ( (csr_temp & (1 << 11) ) == 0 ) {
|
if ( (csr_temp & MIP_MEIP ) == 0 ) {
|
||||||
csr_temp |= (1 << 11); // MEIP bit in MIP register (11th bit)
|
csr_temp |= MIP_MEIP; // MEIP bit in MIP register (11th bit)
|
||||||
register_bank->setCSR(CSR_MIP, csr_temp);
|
register_bank->setCSR(CSR_MIP, csr_temp);
|
||||||
// cout << "time: " << sc_time_stamp() << ". CPU: interrupt" << endl;
|
// cout << "time: " << sc_time_stamp() << ". CPU: interrupt" << endl;
|
||||||
log->SC_log(Log::DEBUG) << "Interrupt!" << endl;
|
log->SC_log(Log::DEBUG) << "Interrupt!" << endl;
|
||||||
|
@ -48,7 +55,7 @@ bool CPU::cpu_process_IRQ() {
|
||||||
log->SC_log(Log::INFO) << "Old PC Value 0x" << hex << old_pc << endl;
|
log->SC_log(Log::INFO) << "Old PC Value 0x" << hex << old_pc << endl;
|
||||||
|
|
||||||
/* update MCAUSE register */
|
/* update MCAUSE register */
|
||||||
register_bank->setCSR(CSR_MCAUSE, 0x8000000);
|
register_bank->setCSR(CSR_MCAUSE, 0x80000000);
|
||||||
|
|
||||||
/* set new PC address */
|
/* set new PC address */
|
||||||
new_pc = register_bank->getCSR(CSR_MTVEC);
|
new_pc = register_bank->getCSR(CSR_MTVEC);
|
||||||
|
@ -61,7 +68,7 @@ bool CPU::cpu_process_IRQ() {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
csr_temp = register_bank->getCSR(CSR_MIP);
|
csr_temp = register_bank->getCSR(CSR_MIP);
|
||||||
csr_temp &= ~(1 << 11);
|
csr_temp &= ~MIP_MEIP;
|
||||||
register_bank->setCSR(CSR_MIP, csr_temp);
|
register_bank->setCSR(CSR_MIP, csr_temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -509,6 +516,7 @@ void CPU::CPU_thread(void) {
|
||||||
} // while(1)
|
} // while(1)
|
||||||
} // CPU_thread
|
} // CPU_thread
|
||||||
|
|
||||||
|
|
||||||
void CPU::call_interrupt(tlm::tlm_generic_payload &trans, sc_time &delay) {
|
void CPU::call_interrupt(tlm::tlm_generic_payload &trans, sc_time &delay) {
|
||||||
interrupt = true;
|
interrupt = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1029,7 +1029,8 @@ bool Execute::CSRRSI(Instruction &inst) {
|
||||||
|
|
||||||
log->SC_log(Log::INFO) << "CSRRSI: CSR #"
|
log->SC_log(Log::INFO) << "CSRRSI: CSR #"
|
||||||
<< csr << " -> x" << rd
|
<< csr << " -> x" << rd
|
||||||
<< ". x" << rs1 << " & CSR #" << csr << endl;
|
<< ". x" << rs1 << " & CSR #" << csr
|
||||||
|
<< "(0x" << hex << aux << ")"<< endl;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1073,6 +1074,15 @@ bool Execute::MRET(Instruction &inst) {
|
||||||
|
|
||||||
log->SC_log(Log::INFO) << "MRET: PC <- 0x" << hex << new_pc << endl;
|
log->SC_log(Log::INFO) << "MRET: PC <- 0x" << hex << new_pc << endl;
|
||||||
|
|
||||||
|
// update mstatus
|
||||||
|
uint32_t csr_temp;
|
||||||
|
csr_temp = regs->getCSR(CSR_MSTATUS);
|
||||||
|
if (csr_temp & MSTATUS_MPIE) {
|
||||||
|
csr_temp |= MSTATUS_MIE;
|
||||||
|
}
|
||||||
|
csr_temp |= MSTATUS_MPIE;
|
||||||
|
regs->setCSR(CSR_MSTATUS, csr_temp);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue