changed IRQ line to TLM socket
This commit is contained in:
parent
0c25abdb00
commit
098aebc15d
33
inc/CPU.h
33
inc/CPU.h
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
14
src/CPU.cpp
14
src/CPU.cpp
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue