1. Trying to drain request from empty request buffers & empty ready batch iterators
2. lastSelectedThread Iterator pointing to readybatchIters instead
This commit is contained in:
Thanh C. Tran
2017-06-01 02:24:05 +02:00
parent 6d739c64f1
commit ab2b87aaeb
3 changed files with 48 additions and 205 deletions

View File

@@ -12,10 +12,14 @@
<mcconfig src="sms.xml"/>
<tracesetup id="sms">
<device clkMhz="200">ddr3_example.stl</device>
<device clkMhz="200">sms_t1.stl</device>
<device clkMhz="200">sms_t2.stl</device>
<device clkMhz="200">sms_t3.stl</device>
<device clkMhz="200">sms_t4.stl</device>
<device clkMhz="200">stream.stl</device>
<device clkMhz="200">random.stl</device>
<device clkMhz="200">chstone-adpcm_32.stl</device>
</tracesetup>
</simulation>

View File

@@ -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<Thread> threadsWithNonEmptyRequestBuffer;
for (auto& requestBuffer : requestBuffers)
// find threads with ready batches
std::vector<Thread> 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<Thread> 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<gp*> &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<gp*>::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<gp*>::iterator last)
*/
bool SMS::pickRR()
{
std::map<Thread, std::deque<gp*>>::iterator nextSelectedThread;
if (lastSelectedThread == requestBuffers.end())
std::map<Thread, std::deque<gp_deque_iterator>>::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<Thread, std::deque<gp*>>::iterator savedOriginalNextSelectedThread = nextSelectedThread;
std::map<Thread, std::deque<gp_deque_iterator>>::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<Thread, std::deque<gp*>>::iterator nextSelectedThread;
if (lastSelectedThread == readybatches.end())
{
lastSelectedThread = readybatches.begin();
nextSelectedThread = lastSelectedThread;
}
else
{
nextSelectedThread = lastSelectedThread;
nextSelectedThread++;
if (nextSelectedThread == readybatches.end())
nextSelectedThread = readybatches.begin();
}
std::map<Thread, std::deque<gp*>>::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<gp*> &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<Thread, std::deque<gp*>> &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<Thread, std::deque<gp*>> &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<Thread, std::deque<gp*>>&)requestBuffer, requestBuffer.second.begin());
}
else
{
formed = batchFormation(memClk, (std::pair<Thread, std::deque<gp*>>&)requestBuffer, readyBatchesIter[requestBuffer.first].back() + 1);
formed = batchFormation(memClk, (std::pair<Thread, std::deque<gp*>>&)requestBuffer, readyBatchIters[requestBuffer.first].back() + 1);
}
} while (formed);
}

View File

@@ -20,6 +20,7 @@
#define REQUEST_BUFFER_SIZE 10
using namespace std;
typedef std::deque<gp*>::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<Thread, std::deque<gp*>> requestBuffers;
std::map<Bank, std::deque<gp*>> bankBuffers;
std::map<Thread, std::deque<gp*>> readybatches;
std::map<Thread, std::deque<std::deque<gp*>::iterator>> readyBatchesIter;
std::map<Thread, std::deque<gp_deque_iterator>> readyBatchIters;
std::map<Thread, unsigned int> inFlightMemRequestCounter;
std::map<Thread, unsigned int> cacheMisses;
std::map<Thread, float> MPKCs;
unsigned int SJFprobability;
std::map<Thread, std::deque<gp*>>::iterator lastSelectedThread;
std::map<Thread, std::deque<gp_deque_iterator>>::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<Thread, std::deque<gp*>> &requestBuffer, std::deque<gp*>::iterator beginIter);
void multiBatchFormation(sc_time memClk);
bool pickSJF();