/* * traceplayer.h * * Created on: Mar 16, 2014 * Author: robert */ #ifndef TRACEPLAYER_H_ #define TRACEPLAYER_H_ #include #include #include #include #include #include #include #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 struct TracePlayer: public sc_module { public: tlm_utils::simple_initiator_socket 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 payloadEventQueue; MemoryManager memoryManager; ifstream file; unsigned int burstlenght; sc_time clk; unsigned int numberOfPendingTransactions; unsigned int transactionsSent; unsigned int transactionsReceived; simulation::ISimulation* simulationManager; }; template TracePlayer::TracePlayer(sc_module_name, string pathToTrace, unsigned int burstLength, unsigned int clkMhz, simulation::ISimulation *simulationManager) : payloadEventQueue(this, &TracePlayer::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().Timings.clk; else clk = core::FrequencyToClk(clkMhz); this->burstlenght = core::Configuration::getInstance().BurstLength; iSocket.register_nb_transport_bw(this, &TracePlayer::nb_transport_bw); } template void TracePlayer::start() { bool fileIsEmpty = file.peek() == std::ifstream::traits_type::eof(); if (!fileIsEmpty) { generateNextPayload(); } } template void TracePlayer::generateNextPayload() { 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(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 tlm_sync_enum TracePlayer::nb_transport_bw(tlm_generic_payload &payload, tlm_phase &phase, sc_time &bwDelay) { payloadEventQueue.notify(payload, phase, bwDelay); return TLM_ACCEPTED; } template void TracePlayer::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(); 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 void TracePlayer::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_ */