diff --git a/DRAMSys/library/resources/simulations/ddr5-generator-example.json b/DRAMSys/library/resources/simulations/ddr5-generator-example.json new file mode 100644 index 00000000..1835e48b --- /dev/null +++ b/DRAMSys/library/resources/simulations/ddr5-generator-example.json @@ -0,0 +1,34 @@ +{ + "simulation": { + "addressmapping": "am_ddr5_2x8x2Gbx4_dimm_p1KB_rbc.json", + "mcconfig": "fr_fcfs.json", + "memspec": "JEDEC_2x8x2Gbx4_DDR5-3200A.json", + "simconfig": "ddr5.json", + "simulationid": "ddr5-example", + "thermalconfig": "config.json", + "tracesetup": [ + { + "clkMhz": 2000, + "type": "generator", + "name": "gen0", + "numRequests": 2000, + "rwRatio": 0.85, + "addressDistribution": "sequential", + "addressIncrement": 256, + "maxPendingReadRequests": 8, + "maxPendingWriteRequests": 8 + }, + { + "clkMhz": 2000, + "type": "generator", + "name": "gen1", + "numRequests": 2000, + "rwRatio": 0.85, + "addressDistribution": "random", + "seed": 123456, + "maxPendingReadRequests": 8, + "maxPendingWriteRequests": 8 + } + ] + } +} diff --git a/DRAMSys/simulator/CMakeLists.txt b/DRAMSys/simulator/CMakeLists.txt index 2487e3af..a938367c 100644 --- a/DRAMSys/simulator/CMakeLists.txt +++ b/DRAMSys/simulator/CMakeLists.txt @@ -31,6 +31,7 @@ # Authors: # Matthias Jung # Lukas Steiner +# Derek Christ cmake_minimum_required(VERSION 3.10) @@ -48,8 +49,8 @@ add_executable(DRAMSys ExampleInitiator.h MemoryManager.cpp StlPlayer.cpp - TraceGenerator.cpp - TracePlayer.cpp + TrafficGenerator.cpp + TrafficInitiator.cpp TraceSetup.cpp ) diff --git a/DRAMSys/simulator/StlPlayer.cpp b/DRAMSys/simulator/StlPlayer.cpp index 1a85a6b3..109309bd 100644 --- a/DRAMSys/simulator/StlPlayer.cpp +++ b/DRAMSys/simulator/StlPlayer.cpp @@ -35,29 +35,43 @@ * Matthias Jung * Éder F. Zulian * Felipe S. Prado + * Derek Christ */ #include "StlPlayer.h" using namespace tlm; -StlPlayer::StlPlayer(sc_module_name name, - std::string pathToTrace, - sc_time playerClk, +StlPlayer::StlPlayer(const sc_module_name &name, + const std::string &pathToTrace, + const sc_time &playerClk, + unsigned int maxPendingReadRequests, + unsigned int maxPendingWriteRequests, TraceSetup *setup, - bool relative) - : TracePlayer(name, setup), file(pathToTrace), - currentBuffer(&lineContents[0]), - parseBuffer(&lineContents[1]), - relative(relative) + bool relative) : + TrafficInitiator(name, setup, maxPendingReadRequests, maxPendingWriteRequests), + file(pathToTrace), currentBuffer(&lineContents[0]), parseBuffer(&lineContents[1]), + relative(relative), playerClk(playerClk) { if (!file.is_open()) SC_REPORT_FATAL("StlPlayer", (std::string("Could not open trace ") + pathToTrace).c_str()); + else + { + std::string line; + while (std::getline(file, line)) + { + if (line.size() > 1 && line[0] != '#') + numberOfLines++; + } + file.clear(); + file.seekg(0); + + if (numberOfLines == 0) + SC_REPORT_FATAL("StlPlayer", "Trace file is empty"); + } - this->playerClk = playerClk; burstLength = Configuration::getInstance().memSpec->burstLength; dataLength = Configuration::getInstance().memSpec->bytesPerBurst; - lineCnt = 0; currentBuffer->reserve(lineBufferSize); parseBuffer->reserve(lineBufferSize); @@ -72,7 +86,7 @@ StlPlayer::~StlPlayer() parserThread.join(); } -void StlPlayer::nextPayload() +void StlPlayer::sendNextPayload() { if (lineIterator == currentBuffer->cend()) { @@ -85,8 +99,6 @@ void StlPlayer::nextPayload() } } - numberOfTransactions++; - // Allocate a generic payload for this request. tlm_generic_payload *payload = setup->allocatePayload(); payload->acquire(); @@ -104,7 +116,7 @@ void StlPlayer::nextPayload() sc_time sendingTime; sc_time sendingOffset; - if (numberOfTransactions == 1) + if (transactionsSent == 0) sendingOffset = SC_ZERO_TIME; else sendingOffset = playerClk - (sc_time_stamp() % playerClk); @@ -117,6 +129,12 @@ void StlPlayer::nextPayload() sendToTarget(*payload, BEGIN_REQ, sendingTime - sc_time_stamp()); transactionsSent++; + + if (payload->get_command() == tlm::TLM_READ_COMMAND) + pendingReadRequests++; + else if (payload->get_command() == tlm::TLM_WRITE_COMMAND) + pendingWriteRequests++; + PRINTDEBUGMESSAGE(name(), "Performing request #" + std::to_string(transactionsSent)); lineIterator++; } @@ -128,6 +146,7 @@ void StlPlayer::parseTraceFile() while (file && !file.eof() && parsedLines < lineBufferSize) { // Get a new line from the input file. + std::string line; std::getline(file, line); lineCnt++; @@ -142,12 +161,9 @@ void StlPlayer::parseTraceFile() // Trace files MUST provide timestamp, command and address for every // transaction. The data information depends on the storage mode // configuration. - time.clear(); - command.clear(); - address.clear(); - dataStr.clear(); + std::string time, command, address, dataStr; + std::istringstream iss; - iss.clear(); iss.str(line); // Get the timestamp for the transaction. @@ -156,7 +172,7 @@ void StlPlayer::parseTraceFile() 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; + content.sendingTime = std::stoull(time) * playerClk; // Get the command. iss >> command; @@ -180,7 +196,7 @@ void StlPlayer::parseTraceFile() 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); + content.addr = std::stoull(address, nullptr, 16); // Get the data if necessary. if (storageEnabled && content.cmd == TLM_WRITE_COMMAND) @@ -202,7 +218,7 @@ void StlPlayer::parseTraceFile() // Set data for (unsigned i = 0; i < dataLength; i++) content.data.emplace_back(static_cast - (std::stoi(dataStr.substr(i * 2 + 2, 2).c_str(), nullptr, 16))); + (std::stoi(dataStr.substr(i * 2 + 2, 2), nullptr, 16))); } } } @@ -221,3 +237,8 @@ std::vector::const_iterator StlPlayer::swapBuffers() return currentBuffer->cbegin(); } + +uint64_t StlPlayer::getNumberOfLines() const +{ + return numberOfLines; +} diff --git a/DRAMSys/simulator/StlPlayer.h b/DRAMSys/simulator/StlPlayer.h index cacf37bf..45c883a7 100644 --- a/DRAMSys/simulator/StlPlayer.h +++ b/DRAMSys/simulator/StlPlayer.h @@ -35,6 +35,7 @@ * Matthias Jung * Éder F. Zulian * Felipe S. Prado + * Derek Christ */ #ifndef STLPLAYER_H @@ -45,7 +46,7 @@ #include #include #include "TraceSetup.h" -#include "TracePlayer.h" +#include "TrafficInitiator.h" struct LineContent { @@ -55,29 +56,30 @@ struct LineContent std::vector data; }; -class StlPlayer : public TracePlayer +class StlPlayer : public TrafficInitiator { public: - StlPlayer(sc_module_name name, - std::string pathToTrace, - sc_time playerClk, + StlPlayer(const sc_module_name &name, + const std::string &pathToTrace, + const sc_time &playerClk, + unsigned int maxPendingReadRequests, + unsigned int maxPendingWriteRequests, TraceSetup *setup, bool relative); - virtual ~StlPlayer() override; - - virtual void nextPayload() override; + ~StlPlayer() override; + void sendNextPayload() override; + uint64_t getNumberOfLines() const; private: void parseTraceFile(); std::vector::const_iterator swapBuffers(); std::ifstream file; - uint64_t lineCnt; + uint64_t lineCnt = 0; + uint64_t numberOfLines = 0; - unsigned int burstLength; - unsigned int dataLength; - sc_time playerClk; // May be different from the memory clock! + const sc_time playerClk; // May be different from the memory clock! static constexpr unsigned lineBufferSize = 10000; @@ -88,14 +90,6 @@ private: std::thread parserThread; - std::string time; - std::string command; - std::string address; - std::string dataStr; - - std::string line; - std::istringstream iss; - const bool relative; }; diff --git a/DRAMSys/simulator/TraceGenerator.cpp b/DRAMSys/simulator/TraceGenerator.cpp deleted file mode 100644 index b08080ee..00000000 --- a/DRAMSys/simulator/TraceGenerator.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2015, Technische Universität Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Robert Gernhardt - * Matthias Jung - */ - -#include "TraceGenerator.h" - -TraceGenerator::TraceGenerator(sc_module_name name, - unsigned int fCKMhz, TraceSetup *setup) - : TracePlayer(name, setup), transCounter(0) -{ - if (fCKMhz == 0) - tCK = Configuration::getInstance().memSpec->tCK; - else - tCK = sc_time(1.0 / fCKMhz, SC_US); - - burstlenght = Configuration::getInstance().memSpec->burstLength; -} - -void TraceGenerator::nextPayload() -{ - if (transCounter >= 1000) // TODO set limit! - terminate(); - - tlm::tlm_generic_payload *payload = setup->allocatePayload(); - payload->acquire(); - unsigned char *dataElement = new unsigned char[16]; - // TODO: column / burst breite - - payload->set_address(0x0); - payload->set_response_status(tlm::TLM_INCOMPLETE_RESPONSE); - payload->set_dmi_allowed(false); - payload->set_byte_enable_length(0); - payload->set_streaming_width(burstlenght); - payload->set_data_ptr(dataElement); - payload->set_data_length(16); - payload->set_command(tlm::TLM_READ_COMMAND); - transCounter++; - - // TODO: do not send two requests in the same cycle - sendToTarget(*payload, tlm::BEGIN_REQ, SC_ZERO_TIME); - transactionsSent++; - PRINTDEBUGMESSAGE(name(), "Performing request #" + std::to_string(transactionsSent)); -} diff --git a/DRAMSys/simulator/TraceGenerator.h b/DRAMSys/simulator/TraceGenerator.h deleted file mode 100644 index 8993e8d3..00000000 --- a/DRAMSys/simulator/TraceGenerator.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2015, Technische Universität Kaiserslautern - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: - * Janik Schlemminger - * Robert Gernhardt - * Matthias Jung - */ - -#ifndef TRACEGENERATOR_H -#define TRACEGENERATOR_H - -#include "TracePlayer.h" -#include "TraceSetup.h" - -class TraceGenerator : public TracePlayer -{ -public: - TraceGenerator(sc_module_name name, unsigned int fCKMhz, TraceSetup *setup); - virtual void nextPayload() override; - -private: - unsigned int burstlenght; - sc_time tCK; - unsigned int transCounter; -}; - -#endif // TRACEGENERATOR_H - diff --git a/DRAMSys/simulator/TraceSetup.cpp b/DRAMSys/simulator/TraceSetup.cpp index 871be829..cff6e372 100644 --- a/DRAMSys/simulator/TraceSetup.cpp +++ b/DRAMSys/simulator/TraceSetup.cpp @@ -32,16 +32,18 @@ * Authors: * Matthias Jung * Luiza Correa + * Derek Christ */ #include "TraceSetup.h" #include "StlPlayer.h" +#include "TrafficGenerator.h" using namespace tlm; -TraceSetup::TraceSetup(std::string uri, - std::string pathToResources, - std::vector *players) +TraceSetup::TraceSetup(const std::string &uri, + const std::string &pathToResources, + std::vector &players) { // Load Simulation: nlohmann::json simulationdoc = parseJSON(uri); @@ -50,62 +52,139 @@ TraceSetup::TraceSetup(std::string uri, SC_REPORT_FATAL("TraceSetup", "Cannot load simulation: simulation node expected"); - // Load TracePlayers: + // Load TrafficInitiators: if (simulationdoc["simulation"]["tracesetup"].empty()) SC_REPORT_FATAL("TraceSetup", "tracesetup is empty"); - for (auto it : simulationdoc["simulation"]["tracesetup"].items()) + for (auto &it : simulationdoc["simulation"]["tracesetup"].items()) { auto value = it.value(); if (!value.empty()) { sc_time playerClk; + if (!value["clkMhz"].is_number_unsigned()) + SC_REPORT_FATAL("TraceSetup", "Frequency is not a number."); + unsigned int frequencyMHz = value["clkMhz"]; if (frequencyMHz == 0) - SC_REPORT_FATAL("TraceSetup", "No frequency defined"); + SC_REPORT_FATAL("TraceSetup", "Frequency must not be zero."); else playerClk = sc_time(1.0 / frequencyMHz, SC_US); + if (!value["name"].is_string()) + SC_REPORT_FATAL("TraceSetup", "No trace name defined."); + std::string name = value["name"]; - size_t pos = name.rfind('.'); - if (pos == std::string::npos) - throw std::runtime_error("Name of the trace file does not contain a valid extension."); + unsigned int maxPendingReadRequests = 0; + unsigned int maxPendingWriteRequests = 0; - // Get the extension and make it lower case - std::string ext = name.substr(pos + 1); - std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower); + if (value["maxPendingReadRequests"].is_number_unsigned()) + maxPendingReadRequests = value["maxPendingReadRequests"]; - std::string stlFile = pathToResources + std::string("traces/") + name; - std::string moduleName = name; + if (value["maxPendingWriteRequests"].is_number_unsigned()) + maxPendingWriteRequests = value["maxPendingWriteRequests"]; - // replace all '.' to '_' - std::replace(moduleName.begin(), moduleName.end(), '.', '_'); + std::string type; - TracePlayer *player; - if (ext == "stl") - player = new StlPlayer(moduleName.c_str(), stlFile, playerClk, this, false); - else if (ext == "rstl") - player = new StlPlayer(moduleName.c_str(), stlFile, playerClk, this, true); + // Defaulting to type "player" when not specified + if (!value["type"].is_string()) + type = "player"; else - throw std::runtime_error("Unsupported file extension in " + name); + type = value["type"]; - players->push_back(player); + if (type == "player") + { + size_t pos = name.rfind('.'); + if (pos == std::string::npos) + throw std::runtime_error("Name of the trace file does not contain a valid extension."); - if (Configuration::getInstance().simulationProgressBar) - totalTransactions += player->getNumberOfLines(stlFile); + // Get the extension and make it lower case + std::string ext = name.substr(pos + 1); + std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower); + + std::stringstream stlFileStream; + stlFileStream << pathToResources << "traces/" << name; + std::string stlFile = stlFileStream.str(); + std::string moduleName = name; + + // replace all '.' to '_' + std::replace(moduleName.begin(), moduleName.end(), '.', '_'); + + StlPlayer *player; + if (ext == "stl") + player = new StlPlayer(moduleName.c_str(), stlFile, playerClk, + maxPendingReadRequests, maxPendingWriteRequests, this, false); + else if (ext == "rstl") + player = new StlPlayer(moduleName.c_str(), stlFile, playerClk, + maxPendingReadRequests, maxPendingWriteRequests, this, true); + else + throw std::runtime_error("Unsupported file extension in " + name); + + players.push_back(player); + + totalTransactions += player->getNumberOfLines(); + } + else if (type == "generator") + { + if (!value["numRequests"].is_number_unsigned()) + SC_REPORT_FATAL("TraceSetup", "Number of requests is not a number."); + + uint64_t numRequests = value["numRequests"]; + + if (!value["rwRatio"].is_number_float()) + SC_REPORT_FATAL("TraceSetup", "Read/Write ratio is not a floating point number."); + + float rwRatio = value["rwRatio"]; + + if (!value["addressDistribution"].is_string()) + SC_REPORT_FATAL("TraceSetup", "Address distribution not defined."); + + std::string addressDistribution = value["addressDistribution"]; + if (addressDistribution != "sequential" && addressDistribution != "random") + SC_REPORT_FATAL("TraceSetup", "Address distribution must either be sequential or random."); + + unsigned int seed = 0; + if (value["seed"].is_number_unsigned()) + seed = value["seed"]; + + TrafficGenerator *generator; + + if (addressDistribution == "sequential") + { + uint64_t addressIncrement = 0x0; + if (!value["addressIncrement"].is_number_unsigned()) + SC_REPORT_FATAL("TraceSetup", "Address increment is not a number."); + + addressIncrement = value["addressIncrement"]; + + generator = new TrafficGeneratorSequential(name.c_str(), playerClk, numRequests, + maxPendingReadRequests, maxPendingWriteRequests, + rwRatio, addressIncrement, seed, this); + } + else + { + generator = new TrafficGeneratorRandom(name.c_str(), playerClk, numRequests, + maxPendingReadRequests, maxPendingWriteRequests, + rwRatio, seed, this); + } + + players.push_back(generator); + + totalTransactions += numRequests; + } } } remainingTransactions = totalTransactions; - numberOfTracePlayers = players->size(); + numberOfTrafficInitiators = players.size(); } -void TraceSetup::tracePlayerTerminates() +void TraceSetup::trafficInitiatorTerminates() { - finishedTracePlayers++; + finishedTrafficInitiators++; - if (finishedTracePlayers == numberOfTracePlayers) + if (finishedTrafficInitiators == numberOfTrafficInitiators) sc_stop(); } @@ -113,7 +192,7 @@ void TraceSetup::transactionFinished() { remainingTransactions--; - loadbar(totalTransactions - remainingTransactions, totalTransactions); + loadBar(totalTransactions - remainingTransactions, totalTransactions); if (remainingTransactions == 0) std::cout << std::endl; @@ -124,7 +203,7 @@ tlm_generic_payload *TraceSetup::allocatePayload() return memoryManager.allocate(); } -void TraceSetup::loadbar(uint64_t x, uint64_t n, unsigned int w, unsigned int granularity) +void TraceSetup::loadBar(uint64_t x, uint64_t n, unsigned int w, unsigned int granularity) { if ((n < 100) || ((x != n) && (x % (n / 100 * granularity) != 0))) return; diff --git a/DRAMSys/simulator/TraceSetup.h b/DRAMSys/simulator/TraceSetup.h index 5194c29a..b2aab202 100644 --- a/DRAMSys/simulator/TraceSetup.h +++ b/DRAMSys/simulator/TraceSetup.h @@ -31,6 +31,7 @@ * * Authors: * Matthias Jung + * Derek Christ */ #ifndef TRACESETUP_H @@ -41,27 +42,27 @@ #include #include "MemoryManager.h" -class TracePlayer; +class TrafficInitiator; class TraceSetup { public: - TraceSetup(std::string uri, - std::string pathToResources, - std::vector *devices); + TraceSetup(const std::string &uri, + const std::string &pathToResources, + std::vector &devices); - void tracePlayerTerminates(); + void trafficInitiatorTerminates(); void transactionFinished(); tlm::tlm_generic_payload *allocatePayload(); private: - unsigned int numberOfTracePlayers; + unsigned int numberOfTrafficInitiators; uint64_t totalTransactions = 0; uint64_t remainingTransactions; - unsigned int finishedTracePlayers = 0; + unsigned int finishedTrafficInitiators = 0; MemoryManager memoryManager; - void loadbar(uint64_t x, uint64_t n, unsigned int w = 50, unsigned int granularity = 1); + static void loadBar(uint64_t x, uint64_t n, unsigned int w = 50, unsigned int granularity = 1); }; #endif // TRACESETUP_H diff --git a/DRAMSys/simulator/TrafficGenerator.cpp b/DRAMSys/simulator/TrafficGenerator.cpp new file mode 100644 index 00000000..0011b064 --- /dev/null +++ b/DRAMSys/simulator/TrafficGenerator.cpp @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2015, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Janik Schlemminger + * Robert Gernhardt + * Matthias Jung + * Derek Christ + */ + +#include "TrafficGenerator.h" + +TrafficGenerator::TrafficGenerator(const sc_module_name &name, + const sc_time &generatorClk, + uint64_t numRequests, + unsigned int maxPendingReadRequests, + unsigned int maxPendingWriteRequests, + float rwRatio, + unsigned int seed, + TraceSetup *setup) : + TrafficInitiator(name, setup, maxPendingReadRequests, maxPendingWriteRequests), + generatorClk(generatorClk), numRequests(numRequests), rwRatio(rwRatio) +{ + burstLength = Configuration::getInstance().memSpec->burstLength; + dataLength = Configuration::getInstance().memSpec->bytesPerBurst; + + randomGenerator = std::default_random_engine(seed); +} + +void TrafficGenerator::sendNextPayload() +{ + if (transactionsSent >= numRequests) + { + finished = true; + return; + } + + tlm::tlm_generic_payload *payload = setup->allocatePayload(); + payload->acquire(); + + // TODO: column / burst breite + + uint64_t address = getNextAddress(); + + tlm::tlm_command command; + if (randomRwDistribution(randomGenerator) < rwRatio) + { + command = tlm::TLM_READ_COMMAND; + pendingReadRequests++; + } + else + { + command = tlm::TLM_WRITE_COMMAND; + pendingWriteRequests++; + } + + payload->set_address(address); + 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_command(command); + + sc_time sendingOffset; + if (transactionsSent == 0) + sendingOffset = SC_ZERO_TIME; + else + sendingOffset = generatorClk - (sc_time_stamp() % generatorClk); + + // TODO: do not send two requests in the same cycle + sendToTarget(*payload, tlm::BEGIN_REQ, sendingOffset); + + transactionsSent++; + PRINTDEBUGMESSAGE(name(), "Performing request #" + std::to_string(transactionsSent)); +} + +TrafficGeneratorRandom::TrafficGeneratorRandom(const sc_core::sc_module_name &name, + const sc_core::sc_time &generatorClk, + uint64_t numRequests, + unsigned int maxPendingReadRequests, + unsigned int maxPendingWriteRequests, + float rwRatio, + unsigned int seed, + TraceSetup *setup) : + TrafficGenerator(name, generatorClk, numRequests, maxPendingReadRequests, + maxPendingWriteRequests, rwRatio, seed, setup) +{ + randomAddressDistribution = std::uniform_int_distribution + (0, Configuration::getInstance().memSpec->getSimMemSizeInBytes()); +} + +uint64_t TrafficGeneratorRandom::getNextAddress() +{ + return randomAddressDistribution(randomGenerator); +} + +TrafficGeneratorSequential::TrafficGeneratorSequential(const sc_core::sc_module_name &name, + const sc_core::sc_time &generatorClk, + uint64_t numRequests, + unsigned int maxPendingReadRequests, + unsigned int maxPendingWriteRequests, + float rwRatio, + uint64_t addressIncrement, + unsigned int seed, + TraceSetup *setup) : + TrafficGenerator(name, generatorClk, numRequests, maxPendingReadRequests, + maxPendingWriteRequests, rwRatio, seed, setup), + addressIncrement(addressIncrement) +{ +} + +uint64_t TrafficGeneratorSequential::getNextAddress() +{ + uint64_t address = currentAddress; + currentAddress += addressIncrement; + return address; +} diff --git a/DRAMSys/simulator/TrafficGenerator.h b/DRAMSys/simulator/TrafficGenerator.h new file mode 100644 index 00000000..16f574a4 --- /dev/null +++ b/DRAMSys/simulator/TrafficGenerator.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2015, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Janik Schlemminger + * Robert Gernhardt + * Matthias Jung + * Derek Christ + */ + +#ifndef TRAFFICGENERATOR_H +#define TRAFFICGENERATOR_H + +#include "TrafficInitiator.h" +#include "TraceSetup.h" + +#include + +class TrafficGenerator : public TrafficInitiator +{ +protected: + TrafficGenerator(const sc_module_name &name, + const sc_time &generatorClk, + uint64_t numRequests, + unsigned int maxPendingReadRequests, + unsigned int maxPendingWriteRequests, + float rwRatio, + unsigned int seed, + TraceSetup *setup); + + void sendNextPayload() override; + virtual uint64_t getNextAddress() = 0; + + std::default_random_engine randomGenerator; + +private: + sc_time generatorClk; + uint64_t numRequests; + float rwRatio; + + std::uniform_real_distribution randomRwDistribution + = std::uniform_real_distribution(0.0f, 1.0f); +}; + +class TrafficGeneratorRandom final : public TrafficGenerator +{ +public: + TrafficGeneratorRandom(const sc_module_name &name, + const sc_time &generatorClk, + uint64_t numRequests, + unsigned int maxPendingReadRequests, + unsigned int maxPendingWriteRequests, + float rwRatio, + unsigned int seed, + TraceSetup *setup); + +private: + uint64_t getNextAddress() override; + + std::uniform_int_distribution randomAddressDistribution; +}; + +class TrafficGeneratorSequential final : public TrafficGenerator +{ +public: + TrafficGeneratorSequential(const sc_module_name &name, + const sc_time &generatorClk, + uint64_t numRequests, + unsigned int maxPendingReadRequests, + unsigned int maxPendingWriteRequests, + float rwRatio, + uint64_t addressIncrement, + unsigned int seed, + TraceSetup *setup); + +private: + uint64_t getNextAddress() override; + + uint64_t currentAddress = 0x0; + uint64_t addressIncrement; +}; + +#endif // TRAFFICGENERATOR_H diff --git a/DRAMSys/simulator/TracePlayer.cpp b/DRAMSys/simulator/TrafficInitiator.cpp similarity index 58% rename from DRAMSys/simulator/TracePlayer.cpp rename to DRAMSys/simulator/TrafficInitiator.cpp index dd45e3e6..ed54a77c 100644 --- a/DRAMSys/simulator/TracePlayer.cpp +++ b/DRAMSys/simulator/TrafficInitiator.cpp @@ -34,20 +34,22 @@ * Matthias Jung * Éder F. Zulian * Felipe S. Prado + * Derek Christ */ -#include "TracePlayer.h" +#include "TrafficInitiator.h" #include "TraceSetup.h" using namespace tlm; -TracePlayer::TracePlayer(sc_module_name name, TraceSetup *setup) : - sc_module(name), - payloadEventQueue(this, &TracePlayer::peqCallback), - setup(setup) +TrafficInitiator::TrafficInitiator(const sc_module_name &name, TraceSetup *setup, + unsigned int maxPendingReadRequests, unsigned int maxPendingWriteRequests) : + sc_module(name), payloadEventQueue(this, &TrafficInitiator::peqCallback), + setup(setup), + maxPendingReadRequests(maxPendingReadRequests), maxPendingWriteRequests(maxPendingWriteRequests) { - SC_METHOD(nextPayload); - iSocket.register_nb_transport_bw(this, &TracePlayer::nb_transport_bw); + SC_METHOD(sendNextPayload); + iSocket.register_nb_transport_bw(this, &TrafficInitiator::nb_transport_bw); if (Configuration::getInstance().storeMode == Configuration::StoreMode::NoStorage) storageEnabled = false; @@ -55,24 +57,29 @@ TracePlayer::TracePlayer(sc_module_name name, TraceSetup *setup) : storageEnabled = true; } -void TracePlayer::terminate() +void TrafficInitiator::terminate() { std::cout << sc_time_stamp() << " " << this->name() << " terminated " << std::endl; - setup->tracePlayerTerminates(); + setup->trafficInitiatorTerminates(); } -tlm_sync_enum TracePlayer::nb_transport_bw(tlm_generic_payload &payload, +tlm_sync_enum TrafficInitiator::nb_transport_bw(tlm_generic_payload &payload, tlm_phase &phase, sc_time &bwDelay) { payloadEventQueue.notify(payload, phase, bwDelay); return TLM_ACCEPTED; } -void TracePlayer::peqCallback(tlm_generic_payload &payload, +void TrafficInitiator::peqCallback(tlm_generic_payload &payload, const tlm_phase &phase) { if (phase == END_REQ) - nextPayload(); + { + if (nextPayloadSendable()) + sendNextPayload(); + else + payloadPostponed = true; + } else if (phase == BEGIN_RESP) { payload.release(); @@ -82,46 +89,42 @@ void TracePlayer::peqCallback(tlm_generic_payload &payload, transactionsReceived++; + if (payload.get_command() == tlm::TLM_READ_COMMAND) + pendingReadRequests--; + else if (payload.get_command() == tlm::TLM_WRITE_COMMAND) + pendingWriteRequests--; + + // If the initiator wasn't able to send the next payload in the END_REQ phase, do it now. + if (payloadPostponed && nextPayloadSendable()) + { + sendNextPayload(); + payloadPostponed = false; + } + // If all answers were received: - if (finished == true && numberOfTransactions == transactionsReceived) + if (finished && transactionsSent == transactionsReceived) terminate(); } else { - SC_REPORT_FATAL("TracePlayer", "PEQ was triggered with unknown phase"); + SC_REPORT_FATAL("TrafficInitiator", "PEQ was triggered with unknown phase"); } } -void TracePlayer::sendToTarget(tlm_generic_payload &payload, const tlm_phase &phase, const sc_time &delay) +void TrafficInitiator::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); } -uint64_t TracePlayer::getNumberOfLines(std::string pathToTrace) +bool TrafficInitiator::nextPayloadSendable() const { - std::ifstream file; - file.open(pathToTrace); - - if (file.is_open()) - { - uint64_t lineCount = 0; - std::string line; - while (std::getline(file, line)) - { - if (line.size() > 1 && line[0] != '#') - lineCount++; - } - file.close(); - - if (lineCount == 0) - SC_REPORT_FATAL("TracePlayer", "Trace file is empty"); - return lineCount; - } + // If either the maxPendingReadRequests or maxPendingWriteRequests + // limit is reached, do not send next payload. + if (((pendingReadRequests >= maxPendingReadRequests) && (maxPendingReadRequests != 0)) + || ((pendingWriteRequests >= maxPendingWriteRequests) && (maxPendingWriteRequests != 0))) + return false; else - { - SC_REPORT_FATAL("TracePlayer", "Unable to open trace file"); - return 0; - } + return true; } diff --git a/DRAMSys/simulator/TracePlayer.h b/DRAMSys/simulator/TrafficInitiator.h similarity index 74% rename from DRAMSys/simulator/TracePlayer.h rename to DRAMSys/simulator/TrafficInitiator.h index 7fc4df35..1c10e04f 100644 --- a/DRAMSys/simulator/TracePlayer.h +++ b/DRAMSys/simulator/TrafficInitiator.h @@ -34,10 +34,11 @@ * Matthias Jung * Éder F. Zulian * Felipe S. Prado + * Derek Christ */ -#ifndef TRACEPLAYER_H -#define TRACEPLAYER_H +#ifndef TRAFFICINITIATOR_H +#define TRAFFICINITIATOR_H #include #include @@ -50,31 +51,40 @@ #include "common/DebugManager.h" #include "TraceSetup.h" -class TracePlayer : public sc_module +class TrafficInitiator : public sc_module { public: - tlm_utils::simple_initiator_socket iSocket; - TracePlayer(sc_module_name name, TraceSetup *setup); - SC_HAS_PROCESS(TracePlayer); - virtual void nextPayload() = 0; - uint64_t getNumberOfLines(std::string pathToTrace); + tlm_utils::simple_initiator_socket iSocket; + TrafficInitiator(const sc_module_name &name, TraceSetup *setup, + unsigned int maxPendingReadRequests, unsigned int maxPendingWriteRequests); + SC_HAS_PROCESS(TrafficInitiator); + virtual void sendNextPayload() = 0; protected: - tlm_utils::peq_with_cb_and_phase payloadEventQueue; + tlm_utils::peq_with_cb_and_phase payloadEventQueue; void terminate(); bool storageEnabled = false; TraceSetup *setup; void sendToTarget(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase, const sc_time &delay); - uint64_t numberOfTransactions = 0; + + uint64_t transactionsReceived = 0; uint64_t transactionsSent = 0; + unsigned int pendingReadRequests = 0; + unsigned int pendingWriteRequests = 0; + unsigned int maxPendingReadRequests = 0; + unsigned int maxPendingWriteRequests = 0; + bool payloadPostponed = false; bool finished = false; + unsigned int burstLength; + unsigned int dataLength; + private: tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &payload, tlm::tlm_phase &phase, - sc_time &bwDelay); + sc_time &bwDelay); void peqCallback(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase); - uint64_t transactionsReceived = 0; + bool nextPayloadSendable() const; }; -#endif // TRACEPLAYER_H +#endif // TRAFFICINITIATOR_H diff --git a/DRAMSys/simulator/main.cpp b/DRAMSys/simulator/main.cpp index c742527a..3050f15c 100644 --- a/DRAMSys/simulator/main.cpp +++ b/DRAMSys/simulator/main.cpp @@ -45,7 +45,7 @@ #include "simulation/DRAMSys.h" #include "TraceSetup.h" -#include "TracePlayer.h" +#include "TrafficInitiator.h" #ifdef RECORDING #include "simulation/DRAMSysRecordable.h" @@ -93,7 +93,7 @@ int sc_main(int argc, char **argv) resources = argv[2]; } - std::vector players; + std::vector players; // Instantiate DRAMSys: DRAMSys *dramSys; @@ -109,7 +109,7 @@ int sc_main(int argc, char **argv) dramSys = new DRAMSys("DRAMSys", simulationJson, resources); // Instantiate STL Players: - TraceSetup *setup = new TraceSetup(simulationJson, resources, &players); + TraceSetup *setup = new TraceSetup(simulationJson, resources, players); // Bind STL Players with DRAMSys: for (size_t i = 0; i < players.size(); i++)