diff --git a/DRAMSys/simulator/resources/simulations/sms-example.xml b/DRAMSys/simulator/resources/simulations/sms-example.xml index d1a2f734..d40e0e8c 100644 --- a/DRAMSys/simulator/resources/simulations/sms-example.xml +++ b/DRAMSys/simulator/resources/simulations/sms-example.xml @@ -12,10 +12,14 @@ + ddr3_example.stl sms_t1.stl sms_t2.stl sms_t3.stl sms_t4.stl + stream.stl + random.stl + chstone-adpcm_32.stl diff --git a/DRAMSys/simulator/src/controller/scheduler/SMS.cpp b/DRAMSys/simulator/src/controller/scheduler/SMS.cpp index 14d63207..d4336415 100644 --- a/DRAMSys/simulator/src/controller/scheduler/SMS.cpp +++ b/DRAMSys/simulator/src/controller/scheduler/SMS.cpp @@ -54,36 +54,25 @@ void SMS::batchScheduler() while (true) { -// updateMPKCs(memClk); -// if (isRequestBuffersEmpty() && !existReadyBatches()) { -// wait(newRequest); -// } else { -// batchFormation(memClk); -// if (existReadyBatches()) { -// if (!isSystemLightlyLoaded() && (existLowIntensityThread() || distribution(generator))) { -// selectSJF(memClk); -// } else { -// selectRR(memClk); -// } -// } else { -// wait(memClk); -// } -// } updateMPKCs(memClk); if (isRequestBuffersEmpty()) { wait(newRequest); } else { multiBatchFormation(memClk); - if (!isSystemLightlyLoaded() && (existLowIntensityThread() || distribution(generator))) { - if (pickSJF()) { - drain(memClk, readyBatchesIter[(*lastSelectedThread).first].front()); - readyBatchesIter[(*lastSelectedThread).first].pop_front(); + if (existReadyBatches()) { + if (!isSystemLightlyLoaded() && (existLowIntensityThread() || distribution(generator))) { + if (pickSJF()) { + drain(memClk, (*lastSelectedThread).second.front()); + (*lastSelectedThread).second.pop_front(); + } + } else { + if (pickRR()) { + drain(memClk, (*lastSelectedThread).second.front()); + (*lastSelectedThread).second.pop_front(); + } } } else { - if (pickRR()) { - drain(memClk, readyBatchesIter[(*lastSelectedThread).first].front()); - readyBatchesIter[(*lastSelectedThread).first].pop_front(); - } + wait(memClk); } } } @@ -96,22 +85,22 @@ void SMS::batchScheduler() */ bool SMS::pickSJF() { - // find threads with non-empty request buffers - std::vector threadsWithNonEmptyRequestBuffer; - for (auto& requestBuffer : requestBuffers) + // find threads with ready batches + std::vector threadsWithReadyBatches; + for (auto& each : readyBatchIters) { - if (!requestBuffer.second.empty()) + if (!each.second.empty()) { // marked as thread with non-empty request buffer - threadsWithNonEmptyRequestBuffer.push_back(requestBuffer.first); + threadsWithReadyBatches.push_back(each.first); } } - if (!threadsWithNonEmptyRequestBuffer.empty()) + if (!threadsWithReadyBatches.empty()) { // pick shortest-job thread among threads with non-empty request buffer - Thread minThread = threadsWithNonEmptyRequestBuffer.front(); - for (auto& thread : threadsWithNonEmptyRequestBuffer) + Thread minThread = threadsWithReadyBatches.front(); + for (auto& thread : threadsWithReadyBatches) { if (inFlightMemRequestCounter[thread] < inFlightMemRequestCounter[minThread]) { @@ -120,7 +109,7 @@ bool SMS::pickSJF() } // save selected thread - lastSelectedThread = readybatches.find(minThread); + lastSelectedThread = readyBatchIters.find(minThread); debugManager.printDebugMessage(name(), "[SJF] Select ready batch of thread " + to_string(minThread.ID())); return true; @@ -131,62 +120,6 @@ bool SMS::pickSJF() } } -bool SMS::selectSJF(sc_time memClk) -{ - // find threads with non-empty ready batch - std::vector threadsWithNonEmptyReadybatches; - for (auto& readybatch : readybatches) - { - if (!readybatch.second.empty()) - { - // marked as thread with non-empty ready batch - threadsWithNonEmptyReadybatches.push_back(readybatch.first); - } - } - - if (!threadsWithNonEmptyReadybatches.empty()) - { - // pick shortest-job thread among threads with non-empty ready batch - Thread minThread = threadsWithNonEmptyReadybatches.front(); - for (auto& thread : threadsWithNonEmptyReadybatches) - { - if (inFlightMemRequestCounter[thread] < inFlightMemRequestCounter[minThread]) - { - minThread = thread; - } - } - - // save selected thread - lastSelectedThread = readybatches.find(minThread); - - debugManager.printDebugMessage(name(), - "[SJF] Select ready batch of thread " + to_string(minThread.ID())); - - // drain to bank buffers - std::deque &requestPtrs = readybatches[minThread]; - for (auto payloadPtrIterator = requestPtrs.begin(); payloadPtrIterator != requestPtrs.end(); - payloadPtrIterator++) - { - Bank bank = DramExtension::getExtension(*payloadPtrIterator).getBank(); - bankBuffers[bank].emplace_back(*payloadPtrIterator); - debugManager.printDebugMessage(name(), - "[SJF] Drain request in the ready batch of thread " + to_string(minThread.ID()) - + " to bankbuffer " + to_string(bank.ID())); - wait(memClk); - } - requestPtrs.clear(); - - // a ready batch has been picked up & drained - return true; - } - else - { - // non-existed ready batch to be picked up & drained - // this mean the request buffers are totally empty - return false; - } -} - /** * Drain the picked request buffer into bank buffers * by move request one-by-one from start of the request buffer till last parameter @@ -195,17 +128,18 @@ bool SMS::selectSJF(sc_time memClk) */ void SMS::drain(sc_time memClk, std::deque::iterator last) { - unsigned int batchSize = std::distance((*lastSelectedThread).second.begin(), last) + 1; + 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(*((*lastSelectedThread).second.begin())).getBank(); + Bank bank = DramExtension::getExtension(requestBuffers[selectedThread].front()).getBank(); // if(bankBuffers[bank].size() == Configuration::getInstance().BankBufferSize) // { // wait(bankBufferIsNotFull); // } wait(memClk); - bankBuffers[bank].emplace_back(*((*lastSelectedThread).second.begin())); - (*lastSelectedThread).second.pop_front(); + bankBuffers[bank].emplace_back(requestBuffers[selectedThread].front()); + requestBuffers[selectedThread].pop_front(); debugManager.printDebugMessage(name(), "[SJF] Drain request in the ready batch of thread " @@ -221,28 +155,28 @@ void SMS::drain(sc_time memClk, std::deque::iterator last) */ bool SMS::pickRR() { - std::map>::iterator nextSelectedThread; - if (lastSelectedThread == requestBuffers.end()) + std::map>::iterator nextSelectedThread; + if (lastSelectedThread == readyBatchIters.end()) { - lastSelectedThread = requestBuffers.begin(); + lastSelectedThread = readyBatchIters.begin(); nextSelectedThread = lastSelectedThread; } else { nextSelectedThread = lastSelectedThread; nextSelectedThread++; - if (nextSelectedThread == requestBuffers.end()) - nextSelectedThread = requestBuffers.begin(); + if (nextSelectedThread == readyBatchIters.end()) + nextSelectedThread = readyBatchIters.begin(); } - std::map>::iterator savedOriginalNextSelectedThread = nextSelectedThread; + std::map>::iterator savedOriginalNextSelectedThread = nextSelectedThread; while ((*nextSelectedThread).second.empty()) { nextSelectedThread++; - if (nextSelectedThread == requestBuffers.end()) + if (nextSelectedThread == readyBatchIters.end()) { - nextSelectedThread = requestBuffers.begin(); + nextSelectedThread = readyBatchIters.begin(); } if (nextSelectedThread == savedOriginalNextSelectedThread) @@ -259,67 +193,6 @@ bool SMS::pickRR() return true; } -bool SMS::selectRR(sc_time memClk) -{ - // no request for this channel, the readybatches map is empty then return - if (readybatches.empty()) { - return false; - } - - // pick the next non-empty ready batch - std::map>::iterator nextSelectedThread; - if (lastSelectedThread == readybatches.end()) - { - lastSelectedThread = readybatches.begin(); - nextSelectedThread = lastSelectedThread; - } - else - { - nextSelectedThread = lastSelectedThread; - nextSelectedThread++; - if (nextSelectedThread == readybatches.end()) - nextSelectedThread = readybatches.begin(); - } - std::map>::iterator savedOriginalNextSelectedThread = nextSelectedThread; - while ((*nextSelectedThread).second.empty()) - { - nextSelectedThread++; - if (nextSelectedThread == readybatches.end()) - { - nextSelectedThread = readybatches.begin(); - } - - if (nextSelectedThread == savedOriginalNextSelectedThread) - { - // 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())); - - // drain to bank buffers - std::deque &requestPtrs = (*nextSelectedThread).second; - for (auto payloadPtrIterator = requestPtrs.begin(); payloadPtrIterator != requestPtrs.end(); - payloadPtrIterator++) - { - Bank bank = DramExtension::getExtension(*payloadPtrIterator).getBank(); - bankBuffers[bank].emplace_back(*payloadPtrIterator); - debugManager.printDebugMessage(name(), - "[RR] Drained request in the ready batch of thread " + to_string((*nextSelectedThread).first.ID()) - + " to bankbuffer " + to_string(bank.ID())); - wait(memClk); - } - requestPtrs.clear(); - - // a ready batch has been picked up & drained - return true; -} - bool SMS::isSystemLightlyLoaded() { unsigned int totalRequest = 0; for (auto& bankBuffer : bankBuffers) { @@ -378,36 +251,6 @@ bool SMS::isExceededReqBufferSize(Thread thread) { return requestBuffers[thread].size() == REQUEST_BUFFER_SIZE; } -void SMS::batchFormation(sc_time memClk) { - for (auto& requestBuffer : requestBuffers) { - if (!requestBuffer.second.empty() && readybatches[requestBuffer.first].empty()) { - if (MPKCs[requestBuffer.first] < LOW_MPKC || isSystemLightlyLoaded()) { - // bypass requests by forming batch with only one request (threshold age is ZERO) - readybatches[requestBuffer.first].emplace_back(requestBuffer.second.front()); - requestBuffer.second.pop_front(); - debugManager.printDebugMessage(name(), "Bypass requests by forming batch of thread " + to_string(requestBuffer.first.ID())); - } else { - // forming batch with FIFO size & threshold age constraints - auto firstDifferentRowAccessReqIter = requestBuffer.second.begin(); - Row firstRow = DramExtension::getRow(*firstDifferentRowAccessReqIter); - while (firstDifferentRowAccessReqIter != requestBuffer.second.end() && DramExtension::getRow(*firstDifferentRowAccessReqIter) == firstRow) { - firstDifferentRowAccessReqIter++; - } - // deem this batch ready - if ((firstDifferentRowAccessReqIter != requestBuffer.second.end()) - || isExceededReqBufferSize(requestBuffer.first) - || isThresholdAgeExceeded(requestBuffer.first, memClk, requestBuffer.second.begin(), firstDifferentRowAccessReqIter)) { - do { - readybatches[requestBuffer.first].emplace_back(requestBuffer.second.front()); - requestBuffer.second.pop_front(); - } while (requestBuffer.second.begin() != firstDifferentRowAccessReqIter); - debugManager.printDebugMessage(name(), "Deem batch ready - thread " + to_string(requestBuffer.first.ID())); - } - } - } - } -} - bool SMS::isRequestBuffersEmpty() { for (auto& requestBuffer : requestBuffers) { if (!requestBuffer.second.empty()) { @@ -418,8 +261,8 @@ bool SMS::isRequestBuffersEmpty() { } bool SMS::existReadyBatches() { - for (auto& readybatch : readybatches) { - if (!readybatch.second.empty()) { + for (auto& each : readyBatchIters) { + if (!each.second.empty()) { return true; } } @@ -449,7 +292,7 @@ bool SMS::batchFormation(sc_time memClk, std::pair> &req if (MPKCs[requestBuffer.first] < LOW_MPKC || isSystemLightlyLoaded()) { // bypass requests by forming batch with only one request (threshold age is ZERO) - readyBatchesIter[requestBuffer.first].push_back(beginIter); + readyBatchIters[requestBuffer.first].push_back(beginIter); return true; } else @@ -470,7 +313,7 @@ bool SMS::batchFormation(sc_time memClk, std::pair> &req firstDifferentRowAccessReqIter)) { firstDifferentRowAccessReqIter--; - readyBatchesIter[requestBuffer.first].push_back(firstDifferentRowAccessReqIter); + readyBatchIters[requestBuffer.first].push_back(firstDifferentRowAccessReqIter); debugManager.printDebugMessage(name(), "Deem batch ready - thread " + to_string(requestBuffer.first.ID())); return true; @@ -489,13 +332,13 @@ void SMS::multiBatchFormation(sc_time memClk) bool formed; do { - if (readyBatchesIter[requestBuffer.first].empty()) + if (readyBatchIters[requestBuffer.first].empty()) { formed = batchFormation(memClk, (std::pair>&)requestBuffer, requestBuffer.second.begin()); } else { - formed = batchFormation(memClk, (std::pair>&)requestBuffer, readyBatchesIter[requestBuffer.first].back() + 1); + formed = batchFormation(memClk, (std::pair>&)requestBuffer, readyBatchIters[requestBuffer.first].back() + 1); } } while (formed); } diff --git a/DRAMSys/simulator/src/controller/scheduler/SMS.h b/DRAMSys/simulator/src/controller/scheduler/SMS.h index c786fbcc..df9c132f 100644 --- a/DRAMSys/simulator/src/controller/scheduler/SMS.h +++ b/DRAMSys/simulator/src/controller/scheduler/SMS.h @@ -20,6 +20,7 @@ #define REQUEST_BUFFER_SIZE 10 using namespace std; +typedef std::deque::iterator gp_deque_iterator; class SMS: public sc_module, public IScheduler { @@ -27,8 +28,7 @@ public: SMS(sc_module_name /*_name*/, ControllerCore &controllerCore, unsigned int SJFprobability) : IScheduler(controllerCore), SJFprobability(SJFprobability), debugManager(DebugManager::getInstance()) { // initialize selected thread iterator -// lastSelectedThread = readybatches.end(); - lastSelectedThread = requestBuffers.end(); + lastSelectedThread = readyBatchIters.end(); SC_THREAD(batchScheduler); } SC_HAS_PROCESS(SMS); @@ -45,22 +45,18 @@ public: private: std::map> requestBuffers; std::map> bankBuffers; - std::map> readybatches; - std::map::iterator>> readyBatchesIter; + std::map> readyBatchIters; 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 selectSJF(sc_time memClk); - bool selectRR(sc_time memClk); - void batchFormation(sc_time memClk); bool batchFormation(sc_time memClk, std::pair> &requestBuffer, std::deque::iterator beginIter); void multiBatchFormation(sc_time memClk); bool pickSJF();