diff --git a/DRAMSys/simulator/LengthConverter.cpp b/DRAMSys/simulator/LengthConverter.cpp index 70b156bf..b4d8a571 100644 --- a/DRAMSys/simulator/LengthConverter.cpp +++ b/DRAMSys/simulator/LengthConverter.cpp @@ -192,7 +192,7 @@ void LengthConverter::createChildTranses(tlm_generic_payload* parentTrans) ParentExtension::setExtension(parentTrans, std::move(childTranses)); } -LengthConverter::MemoryManager::MemoryManager(bool storageEnabled, size_t maxDataLength) +LengthConverter::MemoryManager::MemoryManager(bool storageEnabled, unsigned maxDataLength) : storageEnabled(storageEnabled), maxDataLength(maxDataLength) {} diff --git a/DRAMSys/simulator/LengthConverter.h b/DRAMSys/simulator/LengthConverter.h index 3d69d31b..bac9c29d 100644 --- a/DRAMSys/simulator/LengthConverter.h +++ b/DRAMSys/simulator/LengthConverter.h @@ -88,7 +88,7 @@ private: class MemoryManager : public tlm::tlm_mm_interface { public: - MemoryManager(bool storageEnabled, std::size_t maxDataLength); + MemoryManager(bool storageEnabled, unsigned maxDataLength); ~MemoryManager() override; tlm::tlm_generic_payload* allocate(); void free(tlm::tlm_generic_payload* payload) override; @@ -96,7 +96,7 @@ private: private: std::stack freePayloads; bool storageEnabled = false; - std::size_t maxDataLength; + unsigned maxDataLength; } memoryManager; class ChildExtension : public tlm::tlm_extension diff --git a/DRAMSys/simulator/MemoryManager.cpp b/DRAMSys/simulator/MemoryManager.cpp index eb941d01..d9f029ee 100644 --- a/DRAMSys/simulator/MemoryManager.cpp +++ b/DRAMSys/simulator/MemoryManager.cpp @@ -51,17 +51,18 @@ MemoryManager::MemoryManager() MemoryManager::~MemoryManager() { - for (tlm_generic_payload *payload : freePayloads) + for (auto& innerBuffer : freePayloads) { - if (storageEnabled) + while (!innerBuffer.second.empty()) { - // Delete data buffer - delete[] payload->get_data_ptr(); + tlm_generic_payload* payload = innerBuffer.second.top(); + if (storageEnabled) + delete[] payload->get_data_ptr(); + payload->reset(); + delete payload; + innerBuffer.second.pop(); + numberOfFrees++; } - // Delete all extensions - payload->reset(); - delete payload; - numberOfFrees++; } // Comment in if you are suspecting a memory leak in the manager @@ -69,18 +70,17 @@ MemoryManager::~MemoryManager() //PRINTDEBUGMESSAGE("MemoryManager","Number of freed payloads: " + to_string(numberOfFrees)); } -tlm_generic_payload *MemoryManager::allocate() +tlm_generic_payload *MemoryManager::allocate(unsigned dataLength) { - if (freePayloads.empty()) + if (freePayloads[dataLength].empty()) { numberOfAllocations++; - tlm_generic_payload *payload = new tlm_generic_payload(this); + auto* payload = new tlm_generic_payload(this); if (storageEnabled) { // Allocate a data buffer and initialize it with zeroes: - unsigned int dataLength = Configuration::getInstance().memSpec->maxBytesPerBurst; - unsigned char *data = new unsigned char[dataLength]; + auto* data = new unsigned char[dataLength]; std::fill(data, data + dataLength, 0); payload->set_data_ptr(data); } @@ -89,13 +89,14 @@ tlm_generic_payload *MemoryManager::allocate() } else { - tlm_generic_payload *result = freePayloads.back(); - freePayloads.pop_back(); + tlm_generic_payload *result = freePayloads[dataLength].top(); + freePayloads[dataLength].pop(); return result; } } void MemoryManager::free(tlm_generic_payload *payload) { - freePayloads.push_back(payload); + unsigned dataLength = payload->get_data_length(); + freePayloads[dataLength].push(payload); } diff --git a/DRAMSys/simulator/MemoryManager.h b/DRAMSys/simulator/MemoryManager.h index 6a26bee8..6a5dd1ad 100644 --- a/DRAMSys/simulator/MemoryManager.h +++ b/DRAMSys/simulator/MemoryManager.h @@ -37,7 +37,8 @@ #ifndef MEMORYMANAGER_H #define MEMORYMANAGER_H -#include +#include +#include #include @@ -46,13 +47,13 @@ class MemoryManager : public tlm::tlm_mm_interface public: MemoryManager(); ~MemoryManager() override; - tlm::tlm_generic_payload *allocate(); + tlm::tlm_generic_payload *allocate(unsigned dataLength); void free(tlm::tlm_generic_payload *payload) override; private: uint64_t numberOfAllocations; uint64_t numberOfFrees; - std::vector freePayloads; + std::unordered_map> freePayloads; bool storageEnabled = false; }; diff --git a/DRAMSys/simulator/StlPlayer.cpp b/DRAMSys/simulator/StlPlayer.cpp index 8aa727bf..de4a1ec7 100644 --- a/DRAMSys/simulator/StlPlayer.cpp +++ b/DRAMSys/simulator/StlPlayer.cpp @@ -101,7 +101,7 @@ void StlPlayer::sendNextPayload() } // Allocate a generic payload for this request. - tlm_generic_payload *payload = setup->allocatePayload(); + tlm_generic_payload *payload = setup->allocatePayload(lineIterator->dataLength); payload->acquire(); // Fill up the payload. @@ -169,20 +169,20 @@ void StlPlayer::parseTraceFile() // Get the timestamp for the transaction. iss >> element; if (element.empty()) - SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ").").c_str()); + SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ".").c_str()); content.sendingTime = playerClk * static_cast(std::stoull(element)); // Get the optional burst length and command iss >> element; if (element.empty()) - SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ").").c_str()); + SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ".").c_str()); if (element.at(0) == '(') { element.erase(0, 1); content.dataLength = std::stoul(element); iss >> element; if (element.empty()) - SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ").").c_str()); + SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ".").c_str()); } else content.dataLength = defaultDataLength; @@ -192,12 +192,12 @@ void StlPlayer::parseTraceFile() else if (element == "write") content.command = TLM_WRITE_COMMAND; else - SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ").").c_str()); + SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ".").c_str()); // Get the address. iss >> element; if (element.empty()) - SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ").").c_str()); + SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ".").c_str()); content.address = std::stoull(element, nullptr, 16); // Get the data if necessary. @@ -209,7 +209,7 @@ void StlPlayer::parseTraceFile() // 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 (element.length() != (content.dataLength * 2 + 2)) - SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ").").c_str()); + SC_REPORT_FATAL("StlPlayer", ("Malformed trace file line " + std::to_string(lineCnt) + ".").c_str()); // Set data for (unsigned i = 0; i < content.dataLength; i++) diff --git a/DRAMSys/simulator/TraceSetup.cpp b/DRAMSys/simulator/TraceSetup.cpp index 76a78ffe..ab55f0cf 100644 --- a/DRAMSys/simulator/TraceSetup.cpp +++ b/DRAMSys/simulator/TraceSetup.cpp @@ -226,6 +226,7 @@ TraceSetup::TraceSetup(const std::string &uri, remainingTransactions = totalTransactions; numberOfTrafficInitiators = players.size(); + defaultDataLength = Configuration::getInstance().memSpec->defaultBytesPerBurst; } void TraceSetup::trafficInitiatorTerminates() @@ -246,9 +247,14 @@ void TraceSetup::transactionFinished() std::cout << std::endl; } +tlm_generic_payload *TraceSetup::allocatePayload(unsigned dataLength) +{ + return memoryManager.allocate(dataLength); +} + tlm_generic_payload *TraceSetup::allocatePayload() { - return memoryManager.allocate(); + return allocatePayload(defaultDataLength); } void TraceSetup::loadBar(uint64_t x, uint64_t n, unsigned int w, unsigned int granularity) diff --git a/DRAMSys/simulator/TraceSetup.h b/DRAMSys/simulator/TraceSetup.h index 6fd98fff..064bfd13 100644 --- a/DRAMSys/simulator/TraceSetup.h +++ b/DRAMSys/simulator/TraceSetup.h @@ -55,6 +55,7 @@ public: void trafficInitiatorTerminates(); void transactionFinished(); + tlm::tlm_generic_payload *allocatePayload(unsigned dataLength); tlm::tlm_generic_payload *allocatePayload(); private: @@ -63,6 +64,7 @@ private: uint64_t remainingTransactions; unsigned int finishedTrafficInitiators = 0; MemoryManager memoryManager; + unsigned defaultDataLength = 64; static void loadBar(uint64_t x, uint64_t n, unsigned int w = 50, unsigned int granularity = 1); }; diff --git a/README.md b/README.md index 4deed4ee..d5d1491c 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,8 @@ The JSON code below shows an example configuration: "tracesetup": [ { "clkMhz": 300, - "name": "ddr3_example.stl" + "name": "ddr3_example.stl", + "addLengthConverter": true }, { "clkMhz": 2000, @@ -160,6 +161,7 @@ Fields Description: Each **trace setup** device configuration can be a **trace player** ("type": "player"), a **traffic generator** ("type": "generator") or a **row hammer generator** ("type": "hammer"). By not specifing the **type** parameter, the device will act as a **trace player**. All device configurations must define a **clkMhz** (operation frequency of the **traffic initiator**) and a **name** (in case of a trace player this specifies the **trace file** to play; in case of a generator this field is only for identification purposes). +The optional parameter **addLengthConverter** adds a transaction length converter between initiator and DRAMSys. This unit divides a large transaction up into several smaller transactions with the maximum length of one DRAM burst access. The **maxPendingReadRequests** and **maxPendingWriteRequests** parameters define the maximum number of outstanding read/write requests. The current implementation delays all memory accesses when one limit is reached. The default value (0) disables the limit. A **traffic generator** can be configured to generate **numRequests** requests in total, of which the **rwRatio** field defines the probability of one request being a read request. The **seed** parameter can be used to produce identical results for all simulations. **minAddress** and **maxAddress** specify the address range, by default the whole address range is used. The parameter **addressDistribution** can either be set to **"random"** or **"sequential"**. In case of **"sequential"** the additional **addressIncrement** field must be specified, defining the address increment after each request. @@ -171,7 +173,7 @@ Most configuration fields reference other JSON files which contain more speciali #### Trace Files -A **trace file** is a prerecorded file containing memory transactions. Each memory transaction has a time stamp that tells the simulator when it shall happen, a transaction type (*read* or *write*) and a hexadecimal memory address. +A **trace file** is a prerecorded file containing memory transactions. Each memory transaction has a time stamp that tells the simulator when it shall happen, a transaction type (*read* or *write*) and a hexadecimal memory address. The optional length parameter (in bytes) allows sending transactions with a custom length that does not match the length of a single DRAM burst access. In this case a length converter has to be added. Write transactions also have to specify a data field when storage is enabled in DRAMSys. There are two different kinds of trace files. They differ in their timing behavior and are distinguished by their file extension. @@ -183,11 +185,11 @@ Syntax example: ``` # Comment lines begin with # -# [clock-cyle]: [write|read] [hex-address] [hex-data (optional)] -31: read 0x400140 -33: read 0x400160 -56: write 0x7fff8000 0x123456789abcdef... -81: read 0x400180 +# cycle: [(length)] command hex-address [hex-data] +31: read 0x400140 +33: read 0x400160 +56: write 0x7fff8000 0x123456789abcdef... +81: (128) read 0x400180 ``` ##### Relative STL Traces (.rstl) @@ -198,11 +200,11 @@ Syntax example: ``` # Comment lines begin with # -# [clock-cyle]: [write|read] [hex-address] [hex-data (optional)] -31: read 0x400140 -2: read 0x400160 -23: write 0x7fff8000 0x123456789abcdef... -25: read 0x400180 +# cycle: [(length)] command hex-address [hex-data] +31: read 0x400140 +2: (512) read 0x400160 +23: write 0x7fff8000 0x123456789abcdef... +10: read 0x400180 ``` ##### Elastic Traces