Fix segmentation fault on wrong ranges

This commit is contained in:
Thanh C. Tran
2017-07-19 19:06:53 +02:00
parent 6c5fb579d4
commit 9ed0180895
2 changed files with 244 additions and 244 deletions

View File

@@ -5,72 +5,72 @@ using namespace std;
void SMS::schedule(gp *payload)
{
Thread thread = DramExtension::getExtension(payload).getThread();
bool wasEmpty = isRequestBuffersEmpty();
Thread thread = DramExtension::getExtension(payload).getThread();
bool wasEmpty = isRequestBuffersEmpty();
requestBuffers[thread].emplace_back(payload);
requestBuffers[thread].emplace_back(payload);
if (inFlightMemRequestCounter.find(thread) == inFlightMemRequestCounter.end()) {
inFlightMemRequestCounter[thread] = 0;
cacheMisses[thread] = 0;
}
inFlightMemRequestCounter[thread]++;
cacheMisses[thread]++;
if (inFlightMemRequestCounter.find(thread) == inFlightMemRequestCounter.end()) {
inFlightMemRequestCounter[thread] = 0;
cacheMisses[thread] = 0;
}
inFlightMemRequestCounter[thread]++;
cacheMisses[thread]++;
if (wasEmpty) {
newRequest.notify(SC_ZERO_TIME);
}
if (wasEmpty) {
newRequest.notify(SC_ZERO_TIME);
}
}
std::pair<Command, gp*> SMS::getNextRequest(Bank bank)
{
if (bankBuffers[bank].empty())
{
debugManager.printDebugMessage(name(),
"Get next request on bank " + to_string(bank.ID()) + " : EMPTY buffer");
return pair<Command, tlm::tlm_generic_payload*>(Command::NOP, NULL);
}
else
{
gp* payload = bankBuffers[bank].front();
Command command = IScheduler::getNextCommand(*payload);
if (command == Command::Read || command == Command::ReadA || command == Command::Write
|| command == Command::WriteA)
if (bankBuffers[bank].empty())
{
inFlightMemRequestCounter[DramExtension::getExtension(payload).getThread()]--;
bankBuffers[bank].pop_front();
debugManager.printDebugMessage(name(),
"Get next request on bank " + to_string(bank.ID()) + " : EMPTY buffer");
return pair<Command, tlm::tlm_generic_payload*>(Command::NOP, NULL);
}
else
{
gp* payload = bankBuffers[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()]--;
bankBuffers[bank].pop_front();
}
debugManager.printDebugMessage(name(), "Get next request on bank " + to_string(bank.ID()));
return pair<Command, tlm::tlm_generic_payload*>(command, payload);
}
debugManager.printDebugMessage(name(), "Get next request on bank " + to_string(bank.ID()));
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);
sc_time memClk = Configuration::getInstance().memSpec.clk;
std::default_random_engine generator;
std::bernoulli_distribution distribution((double) SJFprobability / 100.0);
while (true)
{
updateMPKCs(memClk);
if (isRequestBuffersEmpty()) {
wait(newRequest);
} else {
multiBatchFormation(memClk);
if (existReadyBatches()) {
if (!isSystemLightlyLoaded() && (existLowIntensityThread() || distribution(generator))) {
pickSJF();
while (true)
{
updateMPKCs(memClk);
if (isRequestBuffersEmpty()) {
wait(newRequest);
} else {
pickRR();
multiBatchFormation(memClk);
if (existReadyBatches()) {
if (!isSystemLightlyLoaded() && (existLowIntensityThread() || distribution(generator))) {
pickSJF();
} else {
pickRR();
}
drainOnePayloadFromReadybatch(memClk);
} else {
wait(memClk);
}
}
drainOnePayloadFromReadybatch(memClk);
} else {
wait(memClk);
}
}
}
}
/**
@@ -80,39 +80,39 @@ void SMS::batchScheduler()
*/
bool SMS::pickSJF()
{
// find threads with ready batches
std::vector<Thread> threadsWithReadyBatches;
for (const auto &each : readyBatchInclusiveEndLocs)
{
if (!each.second.empty())
// find threads with ready batches
std::vector<Thread> threadsWithReadyBatches;
for (const auto &each : readyBatchInclusiveEndLocs)
{
// marked as thread with non-empty request buffer
threadsWithReadyBatches.push_back(each.first);
}
}
if (!threadsWithReadyBatches.empty())
{
// pick shortest-job thread among threads with non-empty request buffer
Thread &minThread = threadsWithReadyBatches.front();
for (const auto &thread : threadsWithReadyBatches)
{
if (inFlightMemRequestCounter[thread] < inFlightMemRequestCounter[minThread])
{
minThread = thread;
}
if (!each.second.empty())
{
// marked as thread with non-empty request buffer
threadsWithReadyBatches.push_back(each.first);
}
}
// save selected thread
lastSelectedThread = readyBatchInclusiveEndLocs.find(minThread);
debugManager.printDebugMessage(name(),
"[SJF] Select ready batch of thread " + to_string(minThread.ID()));
return true;
}
else
{
return false;
}
if (!threadsWithReadyBatches.empty())
{
// pick shortest-job thread among threads with non-empty request buffer
Thread &minThread = threadsWithReadyBatches.front();
for (const auto &thread : threadsWithReadyBatches)
{
if (inFlightMemRequestCounter[thread] < inFlightMemRequestCounter[minThread])
{
minThread = thread;
}
}
// save selected thread
lastSelectedThread = readyBatchInclusiveEndLocs.find(minThread);
debugManager.printDebugMessage(name(),
"[SJF] Select ready batch of thread " + to_string(minThread.ID()));
return true;
}
else
{
return false;
}
}
/**
@@ -123,34 +123,34 @@ bool SMS::pickSJF()
*/
void SMS::drainOnePayloadFromReadybatch(const sc_time &memClk)
{
if (lastSelectedThread->second.empty()) {
if (lastSelectedThread->second.empty()) {
return;
}
const Thread &selectedThread = lastSelectedThread->first;
const size_t &inclusiveEndLoc = lastSelectedThread->second.front();
assert(inclusiveEndLoc < requestBuffers.size());
for (size_t i = 0; i <= inclusiveEndLoc; ++i)
{
wait(memClk);
Bank bank = DramExtension::getExtension(requestBuffers[selectedThread].front()).getBank();
bankBuffers[bank].emplace_back(requestBuffers[selectedThread].front());
requestBuffers[selectedThread].pop_front();
// decrement inclusive end locations of ready batches
// except this ready batch
for (size_t i = 1; i < readyBatchInclusiveEndLocs.size(); ++i)
{
--readyBatchInclusiveEndLocs[selectedThread][i];
}
const Thread &selectedThread = lastSelectedThread->first;
debugManager.printDebugMessage(name(),
"[SJF] Drain request in the ready batch of thread "
+ to_string((*lastSelectedThread).first.ID()) + " to bankbuffer "
+ to_string(bank.ID()));
}
lastSelectedThread->second.pop_front();
const size_t &inclusiveEndLoc = lastSelectedThread->second.front();
assert(inclusiveEndLoc < requestBuffers.size());
for (size_t i = 0; i <= inclusiveEndLoc; ++i)
{
wait(memClk);
Bank bank = DramExtension::getExtension(requestBuffers[selectedThread].front()).getBank();
bankBuffers[bank].emplace_back(requestBuffers[selectedThread].front());
requestBuffers[selectedThread].pop_front();
// decrement inclusive end locations of ready batches
// except this ready batch
for (size_t i = 1; i < readyBatchInclusiveEndLocs[selectedThread].size(); ++i)
{
--readyBatchInclusiveEndLocs[selectedThread][i];
}
debugManager.printDebugMessage(name(),
"[SJF] Drain request in the ready batch of thread "
+ to_string((*lastSelectedThread).first.ID()) + " to bankbuffer "
+ to_string(bank.ID()));
}
lastSelectedThread->second.pop_front();
}
/**
@@ -162,105 +162,105 @@ bool SMS::pickRR()
{
if (lastSelectedThread == readyBatchInclusiveEndLocs.end())
{
lastSelectedThread = readyBatchInclusiveEndLocs.begin();
if (!(*lastSelectedThread).second.empty()) {
return true;
}
lastSelectedThread = readyBatchInclusiveEndLocs.begin();
if (!(*lastSelectedThread).second.empty()) {
return true;
}
}
std::map<Thread, std::deque<size_t>>::iterator savedOriginalNextSelectedThread = lastSelectedThread;
do
{
lastSelectedThread++;
if (lastSelectedThread == readyBatchInclusiveEndLocs.end()) {
lastSelectedThread = readyBatchInclusiveEndLocs.begin();
}
if (lastSelectedThread == savedOriginalNextSelectedThread) {
return false;
}
lastSelectedThread++;
if (lastSelectedThread == readyBatchInclusiveEndLocs.end()) {
lastSelectedThread = readyBatchInclusiveEndLocs.begin();
}
if (lastSelectedThread == savedOriginalNextSelectedThread) {
return false;
}
} while ((*lastSelectedThread).second.empty());
debugManager.printDebugMessage(name(),
"[RR] Select ready batch of thread " + to_string((*lastSelectedThread).first.ID()));
"[RR] Select ready batch of thread " + to_string((*lastSelectedThread).first.ID()));
return true;
}
bool SMS::isSystemLightlyLoaded() const {
unsigned int totalRequest = 0;
for (const auto &bankBuffer : bankBuffers) {
totalRequest += bankBuffer.second.size();
}
return (totalRequest <= LOW_SYSTEM_LOAD);
unsigned int totalRequest = 0;
for (const auto &bankBuffer : bankBuffers) {
totalRequest += bankBuffer.second.size();
}
return (totalRequest <= LOW_SYSTEM_LOAD);
}
bool SMS::existLowIntensityThread() const {
for (const auto &mpkcPerThread : MPKCs) {
if (mpkcPerThread.second < LOW_MPKC) {
return true;
for (const auto &mpkcPerThread : MPKCs) {
if (mpkcPerThread.second < LOW_MPKC) {
return true;
}
}
}
return false;
return false;
}
bool SMS::isThresholdAgeExceeded(const Thread &thread, sc_time const &memClk, size_t const &inclusiveBeginLoc, size_t const &exclusiveEndLoc) {
assert((exclusiveEndLoc - inclusiveBeginLoc) >= 1);
// find the oldest request in the thread's batch
sc_time oldestGenerationTime = sc_time_stamp();
for (size_t i = inclusiveBeginLoc; i != exclusiveEndLoc; ++i) {
sc_time reqGenerationTime = GenerationExtension::getExtension(requestBuffers[thread][i]).TimeOfGeneration();
if (reqGenerationTime < oldestGenerationTime) {
oldestGenerationTime = reqGenerationTime;
assert((exclusiveEndLoc - inclusiveBeginLoc) >= 1);
// find the oldest request in the thread's batch
sc_time oldestGenerationTime = sc_time_stamp();
for (size_t i = inclusiveBeginLoc; i != exclusiveEndLoc; ++i) {
sc_time reqGenerationTime = GenerationExtension::getExtension(requestBuffers[thread][i]).TimeOfGeneration();
if (reqGenerationTime < oldestGenerationTime) {
oldestGenerationTime = reqGenerationTime;
}
}
}
// check threshold age according to the thread's MPKC
sc_time oldestRequestAge = sc_time_stamp() - oldestGenerationTime;
if ((MPKCs[thread] <= MEDIUM_MPKC) && (oldestRequestAge > (MEDIUM_THRESHOLD_AGE * memClk))) {
return true;
} else if ((MPKCs[thread] > MEDIUM_MPKC) && (oldestRequestAge > (HIGH_THRESHOLD_AGE * memClk))) {
return true;
} else {
return false;
}
// check threshold age according to the thread's MPKC
sc_time oldestRequestAge = sc_time_stamp() - oldestGenerationTime;
if ((MPKCs[thread] <= MEDIUM_MPKC) && (oldestRequestAge > (MEDIUM_THRESHOLD_AGE * memClk))) {
return true;
} else if ((MPKCs[thread] > MEDIUM_MPKC) && (oldestRequestAge > (HIGH_THRESHOLD_AGE * memClk))) {
return true;
} else {
return false;
}
}
void SMS::updateMPKCs(sc_time const &memClk) {
if (sc_time_stamp() % (MPKC_RESET_CYCLE * memClk) <= memClk) {
// reset for every 10k clk cycles
for (const auto &cacheMiss : cacheMisses) {
MPKCs[cacheMiss.first] = 0;
if (sc_time_stamp() % (MPKC_RESET_CYCLE * memClk) <= memClk) {
// reset for every 10k clk cycles
for (const auto &cacheMiss : cacheMisses) {
MPKCs[cacheMiss.first] = 0;
}
debugManager.printDebugMessage(name(), "Reset MKKCs");
} else {
// update MPKC for every thread
for (const auto &cacheMiss : cacheMisses) {
MPKCs[cacheMiss.first] = (cacheMiss.second * 1000.0 * memClk) / (sc_time_stamp());
}
debugManager.printDebugMessage(name(), "Update MPKCs");
}
debugManager.printDebugMessage(name(), "Reset MKKCs");
} else {
// update MPKC for every thread
for (const auto &cacheMiss : cacheMisses) {
MPKCs[cacheMiss.first] = (cacheMiss.second * 1000.0 * memClk) / (sc_time_stamp());
}
debugManager.printDebugMessage(name(), "Update MPKCs");
}
}
bool SMS::isExceededReqBufferSize(size_t const &exclusiveEndLoc) {
return exclusiveEndLoc <= Configuration::getInstance().RequestBufferSize;
return exclusiveEndLoc <= Configuration::getInstance().RequestBufferSize;
}
bool SMS::isRequestBuffersEmpty() const {
for (const auto &requestBuffer : requestBuffers) {
if (!requestBuffer.second.empty()) {
return false;
for (const auto &requestBuffer : requestBuffers) {
if (!requestBuffer.second.empty()) {
return false;
}
}
}
return true;
return true;
}
bool SMS::existReadyBatches() const {
for (const auto &each : readyBatchInclusiveEndLocs) {
if (!each.second.empty()) {
return true;
for (const auto &each : readyBatchInclusiveEndLocs) {
if (!each.second.empty()) {
return true;
}
}
}
return false;
return false;
}
/**
@@ -272,98 +272,98 @@ bool SMS::existReadyBatches() const {
*/
bool SMS::batchFormation(sc_time const &memClk, Thread const &thread, std::deque<gp*> const &requestBuffer, size_t const &inclusiveBeginLoc)
{
if (requestBuffer.empty())
{
return false;
}
assert(inclusiveBeginLoc <= requestBuffer.size());
if (requestBuffer.size() == inclusiveBeginLoc)
{
return false;
}
if (MPKCs[thread] < LOW_MPKC || isSystemLightlyLoaded())
{
// bypass requests by forming batch with only one request (threshold age is ZERO)
readyBatchInclusiveEndLocs[thread].push_back(inclusiveBeginLoc);
return true;
}
else
{
// forming batch with FIFO size & threshold age constraints
size_t firstDifferentRowAccessReqLoc = inclusiveBeginLoc;
Row firstRow = DramExtension::getRow(requestBuffer[inclusiveBeginLoc]);
bool isBatchReady = false;
size_t bufferSize = requestBuffer.size();
while (firstDifferentRowAccessReqLoc != bufferSize
&& DramExtension::getRow(requestBuffer[firstDifferentRowAccessReqLoc]) == firstRow)
if (requestBuffer.empty())
{
++firstDifferentRowAccessReqLoc;
if (firstDifferentRowAccessReqLoc < bufferSize)
{
if (DramExtension::getRow(requestBuffer[firstDifferentRowAccessReqLoc]) != firstRow
|| isExceededReqBufferSize(firstDifferentRowAccessReqLoc)
|| isThresholdAgeExceeded(thread, memClk, inclusiveBeginLoc, firstDifferentRowAccessReqLoc))
{
isBatchReady = true;
break;
}
}
else
{
if (isExceededReqBufferSize(firstDifferentRowAccessReqLoc)
|| isThresholdAgeExceeded(thread, memClk, inclusiveBeginLoc, firstDifferentRowAccessReqLoc))
{
isBatchReady = true;
break;
}
}
return false;
}
// store this ready batch location
if (isBatchReady)
assert(inclusiveBeginLoc <= requestBuffer.size());
if (requestBuffer.size() == inclusiveBeginLoc)
{
--firstDifferentRowAccessReqLoc;
readyBatchInclusiveEndLocs[thread].push_back(firstDifferentRowAccessReqLoc);
debugManager.printDebugMessage(name(),
"Deem batch ready - thread " + to_string(thread.ID()));
return true;
return false;
}
if (MPKCs[thread] < LOW_MPKC || isSystemLightlyLoaded())
{
// bypass requests by forming batch with only one request (threshold age is ZERO)
readyBatchInclusiveEndLocs[thread].push_back(inclusiveBeginLoc);
return true;
}
else
{
return false;
// forming batch with FIFO size & threshold age constraints
size_t firstDifferentRowAccessReqLoc = inclusiveBeginLoc;
Row firstRow = DramExtension::getRow(requestBuffer[inclusiveBeginLoc]);
bool isBatchReady = false;
size_t bufferSize = requestBuffer.size();
while (firstDifferentRowAccessReqLoc != bufferSize
&& DramExtension::getRow(requestBuffer[firstDifferentRowAccessReqLoc]) == firstRow)
{
++firstDifferentRowAccessReqLoc;
if (firstDifferentRowAccessReqLoc < bufferSize)
{
if (DramExtension::getRow(requestBuffer[firstDifferentRowAccessReqLoc]) != firstRow
|| isExceededReqBufferSize(firstDifferentRowAccessReqLoc)
|| isThresholdAgeExceeded(thread, memClk, inclusiveBeginLoc, firstDifferentRowAccessReqLoc))
{
isBatchReady = true;
break;
}
}
else
{
if (isExceededReqBufferSize(firstDifferentRowAccessReqLoc)
|| isThresholdAgeExceeded(thread, memClk, inclusiveBeginLoc, firstDifferentRowAccessReqLoc))
{
isBatchReady = true;
break;
}
}
}
// store this ready batch location
if (isBatchReady)
{
--firstDifferentRowAccessReqLoc;
readyBatchInclusiveEndLocs[thread].push_back(firstDifferentRowAccessReqLoc);
debugManager.printDebugMessage(name(),
"Deem batch ready - thread " + to_string(thread.ID()));
return true;
}
else
{
return false;
}
}
}
}
void SMS::multiBatchFormation(sc_time const &memClk)
{
for (auto &requestBuffer : requestBuffers)
{
bool formed = false;
do
for (auto &requestBuffer : requestBuffers)
{
if (readyBatchInclusiveEndLocs[requestBuffer.first].empty())
{
formed = batchFormation(memClk, requestBuffer.first, requestBuffer.second, 0);
}
else
{
formed = batchFormation(memClk, requestBuffer.first, requestBuffer.second, readyBatchInclusiveEndLocs[requestBuffer.first].back() + 1);
}
} while (!requestBuffer.second.empty() && formed);
}
bool formed = false;
do
{
if (readyBatchInclusiveEndLocs[requestBuffer.first].empty())
{
formed = batchFormation(memClk, requestBuffer.first, requestBuffer.second, 0);
}
else
{
formed = batchFormation(memClk, requestBuffer.first, requestBuffer.second, readyBatchInclusiveEndLocs[requestBuffer.first].back() + 1);
}
} while (!requestBuffer.second.empty() && formed);
}
}
gp* SMS::getPendingRequest(Bank bank)
{
for (const auto &requestBuffer : requestBuffers) {
for (const auto &request : requestBuffer.second) {
if (DramExtension::getBank(request) == bank) {
return request;
}
for (const auto &requestBuffer : requestBuffers) {
for (const auto &request : requestBuffer.second) {
if (DramExtension::getBank(request) == bank) {
return request;
}
}
}
}
return NULL;
return NULL;
}

View File

@@ -34,9 +34,9 @@ class SMS: public sc_module, public IScheduler
public:
SMS(sc_module_name /*_name*/, ControllerCore &controllerCore, unsigned int SJFprobability) : IScheduler(controllerCore), SJFprobability(SJFprobability), debugManager(DebugManager::getInstance())
{
// initialize selected thread iterator
lastSelectedThread = readyBatchInclusiveEndLocs.end();
SC_THREAD(batchScheduler);
// initialize selected thread iterator
lastSelectedThread = readyBatchInclusiveEndLocs.end();
SC_THREAD(batchScheduler);
}
SC_HAS_PROCESS(SMS);