PySysC-SC/components/target.cpp

106 lines
3.1 KiB
C++

/*
* target.cpp
*
* Created on: 02.12.2018
* Author: eyck
*/
#include "target.h"
void Memory::b_transport(tlm::tlm_generic_payload& trans, sc_time& delay) {
tlm::tlm_command cmd = trans.get_command();
sc_dt::uint64 adr = trans.get_address() / 4;
unsigned char* ptr = trans.get_data_ptr();
unsigned int len = trans.get_data_length();
unsigned char* byt = trans.get_byte_enable_ptr();
unsigned int wid = trans.get_streaming_width();
// Obliged to check address range and check for unsupported features,
// i.e. byte enables, streaming, and bursts
// Can ignore extensions
// Generate the appropriate error response
if (adr >= SIZE) {
trans.set_response_status( tlm::TLM_ADDRESS_ERROR_RESPONSE );
return;
}
if (byt != 0) {
trans.set_response_status( tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE );
return;
}
if (len > 4 || wid < len) {
trans.set_response_status( tlm::TLM_BURST_ERROR_RESPONSE );
return;
}
wait(delay);
delay = SC_ZERO_TIME;
// Obliged to implement read and write commands
if ( cmd == tlm::TLM_READ_COMMAND )
memcpy(ptr, &mem[adr], len);
else if ( cmd == tlm::TLM_WRITE_COMMAND )
memcpy(&mem[adr], ptr, len);
// Set DMI hint to indicated that DMI is supported
trans.set_dmi_allowed(true);
// Obliged to set response status to indicate successful completion
trans.set_response_status( tlm::TLM_OK_RESPONSE );
}
bool Memory::get_direct_mem_ptr(tlm::tlm_generic_payload& trans,
tlm::tlm_dmi& dmi_data)
{
// Permit read and write access
dmi_data.allow_read_write();
// Set other details of DMI region
dmi_data.set_dmi_ptr( reinterpret_cast<unsigned char*>( &mem[0] ) );
dmi_data.set_start_address( 0 );
dmi_data.set_end_address( SIZE*4-1 );
dmi_data.set_read_latency( LATENCY );
dmi_data.set_write_latency( LATENCY );
return true;
}
Memory::Memory(sc_core::sc_module_name nm)
: socket("socket")
, clk_i("clk_i")
, reset_i("reset_i")
, LATENCY(10, SC_NS)
{
// Register callbacks for incoming interface method calls
socket.register_b_transport( this, &Memory::b_transport);
socket.register_get_direct_mem_ptr(this, &Memory::get_direct_mem_ptr);
socket.register_transport_dbg( this, &Memory::transport_dbg);
// Initialize memory with random data
for (int i = 0; i < SIZE; i++)
mem[i] = 0xAA000000 | (mem_nr << 20) | (rand() % 256);
++mem_nr;
}
// TLM-2 debug transaction method
unsigned int Memory::transport_dbg(tlm::tlm_generic_payload& trans)
{
tlm::tlm_command cmd = trans.get_command();
sc_dt::uint64 adr = trans.get_address() / 4;
unsigned char* ptr = trans.get_data_ptr();
unsigned int len = trans.get_data_length();
// Calculate the number of bytes to be actually copied
unsigned int num_bytes = (len < (SIZE - adr) * 4) ? len : (SIZE - adr) * 4;
if ( cmd == tlm::TLM_READ_COMMAND )
memcpy(ptr, &mem[adr], num_bytes);
else if ( cmd == tlm::TLM_WRITE_COMMAND )
memcpy(&mem[adr], ptr, num_bytes);
return num_bytes;
}