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/StlPlayer.cpp b/DRAMSys/simulator/StlPlayer.cpp index 4880b5b0..5303be41 100644 --- a/DRAMSys/simulator/StlPlayer.cpp +++ b/DRAMSys/simulator/StlPlayer.cpp @@ -41,9 +41,11 @@ using namespace tlm; -StlPlayer::StlPlayer(sc_module_name name, - std::string pathToTrace, +StlPlayer::StlPlayer(const sc_module_name &name, + const std::string &pathToTrace, sc_time playerClk, + unsigned int maxPendingReadRequests, + unsigned int maxPendingWriteRequests, TraceSetup *setup, bool relative) : TracePlayer(name, setup), file(pathToTrace), @@ -54,6 +56,9 @@ StlPlayer::StlPlayer(sc_module_name name, if (!file.is_open()) SC_REPORT_FATAL("StlPlayer", (std::string("Could not open trace ") + pathToTrace).c_str()); + this->maxPendingReadRequests = maxPendingReadRequests; + this->maxPendingWriteRequests = maxPendingWriteRequests; + this->playerClk = playerClk; burstlength = Configuration::getInstance().memSpec->burstLength; dataLength = Configuration::getInstance().memSpec->bytesPerBurst; @@ -117,6 +122,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++; } diff --git a/DRAMSys/simulator/StlPlayer.h b/DRAMSys/simulator/StlPlayer.h index 27081d41..45a1769b 100644 --- a/DRAMSys/simulator/StlPlayer.h +++ b/DRAMSys/simulator/StlPlayer.h @@ -58,9 +58,11 @@ struct LineContent class StlPlayer : public TracePlayer { public: - StlPlayer(sc_module_name name, - std::string pathToTrace, + StlPlayer(const sc_module_name &name, + const std::string &pathToTrace, sc_time playerClk, + unsigned int maxPendingReadRequests, + unsigned int maxPendingWriteRequests, TraceSetup *setup, bool relative); diff --git a/DRAMSys/simulator/TraceGenerator.cpp b/DRAMSys/simulator/TraceGenerator.cpp index b08080ee..8620d0e5 100644 --- a/DRAMSys/simulator/TraceGenerator.cpp +++ b/DRAMSys/simulator/TraceGenerator.cpp @@ -37,40 +37,84 @@ #include "TraceGenerator.h" -TraceGenerator::TraceGenerator(sc_module_name name, - unsigned int fCKMhz, TraceSetup *setup) - : TracePlayer(name, setup), transCounter(0) +TraceGenerator::TraceGenerator(const sc_module_name &name, + const sc_time &tCK, + uint64_t numRequests, + unsigned int maxPendingReadRequests, + unsigned int maxPendingWriteRequests, + float rwRatio, + AddressDistribution addressDistribution, + unsigned int addressIncrement, + unsigned int seed, + TraceSetup *setup) : + TracePlayer(name, setup), tCK(tCK), numRequests(numRequests), + rwRatio(rwRatio), addressDistribution(addressDistribution), + addressIncrement(addressIncrement) { - if (fCKMhz == 0) - tCK = Configuration::getInstance().memSpec->tCK; - else - tCK = sc_time(1.0 / fCKMhz, SC_US); - burstlenght = Configuration::getInstance().memSpec->burstLength; + + this->maxPendingReadRequests = maxPendingReadRequests; + this->maxPendingWriteRequests = maxPendingWriteRequests; + + randomGenerator = std::default_random_engine(seed); + randomAddressDistribution = std::uniform_int_distribution( + 0, Configuration::getInstance().memSpec->getSimMemSizeInBytes()); + } void TraceGenerator::nextPayload() { - if (transCounter >= 1000) // TODO set limit! - terminate(); + if (transCounter >= numRequests) { + finished = true; + return; + } tlm::tlm_generic_payload *payload = setup->allocatePayload(); payload->acquire(); unsigned char *dataElement = new unsigned char[16]; // TODO: column / burst breite - payload->set_address(0x0); + uint64_t address; + if (addressDistribution == AddressDistribution::Sequential) { + address = currentAddress; + currentAddress += addressIncrement; + } else { + // AddressDistribution::Random + address = randomAddressDistribution(randomGenerator); + } + + tlm::tlm_command command; + if (randomRwDistribution(randomGenerator) < rwRatio) { + command = tlm::TLM_READ_COMMAND; + } else { + command = tlm::TLM_WRITE_COMMAND; + } + + 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(burstlenght); payload->set_data_ptr(dataElement); payload->set_data_length(16); - payload->set_command(tlm::TLM_READ_COMMAND); + payload->set_command(command); transCounter++; + sc_time sendingOffset; + if (lastEndReq == sc_time_stamp()) + sendingOffset = tCK; + else + sendingOffset = SC_ZERO_TIME; + // TODO: do not send two requests in the same cycle - sendToTarget(*payload, tlm::BEGIN_REQ, SC_ZERO_TIME); + sendToTarget(*payload, tlm::BEGIN_REQ, sendingOffset); + transactionsSent++; + + if (command == tlm::TLM_READ_COMMAND) + pendingReadRequests++; + else if (command == tlm::TLM_WRITE_COMMAND) + pendingWriteRequests++; + PRINTDEBUGMESSAGE(name(), "Performing request #" + std::to_string(transactionsSent)); } diff --git a/DRAMSys/simulator/TraceGenerator.h b/DRAMSys/simulator/TraceGenerator.h index 8993e8d3..58cc9006 100644 --- a/DRAMSys/simulator/TraceGenerator.h +++ b/DRAMSys/simulator/TraceGenerator.h @@ -41,16 +41,39 @@ #include "TracePlayer.h" #include "TraceSetup.h" +#include + +enum class AddressDistribution {Sequential, Random}; + class TraceGenerator : public TracePlayer { public: - TraceGenerator(sc_module_name name, unsigned int fCKMhz, TraceSetup *setup); + TraceGenerator(const sc_module_name &name, + const sc_time &tCK, + uint64_t numRequests, + unsigned int maxPendingReadRequests, + unsigned int maxPendingWriteRequests, + float rwRatio, + AddressDistribution addressDistribution, + unsigned int addressIncrement, + unsigned int seed, + TraceSetup *setup); + virtual void nextPayload() override; private: unsigned int burstlenght; sc_time tCK; - unsigned int transCounter; + unsigned int numRequests; + float rwRatio; + AddressDistribution addressDistribution; + unsigned int addressIncrement; + unsigned int transCounter = 0; + unsigned int currentAddress = 0x0; + + std::default_random_engine randomGenerator; + std::uniform_int_distribution randomAddressDistribution; + std::uniform_real_distribution randomRwDistribution = std::uniform_real_distribution(0.0f, 1.0f); }; #endif // TRACEGENERATOR_H diff --git a/DRAMSys/simulator/TracePlayer.cpp b/DRAMSys/simulator/TracePlayer.cpp index 4c588668..393673b6 100644 --- a/DRAMSys/simulator/TracePlayer.cpp +++ b/DRAMSys/simulator/TracePlayer.cpp @@ -74,7 +74,11 @@ void TracePlayer::peqCallback(tlm_generic_payload &payload, if (phase == END_REQ) { lastEndReq = sc_time_stamp(); - nextPayload(); + + if (nextPayloadSendable()) + nextPayload(); + else + payloadPostponed = true; } else if (phase == BEGIN_RESP) { @@ -85,8 +89,19 @@ 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) { + nextPayload(); + payloadPostponed = false; + } + // If all answers were received: - if (finished == true && numberOfTransactions == transactionsReceived) + if (finished == true && transactionsSent == transactionsReceived) terminate(); } else @@ -128,3 +143,21 @@ uint64_t TracePlayer::getNumberOfLines(std::string pathToTrace) return 0; } } + +bool TracePlayer::nextPayloadSendable() +{ + bool sendable = true; + + // If either the maxPendingReadRequests or maxPendingWriteRequests + // limit is reached, do not send next payload. + if (pendingReadRequests >= maxPendingReadRequests && maxPendingReadRequests != 0) + { + sendable = false; + } + else if (pendingWriteRequests >= maxPendingWriteRequests && maxPendingWriteRequests != 0) + { + sendable = false; + } + + return sendable; +} diff --git a/DRAMSys/simulator/TracePlayer.h b/DRAMSys/simulator/TracePlayer.h index 7144c95a..c1e15dd5 100644 --- a/DRAMSys/simulator/TracePlayer.h +++ b/DRAMSys/simulator/TracePlayer.h @@ -66,16 +66,24 @@ protected: 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; sc_time lastEndReq = sc_max_time(); + sc_event transactionFinished; private: tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &payload, tlm::tlm_phase &phase, sc_time &bwDelay); void peqCallback(tlm::tlm_generic_payload &payload, const tlm::tlm_phase &phase); - uint64_t transactionsReceived = 0; + bool nextPayloadSendable(); }; #endif // TRACEPLAYER_H diff --git a/DRAMSys/simulator/TraceSetup.cpp b/DRAMSys/simulator/TraceSetup.cpp index 871be829..015bd163 100644 --- a/DRAMSys/simulator/TraceSetup.cpp +++ b/DRAMSys/simulator/TraceSetup.cpp @@ -36,12 +36,13 @@ #include "TraceSetup.h" #include "StlPlayer.h" +#include "TraceGenerator.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); @@ -53,52 +54,129 @@ TraceSetup::TraceSetup(std::string uri, // Load TracePlayers: 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::string stlFile = pathToResources + std::string("traces/") + name; + std::string moduleName = name; + + // replace all '.' to '_' + std::replace(moduleName.begin(), moduleName.end(), '.', '_'); + + TracePlayer *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); + + if (Configuration::getInstance().simulationProgressBar) + totalTransactions += player->getNumberOfLines(stlFile); + } + 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."); + + AddressDistribution addressDistribution = AddressDistribution::Sequential; + std::string addressDistributionString = value["addressDistribution"]; + if (addressDistributionString == "sequential") + addressDistribution = AddressDistribution::Sequential; + else if (addressDistributionString == "random") + addressDistribution = AddressDistribution::Random; + else + SC_REPORT_FATAL("TraceSetup", "Address distribution must either be sequential or random."); + + unsigned int addressIncrement = 0x0; + unsigned int seed = 0; + if (addressDistribution == AddressDistribution::Sequential) { + if (!value["addressIncrement"].is_number_unsigned()) + SC_REPORT_FATAL("TraceSetup", "Address increment is not a number."); + + addressIncrement = value["addressIncrement"]; + } else { + // addressDistribution == AddressDistribution::Random + if (!value["seed"].is_number_unsigned()) + SC_REPORT_FATAL("TraceSetup", "Seed is not a number."); + + seed = value["seed"]; + } + + TracePlayer *player = new TraceGenerator(name.c_str(), playerClk, numRequests, + maxPendingReadRequests, maxPendingWriteRequests, + rwRatio, addressDistribution, + addressIncrement, seed, this); + + players.push_back(player); + + if (Configuration::getInstance().simulationProgressBar) + totalTransactions += numRequests; + } } } remainingTransactions = totalTransactions; - numberOfTracePlayers = players->size(); + numberOfTracePlayers = players.size(); } void TraceSetup::tracePlayerTerminates() diff --git a/DRAMSys/simulator/TraceSetup.h b/DRAMSys/simulator/TraceSetup.h index 5194c29a..52df9157 100644 --- a/DRAMSys/simulator/TraceSetup.h +++ b/DRAMSys/simulator/TraceSetup.h @@ -46,9 +46,9 @@ class TracePlayer; 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 transactionFinished(); diff --git a/DRAMSys/simulator/main.cpp b/DRAMSys/simulator/main.cpp index c742527a..40f7fe83 100644 --- a/DRAMSys/simulator/main.cpp +++ b/DRAMSys/simulator/main.cpp @@ -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++)