Files
DRAMSys/DRAMSys/simulator/src/controller/scheduler/SMS.cpp
Thanh C. Tran d974851c0e Small fix
2017-04-03 22:14:44 +02:00

184 lines
4.4 KiB
C++

#include "SMS.h"
#include <random>
using namespace std;
void SMS::schedule(gp *payload)
{
buffer[DramExtension::getExtension(payload).getThread()].emplace_back(payload);
inFlightMemRequestCounter[DramExtension::getExtension(payload).getThread()]++;
}
std::pair<Command, gp*> SMS::getNextRequest(Bank bank)
{
if (bankbuffer[bank].empty())
{
return pair<Command, tlm::tlm_generic_payload*>(Command::NOP, NULL);
}
else
{
gp* payload = bankbuffer[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()]--;
bankbuffer[bank].pop_front();
}
return pair<Command, tlm::tlm_generic_payload*>(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);
bool isSJF;
wait(150, SC_NS); // Test Purpose
while (true)
{
wait(memClk); //TODO: Is this correct???
isSJF = distribution(generator);
if (!existReadyBatch())
{
// pick & drain a ready batch
if (batchFormation())
{
isSJF ? selectSJF() : selectRR();
}
}
else
{
// pick & drain a ready batch
isSJF ? selectSJF() : selectRR();
}
}
}
bool SMS::batchFormation()
{
if (existReadyBatch())
{
return false;
SC_REPORT_FATAL("SMS", "Form ready batches when exist at least a ready batch");
}
else
{
bool isBatchForm = false;
bool isBatchFormForThread = false;
unsigned int totalNumThreads = Configuration::getInstance().NumberOfTracePlayers;
for (unsigned int threadID = 1; threadID <= totalNumThreads; threadID++)
{
isBatchFormForThread = batchFormation(Thread(threadID));
isBatchForm = isBatchForm || isBatchFormForThread;
}
return isBatchForm;
}
}
bool SMS::batchFormation(Thread thread)
{
if (!readybatches[thread]->isEmpty())
{
return false;
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();
}
return !readybatches[thread]->isEmpty();
}
}
void SMS::selectSJF()
{
// find shorstest thread
std::vector<Thread> threadsWithNonEmptyReadybatches;
for (auto& readybatch : readybatches)
{
if (!readybatch.second->isEmpty())
{
threadsWithNonEmptyReadybatches.push_back(readybatch.first);
}
}
if (!threadsWithNonEmptyReadybatches.empty())
{
Thread minThread = threadsWithNonEmptyReadybatches.front();
for (auto& thread : threadsWithNonEmptyReadybatches)
{
if (inFlightMemRequestCounter[thread] <= inFlightMemRequestCounter[minThread])
{
minThread = thread;
}
}
// drain to bank buffers
std::deque<gp*> &requestPtrs = readybatches[minThread]->getTransactions();
for (auto payloadPtrIterator = requestPtrs.begin(); payloadPtrIterator != requestPtrs.end(); payloadPtrIterator++)
{
Bank bank = DramExtension::getExtension(*payloadPtrIterator).getBank();
bankbuffer[bank].emplace_back(*payloadPtrIterator);
}
requestPtrs.clear();
// reform the drained ready batch
// batchFormation(Thread(minThread));
}
}
void SMS::selectRR()
{
static std::map<Thread, ReadyBatch*>::iterator next = readybatches.begin();
if (existReadyBatch())
{
while ((*next).second->isEmpty())
{
next++;
if (next == readybatches.end())
{
next = readybatches.begin();
}
}
// drain to bank buffers
std::deque<gp*> &requestPtrs = (*next).second->getTransactions();
for (auto payloadPtrIterator = requestPtrs.begin(); payloadPtrIterator != requestPtrs.end(); payloadPtrIterator++)
{
Bank bank = DramExtension::getExtension(*payloadPtrIterator).getBank();
bankbuffer[bank].emplace_back(*payloadPtrIterator);
}
requestPtrs.clear();
// reform the drained ready batch
// batchFormation((*next).first);
}
}
bool SMS::existReadyBatch()
{
for (auto& thread_readybatch : readybatches)
{
if (!thread_readybatch.second->isEmpty())
{
return true;
}
}
return false;
}