Fix bug
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:
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user