From 6c5fb579d460e9e7d281e86222855f2ee08d1487 Mon Sep 17 00:00:00 2001 From: "Thanh C. Tran" Date: Wed, 19 Jul 2017 18:39:00 +0200 Subject: [PATCH] Change to use batch size to store each batch location due iterator invalidation of deque container when push and pop --- .../simulator/src/common/dramExtension.cpp | 10 ++ DRAMSys/simulator/src/common/dramExtension.h | 2 + .../src/controller/scheduler/SMS.cpp | 113 +++++++++++------- .../simulator/src/controller/scheduler/SMS.h | 14 +-- 4 files changed, 87 insertions(+), 52 deletions(-) diff --git a/DRAMSys/simulator/src/common/dramExtension.cpp b/DRAMSys/simulator/src/common/dramExtension.cpp index 3887f8df..a0a44015 100644 --- a/DRAMSys/simulator/src/common/dramExtension.cpp +++ b/DRAMSys/simulator/src/common/dramExtension.cpp @@ -169,6 +169,16 @@ GenerationExtension& GenerationExtension::getExtension(const tlm::tlm_generic_pa return *result; } +sc_time GenerationExtension::getTimeOfGeneration(const tlm::tlm_generic_payload *payload) +{ + return GenerationExtension::getExtension(payload).TimeOfGeneration(); +} + +sc_time GenerationExtension::getTimeOfGeneration(const tlm::tlm_generic_payload &payload) +{ + return GenerationExtension::getTimeOfGeneration(&payload); +} + //THREAD bool operator ==(const Thread& lhs, const Thread& rhs) { diff --git a/DRAMSys/simulator/src/common/dramExtension.h b/DRAMSys/simulator/src/common/dramExtension.h index 24865e80..ab30decf 100644 --- a/DRAMSys/simulator/src/common/dramExtension.h +++ b/DRAMSys/simulator/src/common/dramExtension.h @@ -212,6 +212,8 @@ public: virtual void copy_from(const tlm_extension_base& ext); static GenerationExtension& getExtension(const tlm::tlm_generic_payload *payload); sc_time TimeOfGeneration() const {return timeOfGeneration;} + static sc_time getTimeOfGeneration(const tlm::tlm_generic_payload *payload); + static sc_time getTimeOfGeneration(const tlm::tlm_generic_payload &payload); private: sc_time timeOfGeneration; diff --git a/DRAMSys/simulator/src/controller/scheduler/SMS.cpp b/DRAMSys/simulator/src/controller/scheduler/SMS.cpp index 8eedea6a..5d103522 100644 --- a/DRAMSys/simulator/src/controller/scheduler/SMS.cpp +++ b/DRAMSys/simulator/src/controller/scheduler/SMS.cpp @@ -62,13 +62,10 @@ void SMS::batchScheduler() if (existReadyBatches()) { if (!isSystemLightlyLoaded() && (existLowIntensityThread() || distribution(generator))) { pickSJF(); - drain(memClk); - (*lastSelectedThread).second.pop_front(); } else { pickRR(); - drain(memClk); - (*lastSelectedThread).second.pop_front(); } + drainOnePayloadFromReadybatch(memClk); } else { wait(memClk); } @@ -85,7 +82,7 @@ bool SMS::pickSJF() { // find threads with ready batches std::vector threadsWithReadyBatches; - for (const auto &each : readyBatchIters) + for (const auto &each : readyBatchInclusiveEndLocs) { if (!each.second.empty()) { @@ -107,7 +104,7 @@ bool SMS::pickSJF() } // save selected thread - lastSelectedThread = readyBatchIters.find(minThread); + lastSelectedThread = readyBatchInclusiveEndLocs.find(minThread); debugManager.printDebugMessage(name(), "[SJF] Select ready batch of thread " + to_string(minThread.ID())); return true; @@ -124,28 +121,36 @@ bool SMS::pickSJF() * @param memClk * @param last */ -void SMS::drain(const sc_time &memClk) +void SMS::drainOnePayloadFromReadybatch(const sc_time &memClk) { if (lastSelectedThread->second.empty()) { return; } const Thread &selectedThread = lastSelectedThread->first; - const std::deque::iterator &last = lastSelectedThread->second.front(); - assert(last != requestBuffers[selectedThread].end()); - unsigned int batchSize = std::distance(requestBuffers[selectedThread].begin(), last) + 1; - assert(batchSize > 0 && batchSize <= requestBuffers[selectedThread].size()); - for (unsigned int i = 1; i <= batchSize; i++) + + const size_t &inclusiveEndLoc = lastSelectedThread->second.front(); + assert(inclusiveEndLoc < requestBuffers.size()); + + for (size_t i = 0; i <= inclusiveEndLoc; ++i) { - Bank bank = DramExtension::getExtension(requestBuffers[selectedThread].front()).getBank(); wait(memClk); + Bank bank = DramExtension::getExtension(requestBuffers[selectedThread].front()).getBank(); bankBuffers[bank].emplace_back(requestBuffers[selectedThread].front()); requestBuffers[selectedThread].pop_front(); + // decrement inclusive end locations of ready batches + // except this ready batch + for (size_t i = 1; i < readyBatchInclusiveEndLocs.size(); ++i) + { + --readyBatchInclusiveEndLocs[selectedThread][i]; + } + debugManager.printDebugMessage(name(), "[SJF] Drain request in the ready batch of thread " + to_string((*lastSelectedThread).first.ID()) + " to bankbuffer " + to_string(bank.ID())); } + lastSelectedThread->second.pop_front(); } /** @@ -155,21 +160,21 @@ void SMS::drain(const sc_time &memClk) */ bool SMS::pickRR() { - if (lastSelectedThread == readyBatchIters.end()) + if (lastSelectedThread == readyBatchInclusiveEndLocs.end()) { - lastSelectedThread = readyBatchIters.begin(); + lastSelectedThread = readyBatchInclusiveEndLocs.begin(); if (!(*lastSelectedThread).second.empty()) { return true; } } - std::map>::iterator savedOriginalNextSelectedThread = lastSelectedThread; + std::map>::iterator savedOriginalNextSelectedThread = lastSelectedThread; do { lastSelectedThread++; - if (lastSelectedThread == readyBatchIters.end()) { - lastSelectedThread = readyBatchIters.begin(); + if (lastSelectedThread == readyBatchInclusiveEndLocs.end()) { + lastSelectedThread = readyBatchInclusiveEndLocs.begin(); } if (lastSelectedThread == savedOriginalNextSelectedThread) { return false; @@ -198,11 +203,12 @@ bool SMS::existLowIntensityThread() const { return false; } -bool SMS::isThresholdAgeExceeded(const Thread &thread, sc_time const &memClk, std::deque::iterator const &begin, std::deque::iterator const &end) { +bool SMS::isThresholdAgeExceeded(const Thread &thread, sc_time const &memClk, size_t const &inclusiveBeginLoc, size_t const &exclusiveEndLoc) { + assert((exclusiveEndLoc - inclusiveBeginLoc) >= 1); // find the oldest request in the thread's batch sc_time oldestGenerationTime = sc_time_stamp(); - for (auto reqIter = begin; reqIter != end; reqIter++) { - sc_time reqGenerationTime = GenerationExtension::getExtension(*reqIter).TimeOfGeneration(); + for (size_t i = inclusiveBeginLoc; i != exclusiveEndLoc; ++i) { + sc_time reqGenerationTime = GenerationExtension::getExtension(requestBuffers[thread][i]).TimeOfGeneration(); if (reqGenerationTime < oldestGenerationTime) { oldestGenerationTime = reqGenerationTime; } @@ -235,8 +241,8 @@ void SMS::updateMPKCs(sc_time const &memClk) { } } -bool SMS::isExceededReqBufferSize(Thread const &thread) { - return requestBuffers[thread].size() == Configuration::getInstance().RequestBufferSize; +bool SMS::isExceededReqBufferSize(size_t const &exclusiveEndLoc) { + return exclusiveEndLoc <= Configuration::getInstance().RequestBufferSize; } bool SMS::isRequestBuffersEmpty() const { @@ -249,7 +255,7 @@ bool SMS::isRequestBuffersEmpty() const { } bool SMS::existReadyBatches() const { - for (const auto &each : readyBatchIters) { + for (const auto &each : readyBatchInclusiveEndLocs) { if (!each.second.empty()) { return true; } @@ -264,14 +270,15 @@ bool SMS::existReadyBatches() const { * @param begin * @return true if this batch is ready, otherwise false */ -bool SMS::batchFormation(sc_time const &memClk, Thread const &thread, std::deque const &requestBuffer, std::deque::iterator const &beginIter) +bool SMS::batchFormation(sc_time const &memClk, Thread const &thread, std::deque const &requestBuffer, size_t const &inclusiveBeginLoc) { if (requestBuffer.empty()) { return false; } - if (requestBuffer.end() == beginIter) + assert(inclusiveBeginLoc <= requestBuffer.size()); + if (requestBuffer.size() == inclusiveBeginLoc) { return false; } @@ -279,30 +286,46 @@ bool SMS::batchFormation(sc_time const &memClk, Thread const &thread, std::deque if (MPKCs[thread] < LOW_MPKC || isSystemLightlyLoaded()) { // bypass requests by forming batch with only one request (threshold age is ZERO) - readyBatchIters[thread].push_back(beginIter); + readyBatchInclusiveEndLocs[thread].push_back(inclusiveBeginLoc); return true; } else { // forming batch with FIFO size & threshold age constraints - std::deque::iterator firstDifferentRowAccessReqIter = beginIter; - Row firstRow = DramExtension::getRow(*beginIter); - while (firstDifferentRowAccessReqIter != requestBuffer.end() - && DramExtension::getRow(*firstDifferentRowAccessReqIter) == firstRow) + size_t firstDifferentRowAccessReqLoc = inclusiveBeginLoc; + Row firstRow = DramExtension::getRow(requestBuffer[inclusiveBeginLoc]); + bool isBatchReady = false; + size_t bufferSize = requestBuffer.size(); + while (firstDifferentRowAccessReqLoc != bufferSize + && DramExtension::getRow(requestBuffer[firstDifferentRowAccessReqLoc]) == firstRow) { - ++firstDifferentRowAccessReqIter; - if (firstDifferentRowAccessReqIter == requestBuffer.end ()) { - break; - } + ++firstDifferentRowAccessReqLoc; + if (firstDifferentRowAccessReqLoc < bufferSize) + { + if (DramExtension::getRow(requestBuffer[firstDifferentRowAccessReqLoc]) != firstRow + || isExceededReqBufferSize(firstDifferentRowAccessReqLoc) + || isThresholdAgeExceeded(thread, memClk, inclusiveBeginLoc, firstDifferentRowAccessReqLoc)) + { + isBatchReady = true; + break; + } + } + else + { + if (isExceededReqBufferSize(firstDifferentRowAccessReqLoc) + || isThresholdAgeExceeded(thread, memClk, inclusiveBeginLoc, firstDifferentRowAccessReqLoc)) + { + isBatchReady = true; + break; + } + } } - // deem this batch ready - if ((firstDifferentRowAccessReqIter != requestBuffer.end()) - || isExceededReqBufferSize(thread) - || isThresholdAgeExceeded(thread, memClk, beginIter, firstDifferentRowAccessReqIter)) + // store this ready batch location + if (isBatchReady) { - --firstDifferentRowAccessReqIter; - readyBatchIters[thread].push_back(firstDifferentRowAccessReqIter); + --firstDifferentRowAccessReqLoc; + readyBatchInclusiveEndLocs[thread].push_back(firstDifferentRowAccessReqLoc); debugManager.printDebugMessage(name(), "Deem batch ready - thread " + to_string(thread.ID())); return true; @@ -318,16 +341,16 @@ void SMS::multiBatchFormation(sc_time const &memClk) { for (auto &requestBuffer : requestBuffers) { - bool formed; + bool formed = false; do { - if (readyBatchIters[requestBuffer.first].empty()) + if (readyBatchInclusiveEndLocs[requestBuffer.first].empty()) { - formed = batchFormation(memClk, requestBuffer.first, requestBuffer.second, requestBuffer.second.begin()); + formed = batchFormation(memClk, requestBuffer.first, requestBuffer.second, 0); } else { - formed = batchFormation(memClk, requestBuffer.first, requestBuffer.second, readyBatchIters[requestBuffer.first].back() + 1); + formed = batchFormation(memClk, requestBuffer.first, requestBuffer.second, readyBatchInclusiveEndLocs[requestBuffer.first].back() + 1); } } while (!requestBuffer.second.empty() && formed); } diff --git a/DRAMSys/simulator/src/controller/scheduler/SMS.h b/DRAMSys/simulator/src/controller/scheduler/SMS.h index bdb5c783..bbfffae1 100644 --- a/DRAMSys/simulator/src/controller/scheduler/SMS.h +++ b/DRAMSys/simulator/src/controller/scheduler/SMS.h @@ -35,7 +35,7 @@ public: SMS(sc_module_name /*_name*/, ControllerCore &controllerCore, unsigned int SJFprobability) : IScheduler(controllerCore), SJFprobability(SJFprobability), debugManager(DebugManager::getInstance()) { // initialize selected thread iterator - lastSelectedThread = readyBatchIters.end(); + lastSelectedThread = readyBatchInclusiveEndLocs.end(); SC_THREAD(batchScheduler); } SC_HAS_PROCESS(SMS); @@ -53,28 +53,28 @@ public: private: std::map> requestBuffers; std::map> bankBuffers; - std::map> readyBatchIters; + std::map> readyBatchInclusiveEndLocs; std::map inFlightMemRequestCounter; std::map cacheMisses; std::map MPKCs; unsigned int SJFprobability; - std::map>::iterator lastSelectedThread; + std::map>::iterator lastSelectedThread; sc_event newRequest; DebugManager& debugManager; - bool batchFormation(sc_time const &memClk, Thread const &thread, const std::deque &requestBuffer, const std::deque::iterator &beginIter); + bool batchFormation(sc_time const &memClk, Thread const &thread, const std::deque &requestBuffer, const size_t &inclusiveBeginLoc); void multiBatchFormation(const sc_time &memClk); bool pickSJF(); bool pickRR(); - void drain(const sc_time &memClk); + void drainOnePayloadFromReadybatch(const sc_time &memClk); bool existLowIntensityThread() const; bool isSystemLightlyLoaded() const; - bool isThresholdAgeExceeded(const Thread &thread, const sc_time &memClk, const std::deque::iterator &begin, const std::deque::iterator &end); - bool isExceededReqBufferSize(Thread const &thread); + bool isThresholdAgeExceeded(const Thread &thread, const sc_time &memClk, const size_t &inclusiveBeginLoc, const size_t &exclusiveEndLoc); + bool isExceededReqBufferSize(size_t const &exclusiveEndLoc); void updateMPKCs(const sc_time &memClk); bool isRequestBuffersEmpty() const;