diff --git a/DRAMSys/simulator/src/controller/scheduler/SMS.cpp b/DRAMSys/simulator/src/controller/scheduler/SMS.cpp index 5d103522..a6547998 100644 --- a/DRAMSys/simulator/src/controller/scheduler/SMS.cpp +++ b/DRAMSys/simulator/src/controller/scheduler/SMS.cpp @@ -5,72 +5,72 @@ using namespace std; void SMS::schedule(gp *payload) { - Thread thread = DramExtension::getExtension(payload).getThread(); - bool wasEmpty = isRequestBuffersEmpty(); + Thread thread = DramExtension::getExtension(payload).getThread(); + bool wasEmpty = isRequestBuffersEmpty(); - requestBuffers[thread].emplace_back(payload); + requestBuffers[thread].emplace_back(payload); - if (inFlightMemRequestCounter.find(thread) == inFlightMemRequestCounter.end()) { - inFlightMemRequestCounter[thread] = 0; - cacheMisses[thread] = 0; - } - inFlightMemRequestCounter[thread]++; - cacheMisses[thread]++; + if (inFlightMemRequestCounter.find(thread) == inFlightMemRequestCounter.end()) { + inFlightMemRequestCounter[thread] = 0; + cacheMisses[thread] = 0; + } + inFlightMemRequestCounter[thread]++; + cacheMisses[thread]++; - if (wasEmpty) { - newRequest.notify(SC_ZERO_TIME); - } + if (wasEmpty) { + newRequest.notify(SC_ZERO_TIME); + } } std::pair SMS::getNextRequest(Bank bank) { - if (bankBuffers[bank].empty()) - { - debugManager.printDebugMessage(name(), - "Get next request on bank " + to_string(bank.ID()) + " : EMPTY buffer"); - return pair(Command::NOP, NULL); - } - else - { - gp* payload = bankBuffers[bank].front(); - Command command = IScheduler::getNextCommand(*payload); - if (command == Command::Read || command == Command::ReadA || command == Command::Write - || command == Command::WriteA) + if (bankBuffers[bank].empty()) { - inFlightMemRequestCounter[DramExtension::getExtension(payload).getThread()]--; - bankBuffers[bank].pop_front(); + debugManager.printDebugMessage(name(), + "Get next request on bank " + to_string(bank.ID()) + " : EMPTY buffer"); + return pair(Command::NOP, NULL); } + else + { + gp* payload = bankBuffers[bank].front(); + Command command = IScheduler::getNextCommand(*payload); + if (command == Command::Read || command == Command::ReadA || command == Command::Write + || command == Command::WriteA) + { + inFlightMemRequestCounter[DramExtension::getExtension(payload).getThread()]--; + bankBuffers[bank].pop_front(); + } - debugManager.printDebugMessage(name(), "Get next request on bank " + to_string(bank.ID())); - return pair(command, payload); - } + debugManager.printDebugMessage(name(), "Get next request on bank " + to_string(bank.ID())); + return pair(command, payload); + } } void SMS::batchScheduler() { - sc_time memClk = Configuration::getInstance().memSpec.clk; - std::default_random_engine generator; - std::bernoulli_distribution distribution((double) SJFprobability / 100.0); + sc_time memClk = Configuration::getInstance().memSpec.clk; + std::default_random_engine generator; + std::bernoulli_distribution distribution((double) SJFprobability / 100.0); - while (true) - { - updateMPKCs(memClk); - if (isRequestBuffersEmpty()) { - wait(newRequest); - } else { - multiBatchFormation(memClk); - if (existReadyBatches()) { - if (!isSystemLightlyLoaded() && (existLowIntensityThread() || distribution(generator))) { - pickSJF(); + while (true) + { + updateMPKCs(memClk); + if (isRequestBuffersEmpty()) { + wait(newRequest); } else { - pickRR(); + multiBatchFormation(memClk); + if (existReadyBatches()) { + if (!isSystemLightlyLoaded() && (existLowIntensityThread() || distribution(generator))) { + pickSJF(); + } else { + pickRR(); + } + drainOnePayloadFromReadybatch(memClk); + } else { + wait(memClk); + } } - drainOnePayloadFromReadybatch(memClk); - } else { - wait(memClk); - } } - } } /** @@ -80,39 +80,39 @@ void SMS::batchScheduler() */ bool SMS::pickSJF() { - // find threads with ready batches - std::vector threadsWithReadyBatches; - for (const auto &each : readyBatchInclusiveEndLocs) - { - if (!each.second.empty()) + // find threads with ready batches + std::vector threadsWithReadyBatches; + for (const auto &each : readyBatchInclusiveEndLocs) { - // marked as thread with non-empty request buffer - threadsWithReadyBatches.push_back(each.first); - } - } - - if (!threadsWithReadyBatches.empty()) - { - // pick shortest-job thread among threads with non-empty request buffer - Thread &minThread = threadsWithReadyBatches.front(); - for (const auto &thread : threadsWithReadyBatches) - { - if (inFlightMemRequestCounter[thread] < inFlightMemRequestCounter[minThread]) - { - minThread = thread; - } + if (!each.second.empty()) + { + // marked as thread with non-empty request buffer + threadsWithReadyBatches.push_back(each.first); + } } - // save selected thread - lastSelectedThread = readyBatchInclusiveEndLocs.find(minThread); - debugManager.printDebugMessage(name(), - "[SJF] Select ready batch of thread " + to_string(minThread.ID())); - return true; - } - else - { - return false; - } + if (!threadsWithReadyBatches.empty()) + { + // pick shortest-job thread among threads with non-empty request buffer + Thread &minThread = threadsWithReadyBatches.front(); + for (const auto &thread : threadsWithReadyBatches) + { + if (inFlightMemRequestCounter[thread] < inFlightMemRequestCounter[minThread]) + { + minThread = thread; + } + } + + // save selected thread + lastSelectedThread = readyBatchInclusiveEndLocs.find(minThread); + debugManager.printDebugMessage(name(), + "[SJF] Select ready batch of thread " + to_string(minThread.ID())); + return true; + } + else + { + return false; + } } /** @@ -123,34 +123,34 @@ bool SMS::pickSJF() */ void SMS::drainOnePayloadFromReadybatch(const sc_time &memClk) { - if (lastSelectedThread->second.empty()) { + if (lastSelectedThread->second.empty()) { return; - } - const Thread &selectedThread = lastSelectedThread->first; - - const size_t &inclusiveEndLoc = lastSelectedThread->second.front(); - assert(inclusiveEndLoc < requestBuffers.size()); - - for (size_t i = 0; i <= inclusiveEndLoc; ++i) - { - 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]; } + const Thread &selectedThread = lastSelectedThread->first; - 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(); + const size_t &inclusiveEndLoc = lastSelectedThread->second.front(); + assert(inclusiveEndLoc < requestBuffers.size()); + + for (size_t i = 0; i <= inclusiveEndLoc; ++i) + { + 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[selectedThread].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(); } /** @@ -162,105 +162,105 @@ bool SMS::pickRR() { if (lastSelectedThread == readyBatchInclusiveEndLocs.end()) { - lastSelectedThread = readyBatchInclusiveEndLocs.begin(); - if (!(*lastSelectedThread).second.empty()) { - return true; - } + lastSelectedThread = readyBatchInclusiveEndLocs.begin(); + if (!(*lastSelectedThread).second.empty()) { + return true; + } } std::map>::iterator savedOriginalNextSelectedThread = lastSelectedThread; do { - lastSelectedThread++; - if (lastSelectedThread == readyBatchInclusiveEndLocs.end()) { - lastSelectedThread = readyBatchInclusiveEndLocs.begin(); - } - if (lastSelectedThread == savedOriginalNextSelectedThread) { - return false; - } + lastSelectedThread++; + if (lastSelectedThread == readyBatchInclusiveEndLocs.end()) { + lastSelectedThread = readyBatchInclusiveEndLocs.begin(); + } + if (lastSelectedThread == savedOriginalNextSelectedThread) { + return false; + } } while ((*lastSelectedThread).second.empty()); debugManager.printDebugMessage(name(), - "[RR] Select ready batch of thread " + to_string((*lastSelectedThread).first.ID())); + "[RR] Select ready batch of thread " + to_string((*lastSelectedThread).first.ID())); return true; } bool SMS::isSystemLightlyLoaded() const { - unsigned int totalRequest = 0; - for (const auto &bankBuffer : bankBuffers) { - totalRequest += bankBuffer.second.size(); - } - return (totalRequest <= LOW_SYSTEM_LOAD); + unsigned int totalRequest = 0; + for (const auto &bankBuffer : bankBuffers) { + totalRequest += bankBuffer.second.size(); + } + return (totalRequest <= LOW_SYSTEM_LOAD); } bool SMS::existLowIntensityThread() const { - for (const auto &mpkcPerThread : MPKCs) { - if (mpkcPerThread.second < LOW_MPKC) { - return true; + for (const auto &mpkcPerThread : MPKCs) { + if (mpkcPerThread.second < LOW_MPKC) { + return true; + } } - } - return false; + return false; } 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 (size_t i = inclusiveBeginLoc; i != exclusiveEndLoc; ++i) { - sc_time reqGenerationTime = GenerationExtension::getExtension(requestBuffers[thread][i]).TimeOfGeneration(); - if (reqGenerationTime < oldestGenerationTime) { - oldestGenerationTime = reqGenerationTime; + assert((exclusiveEndLoc - inclusiveBeginLoc) >= 1); + // find the oldest request in the thread's batch + sc_time oldestGenerationTime = sc_time_stamp(); + for (size_t i = inclusiveBeginLoc; i != exclusiveEndLoc; ++i) { + sc_time reqGenerationTime = GenerationExtension::getExtension(requestBuffers[thread][i]).TimeOfGeneration(); + if (reqGenerationTime < oldestGenerationTime) { + oldestGenerationTime = reqGenerationTime; + } } - } - // check threshold age according to the thread's MPKC - sc_time oldestRequestAge = sc_time_stamp() - oldestGenerationTime; - if ((MPKCs[thread] <= MEDIUM_MPKC) && (oldestRequestAge > (MEDIUM_THRESHOLD_AGE * memClk))) { - return true; - } else if ((MPKCs[thread] > MEDIUM_MPKC) && (oldestRequestAge > (HIGH_THRESHOLD_AGE * memClk))) { - return true; - } else { - return false; - } + // check threshold age according to the thread's MPKC + sc_time oldestRequestAge = sc_time_stamp() - oldestGenerationTime; + if ((MPKCs[thread] <= MEDIUM_MPKC) && (oldestRequestAge > (MEDIUM_THRESHOLD_AGE * memClk))) { + return true; + } else if ((MPKCs[thread] > MEDIUM_MPKC) && (oldestRequestAge > (HIGH_THRESHOLD_AGE * memClk))) { + return true; + } else { + return false; + } } void SMS::updateMPKCs(sc_time const &memClk) { - if (sc_time_stamp() % (MPKC_RESET_CYCLE * memClk) <= memClk) { - // reset for every 10k clk cycles - for (const auto &cacheMiss : cacheMisses) { - MPKCs[cacheMiss.first] = 0; + if (sc_time_stamp() % (MPKC_RESET_CYCLE * memClk) <= memClk) { + // reset for every 10k clk cycles + for (const auto &cacheMiss : cacheMisses) { + MPKCs[cacheMiss.first] = 0; + } + debugManager.printDebugMessage(name(), "Reset MKKCs"); + } else { + // update MPKC for every thread + for (const auto &cacheMiss : cacheMisses) { + MPKCs[cacheMiss.first] = (cacheMiss.second * 1000.0 * memClk) / (sc_time_stamp()); + } + debugManager.printDebugMessage(name(), "Update MPKCs"); } - debugManager.printDebugMessage(name(), "Reset MKKCs"); - } else { - // update MPKC for every thread - for (const auto &cacheMiss : cacheMisses) { - MPKCs[cacheMiss.first] = (cacheMiss.second * 1000.0 * memClk) / (sc_time_stamp()); - } - debugManager.printDebugMessage(name(), "Update MPKCs"); - } } bool SMS::isExceededReqBufferSize(size_t const &exclusiveEndLoc) { - return exclusiveEndLoc <= Configuration::getInstance().RequestBufferSize; + return exclusiveEndLoc <= Configuration::getInstance().RequestBufferSize; } bool SMS::isRequestBuffersEmpty() const { - for (const auto &requestBuffer : requestBuffers) { - if (!requestBuffer.second.empty()) { - return false; + for (const auto &requestBuffer : requestBuffers) { + if (!requestBuffer.second.empty()) { + return false; + } } - } - return true; + return true; } bool SMS::existReadyBatches() const { - for (const auto &each : readyBatchInclusiveEndLocs) { - if (!each.second.empty()) { - return true; + for (const auto &each : readyBatchInclusiveEndLocs) { + if (!each.second.empty()) { + return true; + } } - } - return false; + return false; } /** @@ -272,98 +272,98 @@ bool SMS::existReadyBatches() const { */ bool SMS::batchFormation(sc_time const &memClk, Thread const &thread, std::deque const &requestBuffer, size_t const &inclusiveBeginLoc) { - if (requestBuffer.empty()) - { - return false; - } - - assert(inclusiveBeginLoc <= requestBuffer.size()); - if (requestBuffer.size() == inclusiveBeginLoc) - { - return false; - } - - if (MPKCs[thread] < LOW_MPKC || isSystemLightlyLoaded()) - { - // bypass requests by forming batch with only one request (threshold age is ZERO) - readyBatchInclusiveEndLocs[thread].push_back(inclusiveBeginLoc); - return true; - } - else - { - // forming batch with FIFO size & threshold age constraints - 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) + if (requestBuffer.empty()) { - ++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; - } - } + return false; } - // store this ready batch location - if (isBatchReady) + assert(inclusiveBeginLoc <= requestBuffer.size()); + if (requestBuffer.size() == inclusiveBeginLoc) { - --firstDifferentRowAccessReqLoc; - readyBatchInclusiveEndLocs[thread].push_back(firstDifferentRowAccessReqLoc); - debugManager.printDebugMessage(name(), - "Deem batch ready - thread " + to_string(thread.ID())); - return true; + return false; + } + + if (MPKCs[thread] < LOW_MPKC || isSystemLightlyLoaded()) + { + // bypass requests by forming batch with only one request (threshold age is ZERO) + readyBatchInclusiveEndLocs[thread].push_back(inclusiveBeginLoc); + return true; } else { - return false; + // forming batch with FIFO size & threshold age constraints + 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) + { + ++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; + } + } + } + + // store this ready batch location + if (isBatchReady) + { + --firstDifferentRowAccessReqLoc; + readyBatchInclusiveEndLocs[thread].push_back(firstDifferentRowAccessReqLoc); + debugManager.printDebugMessage(name(), + "Deem batch ready - thread " + to_string(thread.ID())); + return true; + } + else + { + return false; + } } - } } void SMS::multiBatchFormation(sc_time const &memClk) { - for (auto &requestBuffer : requestBuffers) - { - bool formed = false; - do + for (auto &requestBuffer : requestBuffers) { - if (readyBatchInclusiveEndLocs[requestBuffer.first].empty()) - { - formed = batchFormation(memClk, requestBuffer.first, requestBuffer.second, 0); - } - else - { - formed = batchFormation(memClk, requestBuffer.first, requestBuffer.second, readyBatchInclusiveEndLocs[requestBuffer.first].back() + 1); - } - } while (!requestBuffer.second.empty() && formed); - } + bool formed = false; + do + { + if (readyBatchInclusiveEndLocs[requestBuffer.first].empty()) + { + formed = batchFormation(memClk, requestBuffer.first, requestBuffer.second, 0); + } + else + { + formed = batchFormation(memClk, requestBuffer.first, requestBuffer.second, readyBatchInclusiveEndLocs[requestBuffer.first].back() + 1); + } + } while (!requestBuffer.second.empty() && formed); + } } gp* SMS::getPendingRequest(Bank bank) { - for (const auto &requestBuffer : requestBuffers) { - for (const auto &request : requestBuffer.second) { - if (DramExtension::getBank(request) == bank) { - return request; - } + for (const auto &requestBuffer : requestBuffers) { + for (const auto &request : requestBuffer.second) { + if (DramExtension::getBank(request) == bank) { + return request; + } + } } - } - return NULL; + return NULL; } diff --git a/DRAMSys/simulator/src/controller/scheduler/SMS.h b/DRAMSys/simulator/src/controller/scheduler/SMS.h index bbfffae1..1b869cae 100644 --- a/DRAMSys/simulator/src/controller/scheduler/SMS.h +++ b/DRAMSys/simulator/src/controller/scheduler/SMS.h @@ -34,9 +34,9 @@ class SMS: public sc_module, public IScheduler public: SMS(sc_module_name /*_name*/, ControllerCore &controllerCore, unsigned int SJFprobability) : IScheduler(controllerCore), SJFprobability(SJFprobability), debugManager(DebugManager::getInstance()) { - // initialize selected thread iterator - lastSelectedThread = readyBatchInclusiveEndLocs.end(); - SC_THREAD(batchScheduler); + // initialize selected thread iterator + lastSelectedThread = readyBatchInclusiveEndLocs.end(); + SC_THREAD(batchScheduler); } SC_HAS_PROCESS(SMS);