96 lines
2.9 KiB
C++
96 lines
2.9 KiB
C++
#include "Timer.h"
|
|
|
|
SC_HAS_PROCESS(Timer);
|
|
Timer::Timer(sc_module_name name): sc_module(name)
|
|
,socket("timer_socket"), m_mtime(0), m_mtimecmp(0), irq_value(false) {
|
|
|
|
socket.register_b_transport(this, &Timer::b_transport);
|
|
|
|
SC_THREAD(run);
|
|
}
|
|
|
|
/**
|
|
* @brief Waits for event timer_event and triggers an IRQ
|
|
*
|
|
*/
|
|
void Timer::run() {
|
|
while(true) {
|
|
|
|
// timer_event.notify( sc_time(10000, SC_NS) );
|
|
|
|
wait(timer_event);
|
|
|
|
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));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @brief TLM-2.0 socket implementaiton
|
|
* @param trans TLM-2.0 transaction
|
|
* @param delay transactino delay time
|
|
*/
|
|
void Timer::b_transport( tlm::tlm_generic_payload& trans, sc_time& delay ) {
|
|
tlm::tlm_command cmd = trans.get_command();
|
|
sc_dt::uint64 addr = trans.get_address();
|
|
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 char* byt = trans.get_byte_enable_ptr();
|
|
//unsigned int wid = trans.get_streaming_width();
|
|
|
|
// cout << "accessing TIMER 0x" << hex << addr << endl;
|
|
if (cmd == tlm::TLM_WRITE_COMMAND) {
|
|
memcpy(&aux_value, ptr, len);
|
|
switch (addr) {
|
|
case TIMER_MEMORY_ADDRESS_LO:
|
|
m_mtime.range(31,0) = aux_value;
|
|
break;
|
|
case TIMER_MEMORY_ADDRESS_HI:
|
|
m_mtime.range(63,32) = aux_value;
|
|
break;
|
|
case TIMERCMP_MEMORY_ADDRESS_LO:
|
|
m_mtimecmp.range(31,0) = aux_value;
|
|
// timer_event.notify(SC_ZERO_TIME);
|
|
break;
|
|
case TIMERCMP_MEMORY_ADDRESS_HI:
|
|
m_mtimecmp.range(63,32) = aux_value;
|
|
// notify needs relative time, mtimecmp works in absolute time
|
|
notify_time = m_mtimecmp - m_mtime;
|
|
// cout << "time: " << sc_core::sc_time_stamp()
|
|
// << ": interrupt will be in " << dec << notify_time
|
|
// << " ns" << endl;
|
|
timer_event.notify( sc_time(notify_time, SC_NS) );
|
|
break;
|
|
}
|
|
} else { // TLM_READ_COMMAND
|
|
switch (addr) {
|
|
case TIMER_MEMORY_ADDRESS_LO:
|
|
m_mtime = sc_time_stamp().value();
|
|
aux_value = m_mtime.range(31,0);
|
|
break;
|
|
case TIMER_MEMORY_ADDRESS_HI:
|
|
aux_value = m_mtime.range(63,32);
|
|
break;
|
|
case TIMERCMP_MEMORY_ADDRESS_LO:
|
|
aux_value = m_mtimecmp.range(31,0);
|
|
break;
|
|
case TIMERCMP_MEMORY_ADDRESS_HI:
|
|
aux_value = m_mtimecmp.range(63,32);
|
|
break;
|
|
}
|
|
memcpy(ptr, &aux_value, len);
|
|
}
|
|
|
|
trans.set_response_status( tlm::TLM_OK_RESPONSE );
|
|
}
|