better support to IRQs
This commit is contained in:
parent
a91e590d6d
commit
a275e0fa24
|
@ -68,7 +68,8 @@ private:
|
|||
Log *log;
|
||||
|
||||
bool interrupt;
|
||||
|
||||
uint32_t int_cause;
|
||||
bool irq_already_down;
|
||||
/**
|
||||
*
|
||||
* @brief Process and triggers IRQ if all conditions met
|
||||
|
|
24
src/CPU.cpp
24
src/CPU.cpp
|
@ -17,6 +17,9 @@ CPU::CPU(sc_module_name name, uint32_t PC): sc_module(name)
|
|||
irq_line_socket.register_b_transport(this, &CPU::call_interrupt);
|
||||
interrupt = false;
|
||||
|
||||
int_cause = 0;
|
||||
irq_already_down = false;
|
||||
|
||||
SC_THREAD(CPU_thread);
|
||||
}
|
||||
|
||||
|
@ -43,10 +46,9 @@ bool CPU::cpu_process_IRQ() {
|
|||
|
||||
csr_temp = register_bank->getCSR(CSR_MIP);
|
||||
|
||||
if ( (csr_temp & MIP_MEIP ) == 0 ) {
|
||||
if ( (csr_temp & MIP_MEIP ) == 0 ) {
|
||||
csr_temp |= MIP_MEIP; // MEIP bit in MIP register (11th bit)
|
||||
register_bank->setCSR(CSR_MIP, csr_temp);
|
||||
// cout << "time: " << sc_time_stamp() << ". CPU: interrupt" << endl;
|
||||
log->SC_log(Log::DEBUG) << "Interrupt!" << endl;
|
||||
|
||||
/* updated MEPC register */
|
||||
|
@ -59,17 +61,21 @@ bool CPU::cpu_process_IRQ() {
|
|||
|
||||
/* set new PC address */
|
||||
new_pc = register_bank->getCSR(CSR_MTVEC);
|
||||
new_pc = new_pc & 0xFFFFFFFC; // last two bits always to 0
|
||||
//new_pc = new_pc & 0xFFFFFFFC; // last two bits always to 0
|
||||
log->SC_log(Log::DEBUG) << "NEW PC Value 0x" << hex << new_pc << endl;
|
||||
register_bank->setPC(new_pc);
|
||||
|
||||
ret_value = true;
|
||||
interrupt = false;
|
||||
irq_already_down = false;
|
||||
}
|
||||
} else {
|
||||
csr_temp = register_bank->getCSR(CSR_MIP);
|
||||
csr_temp &= ~MIP_MEIP;
|
||||
register_bank->setCSR(CSR_MIP, csr_temp);
|
||||
} else {
|
||||
if (irq_already_down == false) {
|
||||
csr_temp = register_bank->getCSR(CSR_MIP);
|
||||
csr_temp &= ~MIP_MEIP;
|
||||
register_bank->setCSR(CSR_MIP, csr_temp);
|
||||
irq_already_down = true;
|
||||
}
|
||||
}
|
||||
|
||||
return ret_value;
|
||||
|
@ -511,12 +517,12 @@ void CPU::CPU_thread(void) {
|
|||
|
||||
/* Fixed instruction time to 10 ns (i.e. 100 MHz)*/
|
||||
sc_core::wait(10, SC_NS);
|
||||
|
||||
|
||||
} // while(1)
|
||||
} // CPU_thread
|
||||
|
||||
|
||||
void CPU::call_interrupt(tlm::tlm_generic_payload &trans, sc_time &delay) {
|
||||
interrupt = true;
|
||||
/* Socket caller send a cause (its id) */
|
||||
memcpy(&int_cause, trans.get_data_ptr(), sizeof(int));
|
||||
}
|
||||
|
|
|
@ -13,15 +13,15 @@ void Timer::run() {
|
|||
|
||||
tlm::tlm_generic_payload* irq_trans = new tlm::tlm_generic_payload;
|
||||
sc_time delay = SC_ZERO_TIME;
|
||||
|
||||
uint32_t cause = 1 << 31 | 0x07; // Machine timer interrupt
|
||||
irq_trans->set_command(tlm::TLM_WRITE_COMMAND);
|
||||
irq_trans->set_data_ptr(NULL);
|
||||
irq_trans->set_data_length(0);
|
||||
irq_trans->set_streaming_width(0);
|
||||
irq_trans->set_byte_enable_ptr(0);
|
||||
irq_trans->set_data_ptr( reinterpret_cast<unsigned char*>(&cause) );
|
||||
irq_trans->set_data_length( 4 );
|
||||
irq_trans->set_streaming_width( 4 );
|
||||
irq_trans->set_byte_enable_ptr( 0 );
|
||||
irq_trans->set_dmi_allowed(false);
|
||||
irq_trans->set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
|
||||
irq_trans->set_address( 0x01);
|
||||
irq_trans->set_address( 0 );
|
||||
|
||||
while(true) {
|
||||
wait(timer_event);
|
||||
|
@ -40,7 +40,6 @@ void Timer::b_transport( tlm::tlm_generic_payload& trans, sc_time& delay ) {
|
|||
uint32_t aux_value = 0;
|
||||
uint64_t notify_time = 0;
|
||||
|
||||
// cout << "accessing TIMER 0x" << hex << addr << endl;
|
||||
if (cmd == tlm::TLM_WRITE_COMMAND) {
|
||||
memcpy(&aux_value, ptr, len);
|
||||
switch (addr) {
|
||||
|
@ -58,8 +57,7 @@ void Timer::b_transport( tlm::tlm_generic_payload& trans, sc_time& delay ) {
|
|||
|
||||
// notify needs relative time, mtimecmp works in absolute time
|
||||
notify_time = m_mtimecmp - m_mtime;
|
||||
// cout << "time: " << sc_time_stamp() << ". Timer: IRQ will be at "
|
||||
// << dec << notify_time + m_mtime << " ns." << endl;
|
||||
|
||||
timer_event.notify( sc_time(notify_time, SC_NS) );
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue