diff --git a/inc/CPU.h b/inc/CPU.h index 9880d14..ac7b387 100644 --- a/inc/CPU.h +++ b/inc/CPU.h @@ -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 diff --git a/src/CPU.cpp b/src/CPU.cpp index f018cab..3e3ea46 100644 --- a/src/CPU.cpp +++ b/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)); } diff --git a/src/Timer.cpp b/src/Timer.cpp index 53c0afa..b396a38 100644 --- a/src/Timer.cpp +++ b/src/Timer.cpp @@ -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(&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; }