162 lines
4.1 KiB
C++
162 lines
4.1 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 "ISimulationManager.h"
|
|
#include "../common/DebugManager.h"
|
|
#include "../common/xmlAddressdecoder.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,
|
|
simulation::ISimulationManager* simulationManager) :
|
|
payloadEventQueue(this, &TracePlayer::peqCallback), file(pathToTrace), 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 (!file)
|
|
{
|
|
SC_REPORT_FATAL(0, "trace is empty! Simulation stops");
|
|
}
|
|
|
|
iSocket.register_nb_transport_bw(this, &TracePlayer::nb_transport_bw);
|
|
scheduleNextPayload();
|
|
}
|
|
|
|
private:
|
|
tlm_utils::peq_with_cb_and_phase<TracePlayer> payloadEventQueue;
|
|
MemoryManager memoryManager;
|
|
ifstream file;
|
|
unsigned int numberOfPendingTransactions;
|
|
unsigned int transactionsSent;
|
|
unsigned int transactionsReceived;
|
|
simulation::ISimulationManager* simulationManager;
|
|
|
|
void scheduleNextPayload()
|
|
{
|
|
if (file)
|
|
{
|
|
string time, command, address;
|
|
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);
|
|
|
|
if (command == "read")
|
|
{
|
|
payload->set_command(TLM_READ_COMMAND);
|
|
}
|
|
else if (command == "write")
|
|
{
|
|
payload->set_command(TLM_WRITE_COMMAND);
|
|
}
|
|
else
|
|
{
|
|
SC_REPORT_FATAL(0,
|
|
(string("Corrupted tracefile, command ") + command + string(" unknown")).c_str());
|
|
}
|
|
|
|
payload->set_data_length(BUSWIDTH / 8);
|
|
payload->set_response_status(TLM_INCOMPLETE_RESPONSE);
|
|
payload->set_dmi_allowed(false);
|
|
payload->set_byte_enable_length(0);
|
|
payload->set_streaming_width(0);
|
|
|
|
sc_time sendingTime = sc_time(std::stoi(time.c_str()), SC_NS);
|
|
if (sendingTime <= sc_time_stamp())
|
|
{
|
|
payloadEventQueue.notify(*payload, BEGIN_REQ, SC_ZERO_TIME);
|
|
}
|
|
else
|
|
{
|
|
payloadEventQueue.notify(*payload, BEGIN_REQ, sendingTime - sc_time_stamp());
|
|
}
|
|
numberOfPendingTransactions++;
|
|
}
|
|
}
|
|
|
|
tlm_sync_enum nb_transport_bw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& bwDelay)
|
|
{
|
|
payloadEventQueue.notify(payload, phase, bwDelay);
|
|
return TLM_ACCEPTED;
|
|
}
|
|
|
|
void 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)
|
|
{
|
|
scheduleNextPayload();
|
|
}
|
|
else if (phase == BEGIN_RESP)
|
|
{
|
|
payload.release();
|
|
sendToTarget(payload, END_RESP, SC_ZERO_TIME);
|
|
numberOfPendingTransactions--;
|
|
transactionsReceived++;
|
|
|
|
DebugManager::getInstance().printDebugMessage(name(),
|
|
"Pending transactions in core: "
|
|
+ std::to_string(transactionsSent - transactionsReceived));
|
|
|
|
if (numberOfPendingTransactions == 0)
|
|
simulationManager->tracePlayerFinishedCallback();
|
|
}
|
|
|
|
else if (phase == END_RESP)
|
|
{
|
|
}
|
|
|
|
else
|
|
{
|
|
SC_REPORT_FATAL(0, "TracePlayer PEQ was triggered with unknown phase");
|
|
}
|
|
}
|
|
|
|
void 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_ */
|