changed IRQ line to TLM socket

This commit is contained in:
mariusmonton 2019-01-22 12:43:05 +01:00
parent 0c25abdb00
commit 098aebc15d
5 changed files with 74 additions and 22 deletions

View File

@ -34,13 +34,30 @@ using namespace std;
class CPU: sc_module { class CPU: sc_module {
public: public:
/**
* @brief Instruction Memory bus socket
* @param trans transction to perfoem
* @param delay time to annotate
*/
tlm_utils::simple_initiator_socket<CPU> instr_bus; tlm_utils::simple_initiator_socket<CPU> instr_bus;
//tlm_utils::simple_initiator_socket<cpu_base> data_bus; /**
* @brief IRQ line socket
sc_in<bool> interrupt; * @param trans transction to perform (empty)
* @param delay time to annotate
*/
tlm_utils::simple_target_socket<CPU> irq_line_socket;
/**
* @brief Constructor
* @param name Module name
* @param PC Program Counter initialize value
*/
CPU(sc_module_name name, uint32_t PC); CPU(sc_module_name name, uint32_t PC);
/**
* @brief Destructor
*/
~CPU(); ~CPU();
Execute *exec; Execute *exec;
@ -50,12 +67,15 @@ private:
Performance *perf; Performance *perf;
Log *log; Log *log;
bool interrupt;
/** /**
* *
* @brief Process and triggers IRQ if all conditions memory_socket * @brief Process and triggers IRQ if all conditions memory_socket
* @return true if IRQ is triggered, false otherwise * @return true if IRQ is triggered, false otherwise
*/ */
bool cpu_process_IRQ(); bool cpu_process_IRQ();
/** /**
* @brief Executes default ISA instruction * @brief Executes default ISA instruction
* @param inst instruction to execute * @param inst instruction to execute
@ -70,6 +90,13 @@ private:
bool process_a_instruction(Instruction inst); bool process_a_instruction(Instruction inst);
void CPU_thread(void); void CPU_thread(void);
/**
* @brief callback for IRQ simple socket
* @param trans transaction to perform (empty)
* @param delay time to annotate
*/
void call_interrupt(tlm::tlm_generic_payload &trans, sc_time &delay);
}; };
#endif #endif

View File

@ -34,7 +34,9 @@ class Timer: sc_module {
public: public:
// TLM-2 socket, defaults to 32-bits wide, base protocol // TLM-2 socket, defaults to 32-bits wide, base protocol
tlm_utils::simple_target_socket<Timer> socket; tlm_utils::simple_target_socket<Timer> socket;
sc_out<bool> timer_irq;
tlm_utils::simple_initiator_socket<Timer> irq_line;
//sc_out<bool> timer_irq;
/** /**
* *

View File

@ -10,6 +10,13 @@ CPU::CPU(sc_module_name name, uint32_t PC): sc_module(name)
log = Log::getInstance(); log = Log::getInstance();
register_bank->setPC(PC); register_bank->setPC(PC);
register_bank->setValue(Registers::sp, (0xD0000 / 4) - 1);
//register_bank->setValue(Registers::sp, (0x10000000 / 4) - 1);
irq_line_socket.register_b_transport(this, &CPU::call_interrupt);
interrupt = false;
SC_THREAD(CPU_thread); SC_THREAD(CPU_thread);
} }
@ -33,7 +40,7 @@ bool CPU::cpu_process_IRQ() {
csr_temp |= (1 << 11); // MEIP bit in MIP register (11th bit) csr_temp |= (1 << 11); // 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::INFO) << "Interrupt!" << endl; log->SC_log(Log::DEBUG) << "Interrupt!" << endl;
/* updated MEPC register */ /* updated MEPC register */
old_pc = register_bank->getPC(); old_pc = register_bank->getPC();
@ -50,6 +57,7 @@ bool CPU::cpu_process_IRQ() {
register_bank->setPC(new_pc); register_bank->setPC(new_pc);
ret_value = true; ret_value = true;
interrupt = false;
} }
} else { } else {
csr_temp = register_bank->getCSR(CSR_MIP); csr_temp = register_bank->getCSR(CSR_MIP);
@ -500,3 +508,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) {
interrupt = true;
}

View File

