diff --git a/DRAMSys/simulator/src/controller/scheduler/ReadyBatch.cpp b/DRAMSys/simulator/src/controller/scheduler/ReadyBatch.cpp index af218173..84af0d69 100644 --- a/DRAMSys/simulator/src/controller/scheduler/ReadyBatch.cpp +++ b/DRAMSys/simulator/src/controller/scheduler/ReadyBatch.cpp @@ -41,3 +41,13 @@ bool ReadyBatch::addTransaction(gp* payload) return true; } } + +std::deque& ReadyBatch::getTransactions() +{ + return readybatch; +} + +bool ReadyBatch::isEmpty() +{ + return readybatch.empty(); +} diff --git a/DRAMSys/simulator/src/controller/scheduler/ReadyBatch.h b/DRAMSys/simulator/src/controller/scheduler/ReadyBatch.h index ff9e8e80..5e2e8f49 100644 --- a/DRAMSys/simulator/src/controller/scheduler/ReadyBatch.h +++ b/DRAMSys/simulator/src/controller/scheduler/ReadyBatch.h @@ -14,6 +14,9 @@ class ReadyBatch public: ReadyBatch(); bool addTransaction(gp* payload); + unsigned int getNumRequests(); + std::deque& getTransactions(); + bool isEmpty(); private: std::deque readybatch; unsigned int fifosize; @@ -21,7 +24,6 @@ private: Row getRow(); sc_time getTimeOfOldestRequest(); - unsigned int getNumRequests(); }; #endif // READYBATCH_H diff --git a/DRAMSys/simulator/src/controller/scheduler/SMS.cpp b/DRAMSys/simulator/src/controller/scheduler/SMS.cpp index a3ae0867..252300b1 100644 --- a/DRAMSys/simulator/src/controller/scheduler/SMS.cpp +++ b/DRAMSys/simulator/src/controller/scheduler/SMS.cpp @@ -5,6 +5,16 @@ using namespace std; void SMS::schedule(gp *payload) { buffer[DramExtension::getExtension(payload).getThread()].emplace_back(payload); + + Thread thread = DramExtension::getExtension(payload).getThread(); + // update memory request counter + memrequestcounter[thread]++; + inFlightMemRequestCounter[thread]++; + + // update memory request intensity + sc_time lastrequestTimeOfGeneration = GenerationExtension::getExtension(payload).TimeOfGeneration(); + sc_time memClk = Configuration::getInstance().memSpec.clk; + memoryIntensity[thread] = (memrequestcounter[thread] * 1000.0 * memClk) / lastrequestTimeOfGeneration; // in MPKC } std::pair SMS::getNextRequest(Bank bank) @@ -20,6 +30,7 @@ std::pair SMS::getNextRequest(Bank bank) if (command == Command::Read || command == Command::ReadA || command == Command::Write || command == Command::WriteA) { + inFlightMemRequestCounter[DramExtension::getExtension(payload).getThread()]--; bankbuffer[bank].pop_front(); } @@ -27,3 +38,162 @@ std::pair SMS::getNextRequest(Bank bank) } } + +unsigned int SMS::totalMemoryRequests() +{ + //TODO: recheck this? how about total in-flight requests instead? + unsigned int totalSize = 0; + for (auto &reqQueue : buffer) + { + totalSize += reqQueue.second.size(); + } + return totalSize; +} + +void SMS::batchFormation() +{ + if (existReadyBatch()) + { + SC_REPORT_FATAL("SMS", "Form ready batches when exist at least a ready batch"); + } + else + { + auto totalNumThreads = Configuration::getInstance().NumberOfTracePlayers; + for (auto threadID = 1; threadID <= totalNumThreads; threadID++) + { + batchFormation(Thread(threadID)); + } + } +} + +void SMS::batchScheduler() +{ + while (true) + { + srand(time(NULL)); + bool isSJF = (rand() % 100) < SJFprobability; + if (!existReadyBatch()) + { + // bypass low memory intensity thread + + // bypass if system is lightly load + if (totalMemoryRequests() <= 16 && totalMemoryRequests() > 0) //TODO how about buffer empty? + { + bypassRequests(); + } + else + { + batchFormation(); + if (isSJF) + { + selectSJF() + } + else + { + selectRR(); + } + } + } + else if (isSJF) + { + selectSJF() + } + else + { + selectRR(); + } + } +} + +void SMS::selectSJF() +{ + // find shorstest thread + unsigned int minThread = 1 + auto totalNumThreads = Configuration::getInstance().NumberOfTracePlayers; + for (auto threadID = 2; threadID <= totalNumThreads; threadID++) + { + if (memrequestcounter[Thread(threadID)] <= memrequestcounter[Thread(minThread)]) + { + minThread = threadID; + } + } + + // drain to bank buffers + std::deque requestPtrs = readybatches[Thread(minThread)]->getTransactions(); + for (auto intr = requestPtrs.begin(); intr != requestPtrs.end(); intr++) + { + Bank bank = DramExtension::getExtension(*intr).getBank(); + bankbuffer.emplace(bank, *intr); + } + requestPtrs.clear(); + + // reform the drained ready batch + // batchFormation(Thread(minThread)); +} + +void SMS::selectRR() +{ + static std::map::iterator next = readybatches.begin(); + + // drain to bank buffers + std::deque requestPtrs = (*next).second->getTransactions(); + for (auto intr = requestPtrs.begin(); intr != requestPtrs.end(); intr++) + { + Bank bank = DramExtension::getExtension(*intr).getBank(); + bankbuffer.emplace(bank, *intr); + } + requestPtrs.clear(); + + // reform the drained ready batch + // batchFormation((*next).first); + + // point to next pair + do + { + next++; + if (next == readybatches.end()) + { + next = readybatches.begin(); + } + } while ((*next).second->isEmpty()); +} + +bool SMS::existReadyBatch() +{ + for (auto& thread_readybatch : readybatches) + { + if (!thread_readybatch.second->isEmpty()) + { + return true; + } + } + return false; +} + +void SMS::batchFormation(Thread thread) +{ + if (!readybatches[thread]->isEmpty()) + { + SC_REPORT_FATAL("SMS", "Ready batch formation for non empty ready batch"); + } + else + { + while (!buffer[thread].empty() && readybatches[thread]->addTransaction(buffer[thread].front())) + { + buffer[thread].pop_front(); + } + } +} + +void SMS::bypassRequests() +{ + for(auto& thread_requests : buffer) + { + for(auto request = thread_requests.second.begin(); request != thread_requests.second.end(); request++) + { + Bank bank = DramExtension::getExtension(*request).getBank(); + bankbuffer[bank].emplace_back(request); + thread_requests.second.erase(request); + } + } +} diff --git a/DRAMSys/simulator/src/controller/scheduler/SMS.h b/DRAMSys/simulator/src/controller/scheduler/SMS.h index d6fde08a..9f871776 100644 --- a/DRAMSys/simulator/src/controller/scheduler/SMS.h +++ b/DRAMSys/simulator/src/controller/scheduler/SMS.h @@ -1,17 +1,31 @@ #ifndef SMS_H #define SMS_H +#include +#include +#include "sysc/utils/sc_report.h" #include "IScheduler.h" #include "../core/ControllerCore.h" #include "../core/configuration/Configuration.h" #include "../../common/dramExtension.h" +#define MIN_TOTAL_REQ 16 + using namespace std; class SMS: public sc_module, public IScheduler { public: - SMS(ControllerCore &controllerCore, unsigned int SJFprobability) : IScheduler(controllerCore), SJFprobability(SJFprobability){} + SMS(ControllerCore &controllerCore, unsigned int SJFprobability) : IScheduler(controllerCore), SJFprobability(SJFprobability) + { + // initialize memory request counter & memory request intensity for each thread + auto totalNumThreads = Configuration::getInstance().NumberOfTracePlayers; + for (auto threadID = 1; threadID <= totalNumThreads; threadID++) + { + memrequestcounter.emplace(Thread(threadID), 0); + memoryIntensity.emplace(Thread(threadID), 0); + } + } virtual ~SMS(){} virtual void schedule(gp *payload) override; virtual std::pair getNextRequest(Bank bank) override; @@ -19,8 +33,20 @@ public: private: std::map> buffer; std::map> bankbuffer; - + std::map readybatches; + std::map memrequestcounter; + std::map inFlightMemRequestCounter; + std::map memoryIntensity; unsigned int SJFprobability; + + void batchScheduler(); + unsigned int totalMemoryRequests(); + void batchFormation(); + void selectSJF(); + void selectRR(); + bool existReadyBatch(); + void batchFormation(Thread thread); + void bypassRequests(); }; #endif // SMS_H