From 3725eb0c8c034da5108c252d3cc88595dd9b591e Mon Sep 17 00:00:00 2001 From: Lukas Steiner Date: Wed, 9 Sep 2020 14:26:27 +0200 Subject: [PATCH] Parse larger chunks of the input file to create less system calls. --- DRAMSys/simulator/StlPlayer.h | 203 +++++++++++++++++------------- DRAMSys/simulator/TracePlayer.cpp | 5 - DRAMSys/simulator/TracePlayer.h | 1 - DRAMSys/simulator/TraceSetup.cpp | 1 + DRAMSys/simulator/main.cpp | 2 + 5 files changed, 120 insertions(+), 92 deletions(-) diff --git a/DRAMSys/simulator/StlPlayer.h b/DRAMSys/simulator/StlPlayer.h index 29f6e6ef..e1f261a3 100644 --- a/DRAMSys/simulator/StlPlayer.h +++ b/DRAMSys/simulator/StlPlayer.h @@ -43,6 +43,14 @@ #include #include "TracePlayer.h" +struct LineContent +{ + sc_time sendingTime; + tlm::tlm_command cmd; + uint64_t addr; + std::vector data; +}; + template class StlPlayer : public TracePlayer { @@ -58,120 +66,141 @@ public: SC_REPORT_FATAL(0, (std::string("Could not open trace ") + pathToTrace).c_str()); this->playerClk = playerClk; - this->burstlength = Configuration::getInstance().memSpec->burstLength; - this->dataLength = Configuration::getInstance().getBytesPerBurst(); - this->lineCnt = 0; + burstlength = Configuration::getInstance().memSpec->burstLength; + dataLength = Configuration::getInstance().getBytesPerBurst(); + lineCnt = 0; + + parseTraceFile(); } - void nextPayload() + void parseTraceFile() { std::string line; - while (line.empty() && file) { + unsigned parsedLines = 0; + lineContents.clear(); + while (file && !file.eof() && parsedLines < 10000) + { // Get a new line from the input file. std::getline(file, line); lineCnt++; // If the line starts with '#' (commented lines) the transaction is ignored. - if (!line.empty() && line.at(0) == '#') - line.clear(); + if (line.empty() || line.at(0) == '#') + continue; + + parsedLines++; + lineContents.emplace_back(); + LineContent &content = lineContents.back(); + + // Trace files MUST provide timestamp, command and address for every + // transaction. The data information depends on the storage mode + // configuration. + std::string time; + std::string command; + std::string address; + std::string dataStr; + + std::istringstream iss(line); + + // Get the timestamp for the transaction. + iss >> time; + if (time.empty()) + SC_REPORT_FATAL("StlPlayer", + ("Malformed trace file. Timestamp could not be found (line " + std::to_string( + lineCnt) + ").").c_str()); + content.sendingTime = std::stoull(time.c_str()) * playerClk; + + // Get the command. + iss >> command; + if (command.empty()) + SC_REPORT_FATAL("StlPlayer", + ("Malformed trace file. Command could not be found (line " + std::to_string( + lineCnt) + ").").c_str()); + + if (command == "read") + content.cmd = tlm::TLM_READ_COMMAND; + else if (command == "write") + content.cmd = tlm::TLM_WRITE_COMMAND; + else + SC_REPORT_FATAL("StlPlayer", + (std::string("Corrupted tracefile, command ") + command + + std::string(" unknown")).c_str()); + + // Get the address. + iss >> address; + if (address.empty()) + SC_REPORT_FATAL("StlPlayer", + ("Malformed trace file. Address could not be found (line " + + std::to_string(lineCnt) + ").").c_str()); + content.addr = std::stoull(address.c_str(), nullptr, 16); + + // Get the data if necessary. + if (storageEnabled && content.cmd == tlm::TLM_WRITE_COMMAND) + { + // The input trace file must provide the data to be stored into the memory. + iss >> dataStr; + if (dataStr.empty()) + SC_REPORT_FATAL("StlPlayer", + ("Malformed trace file. Data information could not be found (line " + std::to_string( + lineCnt) + ").").c_str()); + + // Check if data length in the trace file is correct. + // We need two characters to represent 1 byte in hexadecimal. Offset for 0x prefix. + if (dataStr.length() != (dataLength * 2 + 2)) + SC_REPORT_FATAL("StlPlayer", + ("Data in the trace file has an invalid length (line " + std::to_string( + lineCnt) + ").").c_str()); + + // Set data + for (unsigned i = 0; i < dataLength; i++) + content.data.emplace_back((unsigned char)std::stoi(dataStr.substr(i * 2 + 2, 2).c_str(), nullptr, 16)); + } + } + lineIterator = lineContents.cbegin(); + } + + void nextPayload() + { + if (lineIterator == lineContents.cend()) + { + // Read new lines of file. + parseTraceFile(); + if (lineIterator == lineContents.cend()) + { + // The file is empty. Nothing more to do. + this->finish(); + return; + } } - if (!file) { - // The file is empty. Nothing more to do. - this->finish(); - return; - } else { - numberOfTransactions++; - } + numberOfTransactions++; + // Allocate a generic payload for this request. tlm::tlm_generic_payload *payload = this->allocatePayload(); payload->acquire(); - unsigned char *data = payload->get_data_ptr(); - - // Trace files MUST provide timestamp, command and address for every - // transaction. The data information depends on the storage mode - // configuration. - std::string time; - std::string command; - std::string address; - std::string dataStr; - - std::istringstream iss(line); - - // Get the timestamp for the transaction. - iss >> time; - if (time.empty()) - SC_REPORT_FATAL("StlPlayer", - ("Malformed trace file. Timestamp could not be found (line " + std::to_string( - lineCnt) + ").").c_str()); - sc_time sendingTime = std::stoull(time.c_str()) * playerClk; - - // Get the command. - iss >> command; - if (command.empty()) - SC_REPORT_FATAL("StlPlayer", - ("Malformed trace file. Command could not be found (line " + std::to_string( - lineCnt) + ").").c_str()); - enum tlm::tlm_command cmd; - if (command == "read") { - cmd = tlm::TLM_READ_COMMAND; - } else if (command == "write") { - cmd = tlm::TLM_WRITE_COMMAND; - } else { - SC_REPORT_FATAL("StlPlayer", - (std::string("Corrupted tracefile, command ") + command + - std::string(" unknown")).c_str()); - } - - // Get the address. - iss >> address; - if (address.empty()) - SC_REPORT_FATAL("StlPlayer", - ("Malformed trace file. Address could not be found (line " - + std::to_string(lineCnt) + ").").c_str()); - unsigned long long addr = std::stoull(address.c_str(), 0, 16); - - // Get the data if necessary. - if (storageEnabled && cmd == tlm::TLM_WRITE_COMMAND) - { - // The input trace file must provide the data to be stored into the memory. - iss >> dataStr; - if (dataStr.empty()) - SC_REPORT_FATAL("StlPlayer", - ("Malformed trace file. Data information could not be found (line " + std::to_string( - lineCnt) + ").").c_str()); - - // Check if data length in the trace file is correct. We need two characters to represent 1 byte in hexadecimal. Offset for 0x prefix. - if (dataStr.length() != (dataLength * 2 + 2)) - SC_REPORT_FATAL("StlPlayer", - ("Data in the trace file has an invalid length (line " + std::to_string( - lineCnt) + ").").c_str()); - - // Set data - for (unsigned i = 0; i < dataLength; i++) - data[i] = (unsigned char)std::stoi(dataStr.substr(i * 2 + 2, 2).c_str(), 0, 16); - } // Fill up the payload. - payload->set_address(addr); + payload->set_address(lineIterator->addr); payload->set_response_status(tlm::TLM_INCOMPLETE_RESPONSE); payload->set_dmi_allowed(false); payload->set_byte_enable_length(0); payload->set_streaming_width(burstlength); payload->set_data_length(dataLength); - payload->set_data_ptr(data); - payload->set_command(cmd); + payload->set_command(lineIterator->cmd); + std::copy(lineIterator->data.begin(), lineIterator->data.end(), payload->get_data_ptr()); if (relative == false) { // Send the transaction directly or schedule it to be sent in the future. - if (sendingTime <= sc_time_stamp()) + if (lineIterator->sendingTime <= sc_time_stamp()) this->payloadEventQueue.notify(*payload, tlm::BEGIN_REQ, SC_ZERO_TIME); else this->payloadEventQueue.notify(*payload, tlm::BEGIN_REQ, - sendingTime - sc_time_stamp()); + lineIterator->sendingTime - sc_time_stamp()); } else - payloadEventQueue.notify(*payload, tlm::BEGIN_REQ, sendingTime); + payloadEventQueue.notify(*payload, tlm::BEGIN_REQ, lineIterator->sendingTime); + + lineIterator++; } private: @@ -181,7 +210,9 @@ private: unsigned int burstlength; unsigned int dataLength; sc_time playerClk; // May be different from the memory clock! + + std::vector lineContents; + std::vector::const_iterator lineIterator; }; #endif // STLPLAYER_H - diff --git a/DRAMSys/simulator/TracePlayer.cpp b/DRAMSys/simulator/TracePlayer.cpp index 1dc090fd..1162963e 100644 --- a/DRAMSys/simulator/TracePlayer.cpp +++ b/DRAMSys/simulator/TracePlayer.cpp @@ -111,11 +111,6 @@ void TracePlayer::sendToTarget(tlm_generic_payload &payload, const tlm_phase &ph iSocket->nb_transport_fw(payload, TPhase, TDelay); } -void TracePlayer::setNumberOfTransactions(unsigned int n) -{ - numberOfTransactions = n; -} - unsigned int TracePlayer::getNumberOfLines(std::string pathToTrace) { // Reference: http://stackoverflow.com/questions/3482064/counting-the-number-of-lines-in-a-text-file diff --git a/DRAMSys/simulator/TracePlayer.h b/DRAMSys/simulator/TracePlayer.h index 638bb421..e1a35b56 100644 --- a/DRAMSys/simulator/TracePlayer.h +++ b/DRAMSys/simulator/TracePlayer.h @@ -64,7 +64,6 @@ protected: tlm_utils::peq_with_cb_and_phase payloadEventQueue; void finish(); void terminate(); - void setNumberOfTransactions(unsigned int n); unsigned int numberOfTransactions = 0; bool storageEnabled = false; diff --git a/DRAMSys/simulator/TraceSetup.cpp b/DRAMSys/simulator/TraceSetup.cpp index 28c42cf1..73bdb3f1 100644 --- a/DRAMSys/simulator/TraceSetup.cpp +++ b/DRAMSys/simulator/TraceSetup.cpp @@ -103,6 +103,7 @@ void TraceSetup::tracePlayerTerminates() if (finishedTracePlayers == numberOfTracePlayers) sc_stop(); } + void TraceSetup::transactionFinished() { remainingTransactions--; diff --git a/DRAMSys/simulator/main.cpp b/DRAMSys/simulator/main.cpp index c0c93065..7d29c614 100644 --- a/DRAMSys/simulator/main.cpp +++ b/DRAMSys/simulator/main.cpp @@ -141,6 +141,8 @@ int sc_main(int argc, char **argv) std::cout << "Simulation took " + std::to_string(elapsed.count()) + " seconds." << std::endl; delete dramSys; + for (auto player : players) + delete player; delete ts; return 0;