Files
DRAMSys/dram/src/simulation/TracePlayer.h
2014-12-02 14:44:46 +01:00

297 lines
10 KiB
C++

/*
* traceplayer.h
*
* Created on: Mar 16, 2014
* Author: robert
*/
#ifndef TRACEPLAYER_H_
#define TRACEPLAYER_H_
#include <deque>
#include <tlm.h>
#include <systemc.h>
#include <tlm_utils/simple_initiator_socket.h>
#include <tlm_utils/peq_with_cb_and_phase.h>
#include <iostream>
#include <string>
#include "MemoryManager.h"
#include "ISimulation.h"
#include "../controller/core/configuration/Configuration.h"
#include "../common/DebugManager.h"
#include "../common/xmlAddressdecoder.h"
#include "../common/TlmRecorder.h"
#include "../common/dramExtension.h"
#include "../controller/core/TimingCalculation.h"
using namespace std;
using namespace tlm;
template<unsigned int BUSWIDTH = 128>
struct TracePlayer: public sc_module
{
public:
tlm_utils::simple_initiator_socket<TracePlayer, BUSWIDTH, tlm::tlm_base_protocol_types> iSocket;
TracePlayer(sc_module_name /*name*/, string pathToTrace, unsigned int burstLength, unsigned int clkMhz,
simulation::ISimulation* simulationManager);
void start();
private:
void generateNextPayload();
tlm_sync_enum nb_transport_bw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& bwDelay);
void peqCallback(tlm_generic_payload& payload, const tlm_phase& phase);
void sendToTarget(tlm_generic_payload& payload, const tlm_phase& phase, const sc_time& delay);
tlm_utils::peq_with_cb_and_phase<TracePlayer> payloadEventQueue;
MemoryManager memoryManager;
ifstream file;
unsigned int burstlenght;
sc_time clk;
unsigned int numberOfPendingTransactions;
unsigned int transactionsSent;
unsigned int transactionsReceived;
simulation::ISimulation* simulationManager;
};
template<unsigned int BUSWIDTH>
TracePlayer<BUSWIDTH>::TracePlayer(sc_module_name, string pathToTrace, unsigned int burstLength, unsigned int clkMhz, simulation::ISimulation *simulationManager) :
payloadEventQueue(this, &TracePlayer<BUSWIDTH>::peqCallback), file(pathToTrace), burstlenght(burstLength),
numberOfPendingTransactions(0), transactionsSent(0), transactionsReceived(0), simulationManager(simulationManager)
{
if (!file.is_open())
SC_REPORT_FATAL(0, (string("Could not open trace ") + pathToTrace).c_str());
if(clkMhz == 0)
clk = core::Configuration::getInstance().memSpec.clk;
else
clk = core::FrequencyToClk(clkMhz);
this->burstlenght = core::Configuration::getInstance().memSpec.BurstLength;
iSocket.register_nb_transport_bw(this, &TracePlayer<BUSWIDTH>::nb_transport_bw);
}
template<unsigned int BUSWIDTH>
void TracePlayer<BUSWIDTH>::start()
{
bool fileIsEmpty = file.peek() == std::ifstream::traits_type::eof();
if (!fileIsEmpty)
{
generateNextPayload();
}
}
template<unsigned int BUSWIDTH>
void TracePlayer<BUSWIDTH>::generateNextPayload()
{
if(file)
{
string line;
if (std::getline(file, line))
{
std::istringstream iss(line);
string time, command, address;
iss >> time >> command >> address;
if (time.empty() || command.empty() || address.empty() )
return;
unsigned int parsedAdress = std::stoi(address.c_str(), 0, 16);
gp* payload = memoryManager.allocate();
payload->set_address(parsedAdress);
// Set data pointer
unsigned char * dataElement = new unsigned char[16*2]; // TODO: column / burst breite
payload->set_data_length(16*2); // TODO: column / burst breite
payload->set_data_ptr(dataElement);
for(int i = 0; i < 16*2; i++) // TODO: column / burst breite
dataElement[i] = 0;
if (command == "read")
{
payload->set_command(TLM_READ_COMMAND);
}
else if (command == "write")
{
payload->set_command(TLM_WRITE_COMMAND);
// Parse and set data
string data;
iss >> data;
if(!data.empty())
{
//cout << "parsing write data: " << data << std::endl;
for(int i = 0; i < 16*2; i++) // TODO column / burst breite
{
std::string byteString = "0x";
byteString.append(data.substr(2*(i+1), 2));
//cout << byteString << " " << std::stoi(byteString.c_str(), 0, 16) << endl;
dataElement[i] = std::stoi(byteString.c_str(), 0, 16);
}
}
}
else
{
SC_REPORT_FATAL(0,
(string("Corrupted tracefile, command ") + command + string(" unknown")).c_str());
}
payload->set_response_status(TLM_INCOMPLETE_RESPONSE);
payload->set_dmi_allowed(false);
payload->set_byte_enable_length(0);
payload->set_streaming_width(burstlenght);
sc_time sendingTime = std::stoull(time.c_str())*clk;
GenerationExtension* genExtension = new GenerationExtension(sendingTime);
payload->set_auto_extension(genExtension);
if (sendingTime <= sc_time_stamp())
{
payloadEventQueue.notify(*payload, BEGIN_REQ, SC_ZERO_TIME);
}
else
{
payloadEventQueue.notify(*payload, BEGIN_REQ, sendingTime - sc_time_stamp());
}
numberOfPendingTransactions++;
}
}
}
// if (file)
// {
// string time, command, address, data;
// file >> time >> command >> address;
// //if there is a newline at the end of the .stl
// if (time.empty() || command.empty() || address.empty() )
// return;
// long parsedAdress = std::stoi(address.c_str(), 0, 16);
// gp* payload = memoryManager.allocate();
// payload->set_address(parsedAdress);
// // Set data pointer
// unsigned char * dataElement = new unsigned char[16]; // TODO: column / burst breite
// payload->set_data_length(16); // TODO: column / burst breite
// payload->set_data_ptr(dataElement);
// for(int i = 0; i < 16; i++) // TODO: column / burst breite
// dataElement[i] = 0;
// if (command == "read")
// {
// payload->set_command(TLM_READ_COMMAND);
// }
// else if (command == "write")
// {
// payload->set_command(TLM_WRITE_COMMAND);
// // Parse and set data
//// file >> data;
//// unsigned int counter = 0;
//// for(int i = 0; i < 16*2-2; i=i+2) // TODO column / burst breite
//// {
//// std::string byteString = "0x";
//// byteString.append(data.substr(i+2, 2));
//// //cout << byteString << " " << std::stoi(byteString.c_str(), 0, 16) << endl;
//// dataElement[counter++] = std::stoi(byteString.c_str(), 0, 16);
//// }
// }
// else
// {
// SC_REPORT_FATAL(0,
// (string("Corrupted tracefile, command ") + command + string(" unknown")).c_str());
// }
// payload->set_response_status(TLM_INCOMPLETE_RESPONSE);
// payload->set_dmi_allowed(false);
// payload->set_byte_enable_length(0);
// payload->set_streaming_width(burstlenght);
// sc_time sendingTime = std::stoi(time.c_str())*clk;
// GenerationExtension* genExtension = new GenerationExtension(sendingTime);
// payload->set_auto_extension(genExtension);
// if (sendingTime <= sc_time_stamp())
// {
// payloadEventQueue.notify(*payload, BEGIN_REQ, SC_ZERO_TIME);
// }
// else
// {
// payloadEventQueue.notify(*payload, BEGIN_REQ, sendingTime - sc_time_stamp());
// }
// numberOfPendingTransactions++;
// }
//}
template<unsigned int BUSWIDTH>
tlm_sync_enum TracePlayer<BUSWIDTH>::nb_transport_bw(tlm_generic_payload &payload, tlm_phase &phase, sc_time &bwDelay)
{
payloadEventQueue.notify(payload, phase, bwDelay);
return TLM_ACCEPTED;
}
template<unsigned int BUSWIDTH>
void TracePlayer<BUSWIDTH>::peqCallback(tlm_generic_payload &payload, const tlm_phase &phase)
{
if (phase == BEGIN_REQ)
{
payload.acquire();
sendToTarget(payload, phase, SC_ZERO_TIME);
transactionsSent++;
DebugManager::getInstance().printDebugMessage(name(),
"Sending transaction number: " + std::to_string(transactionsSent));
}
else if (phase == END_REQ)
{
generateNextPayload();
}
else if (phase == BEGIN_RESP)
{
sendToTarget(payload, END_RESP, SC_ZERO_TIME);
payload.release();
unsigned char * dataElement = payload.get_data_ptr();
// if(payload.get_command() == TLM_READ_COMMAND)
// {
// cout << "0x";
// for(int i=0; i < 16*2; i++)
// {
// cout << hex << int(dataElement[i]);
// }
// cout << endl;
// }
simulationManager->transactionFinished();
numberOfPendingTransactions--;
transactionsReceived++;
DebugManager::getInstance().printDebugMessage(name(),
"Pending transactions in core: "
+ std::to_string(transactionsSent - transactionsReceived));
}
else if (phase == END_RESP)
{
}
else
{
SC_REPORT_FATAL(0, "TracePlayer PEQ was triggered with unknown phase");
}
}
template<unsigned int BUSWIDTH>
void TracePlayer<BUSWIDTH>::sendToTarget(tlm_generic_payload &payload, const tlm_phase &phase, const sc_time &delay)
{
tlm_phase TPhase = phase;
sc_time TDelay = delay;
iSocket->nb_transport_fw(payload, TPhase, TDelay);
}
#endif /* TRACEPLAYER_H_ */