risc-v-tlm/src/Memory.cpp

180 lines
5.9 KiB
C++
Raw Normal View History

2018-09-11 00:44:54 +08:00
#include "Memory.h"
2018-12-13 01:15:21 +08:00
2018-09-11 00:44:54 +08:00
SC_HAS_PROCESS(Memory);
Memory::Memory(sc_module_name name, string filename): sc_module(name)
,socket("socket")
,LATENCY(SC_ZERO_TIME) {
// 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);
2018-12-13 01:15:21 +08:00
mem = new uint8_t[SIZE];
//memset(mem, 0, SIZE*sizeof(uint8_t));
2018-09-11 00:44:54 +08:00
2018-12-13 01:15:21 +08:00
memory_offset = 0;
2018-09-21 15:24:49 +08:00
readHexFile(filename);
2018-12-13 01:15:21 +08:00
log = Log::getInstance();
log->SC_log(Log::INFO) << "Using file: " << filename << endl;
2018-09-11 00:44:54 +08:00
}
Memory::Memory(sc_module_name name, bool use_file): sc_module(name)
,socket("socket")
,LATENCY(SC_ZERO_TIME) {
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);
2019-03-29 05:52:36 +08:00
memory_offset = 0;
program_counter = 0;
2018-12-13 01:15:21 +08:00
//memset(mem, 0, SIZE*sizeof(uint8_t));
}
2018-09-11 00:44:54 +08:00
uint32_t Memory::getPCfromHEX() {
return program_counter;
}
2018-09-11 00:44:54 +08:00
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();
2018-09-11 00:44:54 +08:00
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();
2018-12-13 01:15:21 +08:00
adr = adr - memory_offset;
2018-09-11 00:44:54 +08:00
// 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 >= sc_dt::uint64(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;
}
// 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);
// Illustrates that b_transport may block
wait(delay);
// Reset timing annotation after waiting
delay = SC_ZERO_TIME;
// *********************************************
// Set DMI hint to indicated that DMI is supported
// *********************************************
2019-03-29 05:52:36 +08:00
if (memory_offset == 0) {
trans.set_dmi_allowed(true);
} else {
trans.set_dmi_allowed(false);
}
2018-09-11 00:44:54 +08:00
// 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;
}
unsigned int Memory::transport_dbg(tlm::tlm_generic_payload& trans)
{
tlm::tlm_command cmd = trans.get_command();
sc_dt::uint64 adr = trans.get_address();
2018-09-11 00:44:54 +08:00
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;
}
void Memory::readHexFile(string filename) {
ifstream hexfile;
string line;
int byte_count;
2018-12-13 01:15:21 +08:00
uint32_t address;
2018-09-11 00:44:54 +08:00
int i = 0;
2018-12-13 01:15:21 +08:00
uint32_t extended_address = 0;
2018-09-11 00:44:54 +08:00
hexfile.open(filename);
if (hexfile.is_open()) {
while(getline(hexfile, line) ) {
if (line[0] == ':') {
2018-09-21 15:24:49 +08:00
if (line.substr(7,2) == "00") {
2018-09-11 00:44:54 +08:00
/* Data */
byte_count = stol(line.substr(1,2), nullptr, 16);
address = stol(line.substr(3,4), nullptr, 16);
address = address + extended_address;
2018-12-13 01:15:21 +08:00
//cout << "00 address 0x" << hex << address << endl;
for (i=0; i < byte_count; i++) {
2019-03-29 05:52:36 +08:00
mem[address+i] = stol(line.substr(9 + (i * 2), 2), nullptr, 16);
2018-09-21 15:24:49 +08:00
}
} else if (line.substr(7,2) == "02") {
/* Extended segment address */
extended_address = stol(line.substr(9,4), nullptr, 16) * 16;
2018-12-13 01:15:21 +08:00
cout << "02 extended address 0x" << hex << extended_address << endl;
} else if (line.substr(7,2) == "03") {
/* Start segment address */
2018-09-21 15:24:49 +08:00
uint32_t code_segment;
code_segment = stol(line.substr(9,4), nullptr, 16) * 16; /* ? */
program_counter = stol(line.substr(13,4), nullptr, 16);
program_counter = program_counter + code_segment;
2018-12-13 01:15:21 +08:00
cout << "03 PC set to 0x" << hex << program_counter << endl;
} else if (line.substr(7,2) == "04") {
/* Start segment address */
memory_offset = stol(line.substr(9,4), nullptr, 16) << 16;
extended_address = 0;
cout << "04 address set to 0x" << hex << extended_address << endl;
cout << "04 offset set to 0x" << hex << memory_offset << endl;
} else if (line.substr(7,2) == "05") {
program_counter = stol(line.substr(9,8), nullptr, 16);
cout << "05 PC set to 0x" << hex << program_counter << endl;
2018-09-11 00:44:54 +08:00
}
}
}
hexfile.close();
} else {
SC_REPORT_ERROR("Memory", "Open file error");
}
}