diff --git a/DRAMSys/simulator/resources/configs/mcconfigs/sms.xml b/DRAMSys/simulator/resources/configs/mcconfigs/sms.xml index 088a9f66..f2ac6c19 100644 --- a/DRAMSys/simulator/resources/configs/mcconfigs/sms.xml +++ b/DRAMSys/simulator/resources/configs/mcconfigs/sms.xml @@ -1,7 +1,7 @@ - + @@ -13,4 +13,4 @@ - \ No newline at end of file + diff --git a/DRAMSys/simulator/resources/simulations/sms-example.xml b/DRAMSys/simulator/resources/simulations/sms-example.xml index d40e0e8c..3b412664 100644 --- a/DRAMSys/simulator/resources/simulations/sms-example.xml +++ b/DRAMSys/simulator/resources/simulations/sms-example.xml @@ -12,14 +12,15 @@ - ddr3_example.stl + + + random.stl + chstone-adpcm_32.stl + stream.stl 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 64882dc3..a6547998 100644 --- a/DRAMSys/simulator/src/controller/scheduler/SMS.cpp +++ b/DRAMSys/simulator/src/controller/scheduler/SMS.cpp @@ -5,77 +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))) { - if (pickSJF()) { - drain(memClk, (*lastSelectedThread).second.front()); - (*lastSelectedThread).second.pop_front(); - } + while (true) + { + updateMPKCs(memClk); + if (isRequestBuffersEmpty()) { + wait(newRequest); } else { - if (pickRR()) { - drain(memClk, (*lastSelectedThread).second.front()); - (*lastSelectedThread).second.pop_front(); - } + multiBatchFormation(memClk); + if (existReadyBatches()) { + if (!isSystemLightlyLoaded() && (existLowIntensityThread() || distribution(generator))) { + pickSJF(); + } else { + pickRR(); + } + drainOnePayloadFromReadybatch(memClk); + } else { + wait(memClk); + } } - } else { - wait(memClk); - } } - } } /** @@ -85,39 +80,39 @@ void SMS::batchScheduler() */ bool SMS::pickSJF() { - // find threads with ready batches - std::vector threadsWithReadyBatches; - for (auto& each : readyBatchIters) - { - 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 (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 = readyBatchIters.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; + } } /** @@ -126,26 +121,36 @@ bool SMS::pickSJF() * @param memClk * @param last */ -void SMS::drain(sc_time memClk, std::deque::iterator last) +void SMS::drainOnePayloadFromReadybatch(const sc_time &memClk) { - Thread selectedThread = (*lastSelectedThread).first; - unsigned int batchSize = std::distance(requestBuffers[selectedThread].begin(), last) + 1; - for (unsigned int i = 1; i <= batchSize; i++) - { - Bank bank = DramExtension::getExtension(requestBuffers[selectedThread].front()).getBank(); - // if(bankBuffers[bank].size() == Configuration::getInstance().BankBufferSize) - // { - // wait(bankBufferIsNotFull); - // } - wait(memClk); - bankBuffers[bank].emplace_back(requestBuffers[selectedThread].front()); - requestBuffers[selectedThread].pop_front(); + if (lastSelectedThread->second.empty()) { + return; + } + 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())); - } + 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(); } /** @@ -155,118 +160,107 @@ void SMS::drain(sc_time memClk, std::deque::iterator last) */ bool SMS::pickRR() { - std::map>::iterator nextSelectedThread; - if (lastSelectedThread == readyBatchIters.end()) - { - lastSelectedThread = readyBatchIters.begin(); - nextSelectedThread = lastSelectedThread; - } - else - { - nextSelectedThread = lastSelectedThread; - nextSelectedThread++; - if (nextSelectedThread == readyBatchIters.end()) - nextSelectedThread = readyBatchIters.begin(); - } - - std::map>::iterator savedOriginalNextSelectedThread = nextSelectedThread; - - while ((*nextSelectedThread).second.empty()) - { - nextSelectedThread++; - if (nextSelectedThread == readyBatchIters.end()) + if (lastSelectedThread == readyBatchInclusiveEndLocs.end()) { - nextSelectedThread = readyBatchIters.begin(); + lastSelectedThread = readyBatchInclusiveEndLocs.begin(); + if (!(*lastSelectedThread).second.empty()) { + return true; + } } - if (nextSelectedThread == savedOriginalNextSelectedThread) + std::map>::iterator savedOriginalNextSelectedThread = lastSelectedThread; + + do { - // the next thread is the original thread, that mean req buffer are totally empty - // non-existed ready batch to be picked up & drained - return false; - } - } - // save last selected thread - lastSelectedThread = nextSelectedThread; - debugManager.printDebugMessage(name(), - "[RR] Select ready batch of thread " + to_string((*nextSelectedThread).first.ID())); - return true; -} + lastSelectedThread++; + if (lastSelectedThread == readyBatchInclusiveEndLocs.end()) { + lastSelectedThread = readyBatchInclusiveEndLocs.begin(); + } + if (lastSelectedThread == savedOriginalNextSelectedThread) { + return false; + } + } while ((*lastSelectedThread).second.empty()); -bool SMS::isSystemLightlyLoaded() { - unsigned int totalRequest = 0; - for (auto& bankBuffer : bankBuffers) { - totalRequest += bankBuffer.second.size(); - } - return (totalRequest <= LOW_SYSTEM_LOAD); -} - -bool SMS::existLowIntensityThread() { - for (auto& mpkcPerThread : MPKCs) { - if (mpkcPerThread.second < LOW_MPKC) { - return true; - } - } - return false; -} - -bool SMS::isThresholdAgeExceeded(Thread thread, sc_time memClk, std::deque::iterator begin, std::deque::iterator end) { - // 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(); - 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))) { + debugManager.printDebugMessage(name(), + "[RR] Select ready batch of thread " + to_string((*lastSelectedThread).first.ID())); return true; - } else if ((MPKCs[thread] > MEDIUM_MPKC) && (oldestRequestAge > (HIGH_THRESHOLD_AGE * memClk))) { - return true; - } else { +} + +bool SMS::isSystemLightlyLoaded() const { + 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; + } + } return false; - } } -void SMS::updateMPKCs(sc_time memClk) { - if (sc_time_stamp() % (MPKC_RESET_CYCLE * memClk) <= memClk) { - // reset for every 10k clk cycles - for (auto& cacheMiss : cacheMisses) { - MPKCs[cacheMiss.first] = 0; +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; + } } - debugManager.printDebugMessage(name(), "Reset MKKCs"); - } else { - // update MPKC for every thread - for (auto& cacheMiss : cacheMisses) { - MPKCs[cacheMiss.first] = (cacheMiss.second * 1000.0 * memClk) / (sc_time_stamp()); + + // 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; } - debugManager.printDebugMessage(name(), "Update MPKCs"); - } } -bool SMS::isExceededReqBufferSize(Thread thread) { - return requestBuffers[thread].size() == Configuration::getInstance().RequestBufferSize; +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; + } + 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::isRequestBuffersEmpty() { - for (auto& requestBuffer : requestBuffers) { - if (!requestBuffer.second.empty()) { - return false; - } - } - return true; +bool SMS::isExceededReqBufferSize(size_t const &exclusiveEndLoc) { + return exclusiveEndLoc <= Configuration::getInstance().RequestBufferSize; } -bool SMS::existReadyBatches() { - for (auto& each : readyBatchIters) { - if (!each.second.empty()) { - return true; +bool SMS::isRequestBuffersEmpty() const { + for (const auto &requestBuffer : requestBuffers) { + if (!requestBuffer.second.empty()) { + return false; + } } - } - return false; + return true; +} + +bool SMS::existReadyBatches() const { + for (const auto &each : readyBatchInclusiveEndLocs) { + if (!each.second.empty()) { + return true; + } + } + return false; } /** @@ -276,82 +270,100 @@ bool SMS::existReadyBatches() { * @param begin * @return true if this batch is ready, otherwise false */ -bool SMS::batchFormation(sc_time memClk, std::pair> &requestBuffer, - std::deque::iterator beginIter) +bool SMS::batchFormation(sc_time const &memClk, Thread const &thread, std::deque const &requestBuffer, size_t const &inclusiveBeginLoc) { - if (requestBuffer.second.empty()) - { - return false; - } - - if (requestBuffer.second.end() == beginIter) - { - return false; - } - - if (MPKCs[requestBuffer.first] < LOW_MPKC || isSystemLightlyLoaded()) - { - // bypass requests by forming batch with only one request (threshold age is ZERO) - readyBatchIters[requestBuffer.first].push_back(beginIter); - return true; - } - else - { - // forming batch with FIFO size & threshold age constraints - auto firstDifferentRowAccessReqIter = beginIter; - Row firstRow = DramExtension::getRow(*beginIter); - while (firstDifferentRowAccessReqIter != requestBuffer.second.end() - && DramExtension::getRow(*firstDifferentRowAccessReqIter) == firstRow) + if (requestBuffer.empty()) { - firstDifferentRowAccessReqIter++; + return false; } - // deem this batch ready - if ((firstDifferentRowAccessReqIter != requestBuffer.second.end()) - || isExceededReqBufferSize(requestBuffer.first) - || isThresholdAgeExceeded(requestBuffer.first, memClk, beginIter, - firstDifferentRowAccessReqIter)) + assert(inclusiveBeginLoc <= requestBuffer.size()); + if (requestBuffer.size() == inclusiveBeginLoc) { - firstDifferentRowAccessReqIter--; - readyBatchIters[requestBuffer.first].push_back(firstDifferentRowAccessReqIter); - debugManager.printDebugMessage(name(), - "Deem batch ready - thread " + to_string(requestBuffer.first.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 memClk) +void SMS::multiBatchFormation(sc_time const &memClk) { - for (auto& requestBuffer : requestBuffers) - { - bool formed; - do + for (auto &requestBuffer : requestBuffers) { - if (readyBatchIters[requestBuffer.first].empty()) - { - formed = batchFormation(memClk, (std::pair>&)requestBuffer, requestBuffer.second.begin()); - } - else - { - formed = batchFormation(memClk, (std::pair>&)requestBuffer, readyBatchIters[requestBuffer.first].back() + 1); - } - } while (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 (auto& requestBuffer : requestBuffers) { - for (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 2843b990..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 = readyBatchIters.end(); - SC_THREAD(batchScheduler); + // initialize selected thread iterator + lastSelectedThread = readyBatchInclusiveEndLocs.end(); + SC_THREAD(batchScheduler); } SC_HAS_PROCESS(SMS); @@ -53,32 +53,32 @@ 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 memClk, std::pair> &requestBuffer, std::deque::iterator beginIter); - void multiBatchFormation(sc_time memClk); + 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(sc_time memClk, std::deque::iterator last); + void drainOnePayloadFromReadybatch(const sc_time &memClk); - bool existLowIntensityThread(); - bool isSystemLightlyLoaded(); - bool isThresholdAgeExceeded(Thread thread, sc_time memClk, std::deque::iterator begin, std::deque::iterator end); - bool isExceededReqBufferSize(Thread thread); - void updateMPKCs(sc_time memClk); + bool existLowIntensityThread() const; + bool isSystemLightlyLoaded() const; + 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(); - bool existReadyBatches(); + bool isRequestBuffersEmpty() const; + bool existReadyBatches() const; }; #endif // SMS_H