@ -40,12 +40,15 @@ SC_MODULE(Simulator)
BusCtrl* Bus; BusCtrl* Bus;
Trace *trace; Trace *trace;
Timer *timer; Timer *timer;
Log *log;
uint32_t start_PC; uint32_t start_PC;
sc_signal<bool> IRQ;
SC_CTOR(Simulator) SC_CTOR(Simulator)
{ {
log = Log::getInstance();
log->setLogLevel(Log::ERROR);
MainMemory = new Memory("Main_Memory", filename); MainMemory = new Memory("Main_Memory", filename);
start_PC = MainMemory->getPCfromHEX(); start_PC = MainMemory->getPCfromHEX();
@ -61,8 +64,10 @@ SC_MODULE(Simulator)
Bus->memory_socket.bind(MainMemory->socket); Bus->memory_socket.bind(MainMemory->socket);
Bus->trace_socket.bind(trace->socket); Bus->trace_socket.bind(trace->socket);
Bus->timer_socket.bind(timer->socket); Bus->timer_socket.bind(timer->socket);
timer->timer_irq.bind(IRQ);
cpu->interrupt.bind(IRQ); //timer->timer_irq.bind(IRQ);
// cpu->interrupt.bind(IRQ);
timer->irq_line.bind(cpu->irq_line_socket);
} }
~Simulator() { ~Simulator() {

View File

@ -10,19 +10,22 @@ Timer::Timer(sc_module_name name): sc_module(name)
} }
void Timer::run() { void Timer::run() {
tlm::tlm_generic_payload* irq_trans = new tlm::tlm_generic_payload;
sc_time delay = SC_ZERO_TIME;
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_dmi_allowed(false);
irq_trans->set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
irq_trans->set_address( 0x01);
while(true) { while(true) {
wait(timer_event); wait(timer_event);
irq_line->b_transport(*irq_trans, delay);
if (timer_irq.read() == true) {
timer_irq.write(false);
// cout << "time: " << sc_time_stamp() <<". bla bla " << endl;
} else {
timer_irq.write(true);
cout << "time: " << sc_time_stamp() << ". Timer interrupt!" << endl;
// notify in 20 ns to low irq signal
timer_event.notify( sc_time(20, SC_NS));
}
} }
} }
@ -30,12 +33,13 @@ void Timer::b_transport( tlm::tlm_generic_payload& trans, sc_time& delay ) {
tlm::tlm_command cmd = trans.get_command(); tlm::tlm_command cmd = trans.get_command();
sc_dt::uint64 addr = trans.get_address(); sc_dt::uint64 addr = trans.get_address();
unsigned char* ptr = trans.get_data_ptr(); unsigned char* ptr = trans.get_data_ptr();
uint32_t aux_value = 0;
uint64_t notify_time = 0;
unsigned int len = trans.get_data_length(); unsigned int len = trans.get_data_length();
//unsigned char* byt = trans.get_byte_enable_ptr(); //unsigned char* byt = trans.get_byte_enable_ptr();
//unsigned int wid = trans.get_streaming_width(); //unsigned int wid = trans.get_streaming_width();
uint32_t aux_value = 0;
uint64_t notify_time = 0;
// cout << "accessing TIMER 0x" << hex << addr << endl; // cout << "accessing TIMER 0x" << hex << addr << endl;
if (cmd == tlm::TLM_WRITE_COMMAND) { if (cmd == tlm::TLM_WRITE_COMMAND) {
memcpy(&aux_value, ptr, len); memcpy(&aux_value, ptr, len);
@ -48,12 +52,14 @@ void Timer::b_transport( tlm::tlm_generic_payload& trans, sc_time& delay ) {
break; break;
case TIMERCMP_MEMORY_ADDRESS_LO: case TIMERCMP_MEMORY_ADDRESS_LO:
m_mtimecmp.range(31,0) = aux_value; m_mtimecmp.range(31,0) = aux_value;
// timer_event.notify(SC_ZERO_TIME);
break; break;
case TIMERCMP_MEMORY_ADDRESS_HI: case TIMERCMP_MEMORY_ADDRESS_HI:
m_mtimecmp.range(63,32) = aux_value; m_mtimecmp.range(63,32) = aux_value;
// notify needs relative time, mtimecmp works in absolute time // notify needs relative time, mtimecmp works in absolute time
notify_time = m_mtimecmp - m_mtime; 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) ); timer_event.notify( sc_time(notify_time, SC_NS) );
break; break;
} }