184 lines
4.4 KiB
C++
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;
|
|
}
|
|
|
|
|
|
|