Files
DRAMSys/DRAMSys/simulator/ExampleInitiator.h
2020-06-02 14:02:08 +02:00

204 lines
6.6 KiB
C++

#ifndef EXAMPLEINITIATOR_H
#define EXAMPLEINITIATOR_H
#include <stdlib.h>
#include <iostream>
#include "MemoryManager.h"
#include "common/dramExtensions.h"
#include "TracePlayer.h"
struct ExampleInitiator : sc_module
{
// TLM-2 socket, defaults to 32-bits wide, base protocol
tlm_utils::simple_initiator_socket<ExampleInitiator> socket;
SC_CTOR(ExampleInitiator)
: socket("socket"),
request_in_progress(0),
m_peq(this, &ExampleInitiator::peq_cb)
{
socket.register_nb_transport_bw(this, &ExampleInitiator::nb_transport_bw);
SC_THREAD(thread_process);
}
void thread_process()
{
tlm::tlm_generic_payload *trans;
tlm::tlm_phase phase;
sc_time delay;
dump_mem();
init_mem();
dump_mem();
for (int i = 0; i < 64; i++)
data[i] = 0x55;
// Generate 2 write transactions
for (int i = 0; i < 2; i++) {
int adr = i * 64;
tlm::tlm_command cmd = tlm::TLM_WRITE_COMMAND;
// Grab a new transaction from the memory manager
trans = m_mm.allocate();
trans->acquire();
trans->set_command( cmd );
trans->set_address( adr );
trans->set_data_ptr( reinterpret_cast<unsigned char *>(&data[0]) );
trans->set_data_length( 64 );
trans->set_streaming_width( 4 );
trans->set_byte_enable_ptr( 0 );
trans->set_dmi_allowed( false );
trans->set_response_status( tlm::TLM_INCOMPLETE_RESPONSE );
// ExampleInitiator must honor BEGIN_REQ/END_REQ exclusion rule
if (request_in_progress)
wait(end_request_event);
request_in_progress = trans;
phase = tlm::BEGIN_REQ;
// Timing annotation models processing time of initiator prior to call
delay = sc_time(100000, SC_PS);
cout << "Address " << hex << adr << " new, cmd=" << (cmd ? "write" : "read")
<< ", data=" << hex << data[0] << " at time " << sc_time_stamp()
<< " in " << name() << endl;
GenerationExtension *genExtension = new GenerationExtension(sc_time_stamp());
trans->set_auto_extension(genExtension);
// Non-blocking transport call on the forward path
tlm::tlm_sync_enum status;
status = socket->nb_transport_fw( *trans, phase, delay );
// Check value returned from nb_transport_fw
if (status == tlm::TLM_UPDATED) {
// The timing annotation must be honored
m_peq.notify( *trans, phase, delay );
} else if (status == tlm::TLM_COMPLETED) {
// The completion of the transaction necessarily ends the BEGIN_REQ phase
request_in_progress = 0;
// The target has terminated the transaction
check_transaction( *trans );
// Allow the memory manager to free the transaction object
trans->release();
}
wait( sc_time(500, SC_NS) );
dump_mem();
}
wait( sc_time(500, SC_NS) );
sc_stop();
}
void init_mem()
{
unsigned char buffer[64];
for (int i = 0; i < 64; i++) {
buffer[i] = 0xff;
}
for (int addr = 0; addr < 128; addr += 64) {
tlm::tlm_generic_payload trans;
trans.set_command( tlm::TLM_WRITE_COMMAND );
trans.set_address( addr );
trans.set_data_ptr( buffer );
trans.set_data_length( 64 );
socket->transport_dbg( trans );
}
}
void dump_mem()
{
for (int addr = 0; addr < 128; addr += 64) {
unsigned char buffer[64];
tlm::tlm_generic_payload trans;
trans.set_command( tlm::TLM_READ_COMMAND );
trans.set_address( addr );
trans.set_data_ptr( buffer );
trans.set_data_length( 64 );
socket->transport_dbg( trans );
cout << "\nMemory dump\n";
for (int i = 0; i < 64; i++)
cout << "mem[" << addr + i << "] = " << hex << (int)buffer[i] << endl;
}
}
// TLM-2 backward non-blocking transport method
virtual tlm::tlm_sync_enum nb_transport_bw( tlm::tlm_generic_payload &trans,
tlm::tlm_phase &phase, sc_time &delay )
{
m_peq.notify( trans, phase, delay );
return tlm::TLM_ACCEPTED;
}
// Payload event queue callback to handle transactions from target
// Transaction could have arrived through return path or backward path
void peq_cb(tlm::tlm_generic_payload &trans, const tlm::tlm_phase &phase)
{
if (phase == tlm::END_REQ || (&trans == request_in_progress
&& phase == tlm::BEGIN_RESP)) {
// The end of the BEGIN_REQ phase
request_in_progress = 0;
end_request_event.notify();
} else if (phase == tlm::BEGIN_REQ || phase == tlm::END_RESP)
SC_REPORT_FATAL("TLM-2", "Illegal transaction phase received by initiator");
if (phase == tlm::BEGIN_RESP) {
check_transaction( trans );
// Send final phase transition to target
tlm::tlm_phase fw_phase = tlm::END_RESP;
sc_time delay = sc_time(60000, SC_PS);
socket->nb_transport_fw( trans, fw_phase, delay );
// Ignore return value
// Allow the memory manager to free the transaction object
trans.release();
}
}
// Called on receiving BEGIN_RESP or TLM_COMPLETED
void check_transaction(tlm::tlm_generic_payload &trans)
{
if ( trans.is_response_error() ) {
char txt[100];
sprintf(txt, "Transaction returned with error, response status = %s",
trans.get_response_string().c_str());
SC_REPORT_ERROR("TLM-2", txt);
}
tlm::tlm_command cmd = trans.get_command();
uint64_t adr = trans.get_address();
int *ptr = reinterpret_cast<int *>( trans.get_data_ptr() );
cout << hex << adr << " check, cmd=" << (cmd ? "write" : "read")
<< ", data=" << hex << *ptr << " at time " << sc_time_stamp()
<< " in " << name() << endl;
if (cmd == tlm::TLM_READ_COMMAND)
assert( *ptr == -int(adr) );
}
MemoryManager m_mm;
unsigned char data[64];
tlm::tlm_generic_payload *request_in_progress;
sc_event end_request_event;
tlm_utils::peq_with_cb_and_phase<ExampleInitiator> m_peq;
};
#endif // EXAMPLEINITIATOR_H