modified rd/write grouper
This commit is contained in:
@@ -8,15 +8,15 @@ LIBS += -L/opt/systemc/lib-linux64 -lsystemc
|
||||
LIBS += -L/opt/boost/lib -lboost_filesystem -lboost_system
|
||||
LIBS += -L/opt/sqlite3/lib -lsqlite3
|
||||
LIBS += -lpthread
|
||||
#LIBS += -lxerces-c
|
||||
#LIBS += -L../src/common/third_party/DRAMPower/src/ -ldrampowerxml
|
||||
#LIBS += -L../src/common/third_party/DRAMPower/src/ -ldrampower
|
||||
LIBS += -L/opt/xerces/lib -lxerces-c
|
||||
LIBS += -L../src/common/third_party/DRAMPower/src/ -ldrampowerxml
|
||||
LIBS += -L../src/common/third_party/DRAMPower/src/ -ldrampower
|
||||
|
||||
INCLUDEPATH += /opt/systemc/include
|
||||
INCLUDEPATH += /opt/boost/include
|
||||
INCLUDEPATH += /opt/sqlite3/include
|
||||
#INCLUDEPATH += ../src/common/third_party/DRAMPower/src
|
||||
#INCLUDEPATH += ../src/common/third_party/DRAMPower/src/libdrampower
|
||||
INCLUDEPATH += ../src/common/third_party/DRAMPower/src
|
||||
INCLUDEPATH += ../src/common/third_party/DRAMPower/src/libdrampower
|
||||
|
||||
DEFINES += TIXML_USE_STL
|
||||
DEFINES += SC_INCLUDE_DYNAMIC_PROCESSES
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<memspec>
|
||||
<memconfig>
|
||||
<parameter id="bankwiseLogic" type="bool" value="1" />
|
||||
<parameter id="bankwiseLogic" type="bool" value="0" />
|
||||
<parameter id="openPagePolicy" type="bool" value="1" />
|
||||
<parameter id="adaptiveOpenPagePolicy" type="bool" value="0" />
|
||||
<parameter id="refreshAwareScheduling" type="bool" value="1" />
|
||||
@@ -9,7 +9,6 @@
|
||||
<parameter id="capsize" type="uint" value="5" />
|
||||
<parameter id="powerDownMode" type="string" value="Staggered" />
|
||||
<parameter id="powerDownTimeout" type="uint" value="100" />
|
||||
|
||||
<parameter id="databaseRecordingEnabled" type="bool" value="1" />
|
||||
<parameter id="databaseRecordingEnabled" type="bool" value="1" />
|
||||
</memconfig>
|
||||
</memspec>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
|
||||
<trace-setup id="media">
|
||||
<device clkMhz="800">chstone-sha_32.stl</device>
|
||||
<device clkMhz="800">mediabench-epic_32.stl</device>
|
||||
</trace-setup>
|
||||
|
||||
</trace-setups>
|
||||
|
||||
@@ -116,13 +116,10 @@ template<unsigned int BUSWIDTH>
|
||||
void Controller<BUSWIDTH>::buildScheduler()
|
||||
{
|
||||
string selectedScheduler = Configuration::getInstance().Scheduler;
|
||||
//selectedScheduler == "ReadWriteGrouper";
|
||||
|
||||
if (selectedScheduler == "FR_FCFS")
|
||||
{
|
||||
|
||||
//Scheduler* s = new FR_FCFS(*controllerCore, Configuration::getInstance().RefreshAwareScheduling,
|
||||
// Configuration::getInstance().AdaptiveOpenPagePolicy);
|
||||
//scheduler = new ReadWriteGrouper(s);
|
||||
scheduler = new FR_FCFS(*controllerCore, Configuration::getInstance().RefreshAwareScheduling,Configuration::getInstance().AdaptiveOpenPagePolicy);
|
||||
}
|
||||
else if (selectedScheduler == "PAR_BS")
|
||||
@@ -131,7 +128,13 @@ void Controller<BUSWIDTH>::buildScheduler()
|
||||
Configuration::getInstance().Capsize);
|
||||
}
|
||||
else if (selectedScheduler == "FIFO")
|
||||
{
|
||||
scheduler = new Fifo(*controllerCore);
|
||||
}
|
||||
else if (selectedScheduler == "ReadWriteGrouper")
|
||||
{
|
||||
scheduler = new ReadWriteGrouper(*controllerCore);
|
||||
}
|
||||
else
|
||||
reportFatal(name(), "unsupported scheduler: " + selectedScheduler);
|
||||
}
|
||||
|
||||
@@ -97,6 +97,19 @@ unsigned int FR_FCFS::getNumberOfQueuedPayloads()
|
||||
return numberOfQueuedPaylods;
|
||||
}
|
||||
|
||||
bool FR_FCFS::containsPayloadTragetingSameAddress(gp *payload)
|
||||
{
|
||||
Bank bank = DramExtension::getExtension(payload).getBank();
|
||||
Row row = DramExtension::getExtension(payload).getRow();
|
||||
|
||||
for(gp* bufferedPayload: buffer[bank])
|
||||
{
|
||||
if(DramExtension::getExtension(bufferedPayload).getRow() == row)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<gp*> FR_FCFS::findRowHits(Bank bank, Row row)
|
||||
{
|
||||
vector<gp*> found;
|
||||
|
||||
@@ -25,6 +25,8 @@ public:
|
||||
gp* popOldest(Bank bank);
|
||||
unsigned int getNumberOfQueuedPayloads();
|
||||
|
||||
//used by read/write grouper
|
||||
bool containsPayloadTragetingSameAddress(gp* payload);
|
||||
private:
|
||||
std::vector<gp*> findRowHits(Bank bank, Row row);
|
||||
std::map<Bank,std::list<gp*>> buffer;
|
||||
|
||||
@@ -6,130 +6,139 @@ namespace scheduler{
|
||||
using namespace tlm;
|
||||
using namespace std;
|
||||
|
||||
string ReadWriteGrouper::senderName = "ReadWriteGrouper";
|
||||
|
||||
ReadWriteGrouper::ReadWriteGrouper(Scheduler *scheduler):
|
||||
scheduler(scheduler), mode(Mode::read)
|
||||
ReadWriteGrouper::ReadWriteGrouper(core::ControllerCore& controllerCore): controllerCore(controllerCore)
|
||||
{
|
||||
printDebugMessage("In read mode");
|
||||
batches.push_back(shared_ptr<FR_FCFS>(new FR_FCFS(controllerCore,true,false)));
|
||||
batches.push_back(shared_ptr<FR_FCFS>(new FR_FCFS(controllerCore,true,false)));
|
||||
}
|
||||
|
||||
ReadWriteGrouper::~ReadWriteGrouper()
|
||||
{
|
||||
delete scheduler;
|
||||
|
||||
}
|
||||
|
||||
void ReadWriteGrouper::schedule(gp *payload)
|
||||
{
|
||||
tlm_command command = payload->get_command();
|
||||
printDebugMessage("Scheduling new payload");
|
||||
|
||||
if(batches.size() > 2)
|
||||
{
|
||||
if(command == TLM_READ_COMMAND)
|
||||
{
|
||||
if(schedulingReadCausesHazardWithQueuedWrite(payload))
|
||||
{
|
||||
printDebugMessage("Scheduling read causes hazard with queued write");
|
||||
batches.push_back(shared_ptr<FR_FCFS>(new FR_FCFS(controllerCore,true,false)));
|
||||
batches.push_back(shared_ptr<FR_FCFS>(new FR_FCFS(controllerCore,true,false)));
|
||||
}
|
||||
|
||||
getLatestReadBatch().schedule(payload);
|
||||
}
|
||||
else if(command == TLM_WRITE_COMMAND)
|
||||
{
|
||||
getLatestWriteBatch().schedule(payload);
|
||||
}
|
||||
}
|
||||
else if(batches.size() == 2)
|
||||
{
|
||||
if(command == TLM_READ_COMMAND)
|
||||
{
|
||||
if(getLatestReadBatch().hasPayloads() && schedulingReadCausesHazardWithQueuedWrite(payload))
|
||||
{
|
||||
printDebugMessage("Scheduling read causes hazard with queued write");
|
||||
batches.push_back(shared_ptr<FR_FCFS>(new FR_FCFS(controllerCore,true,false)));
|
||||
batches.push_back(shared_ptr<FR_FCFS>(new FR_FCFS(controllerCore,true,false)));
|
||||
}
|
||||
else if(!getLatestReadBatch().hasPayloads() && getLatestWriteBatch().hasPayloads())
|
||||
{
|
||||
batches.erase(batches.begin());
|
||||
batches.push_back(shared_ptr<FR_FCFS>(new FR_FCFS(controllerCore,true,false)));
|
||||
batches.push_back(shared_ptr<FR_FCFS>(new FR_FCFS(controllerCore,true,false)));
|
||||
}
|
||||
getLatestReadBatch().schedule(payload);
|
||||
|
||||
}
|
||||
else if(command == TLM_WRITE_COMMAND)
|
||||
{
|
||||
getLatestWriteBatch().schedule(payload);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sc_assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
gp *ReadWriteGrouper::getNextPayload()
|
||||
{
|
||||
if(batches.size() > 2)
|
||||
{
|
||||
return batches.front()->getNextPayload();
|
||||
}
|
||||
else if(batches.size() == 2)
|
||||
{
|
||||
if(getLatestReadBatch().hasPayloads())
|
||||
return getLatestReadBatch().getNextPayload();
|
||||
else if(getLatestWriteBatch().hasPayloads())
|
||||
return getLatestWriteBatch().getNextPayload();
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc_assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ReadWriteGrouper::removePayload(gp *payload)
|
||||
{
|
||||
scheduler->removePayload(payload);
|
||||
|
||||
//if scheduler is empty now
|
||||
if(!scheduler->hasPayloads())
|
||||
if(batches.size() > 2)
|
||||
{
|
||||
printDebugMessage("No more transactions in scheduler");
|
||||
|
||||
if((mode == Mode::read && !writeQueue.empty()) || mode == Mode::readToWrite)
|
||||
switchToWriteMode();
|
||||
batches.front()->removePayload(payload);
|
||||
if(!batches.front()->hasPayloads())
|
||||
batches.erase(batches.begin());
|
||||
}
|
||||
else if(batches.size() == 2)
|
||||
{
|
||||
if(payload->is_read())
|
||||
getLatestReadBatch().removePayload(payload);
|
||||
else
|
||||
switchToReadMode();
|
||||
getLatestWriteBatch().removePayload(payload);
|
||||
}
|
||||
}
|
||||
|
||||
void ReadWriteGrouper::schedule(gp *payload)
|
||||
{
|
||||
tlm_command command = payload->get_command();
|
||||
|
||||
//in read mode hazards could occur by letting a read pass a queued write
|
||||
if(mode == Mode::read)
|
||||
{
|
||||
if(command == TLM_READ_COMMAND)
|
||||
else
|
||||
{
|
||||
//if scheduling the read would cause a hazard switch to readToWriteMode and put the read into the readQueue
|
||||
if(schedulingReadCausesHazardWithQueuedWrite(payload))
|
||||
{
|
||||
switchToReadToWriteMode();
|
||||
readQueue.push_back(payload);
|
||||
}
|
||||
else
|
||||
scheduler->schedule(payload);
|
||||
}
|
||||
else if(command == TLM_WRITE_COMMAND)
|
||||
{
|
||||
writeQueue.push_back(payload);
|
||||
if(!scheduler->hasPayloads())
|
||||
//there are no reads in the scheduler, so switch directly to write mode
|
||||
switchToWriteMode();
|
||||
sc_assert(false);
|
||||
}
|
||||
}
|
||||
else if(mode == Mode::readToWrite)
|
||||
{
|
||||
if(command == TLM_READ_COMMAND)
|
||||
readQueue.push_back(payload);
|
||||
else if(command == TLM_WRITE_COMMAND)
|
||||
writeQueue.push_back(payload);
|
||||
}
|
||||
else if(mode == Mode::write)
|
||||
{
|
||||
if(command == TLM_READ_COMMAND)
|
||||
readQueue.push_back(payload);
|
||||
else if(command == TLM_WRITE_COMMAND)
|
||||
scheduler->schedule(payload);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
gp *ReadWriteGrouper::getNextPayload()
|
||||
{
|
||||
return scheduler->getNextPayload();
|
||||
}
|
||||
|
||||
bool ReadWriteGrouper::hasPayloads()
|
||||
{
|
||||
return scheduler->hasPayloads();
|
||||
if(batches.size() > 2)
|
||||
return true;
|
||||
else if(batches.size() == 2)
|
||||
return (getLatestReadBatch().hasPayloads() || getLatestWriteBatch().hasPayloads());
|
||||
else
|
||||
sc_assert(false);
|
||||
}
|
||||
|
||||
|
||||
bool ReadWriteGrouper::schedulingReadCausesHazardWithQueuedWrite(gp *payload)
|
||||
{
|
||||
sc_assert(payload->is_read());
|
||||
for(gp* write: writeQueue)
|
||||
{
|
||||
if(payload->get_address()==write->get_address())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return getLatestWriteBatch().containsPayloadTragetingSameAddress(payload);
|
||||
}
|
||||
|
||||
void ReadWriteGrouper::switchToReadMode()
|
||||
FR_FCFS &ReadWriteGrouper::getLatestWriteBatch()
|
||||
{
|
||||
printDebugMessage("Switching to read mode");
|
||||
sc_assert(!scheduler->hasPayloads());
|
||||
mode = Mode::read;
|
||||
for(gp* read: readQueue)
|
||||
scheduler->schedule(read);
|
||||
readQueue.clear();
|
||||
return *batches[batches.size()-1];
|
||||
}
|
||||
|
||||
void ReadWriteGrouper::switchToWriteMode()
|
||||
FR_FCFS &ReadWriteGrouper::getLatestReadBatch()
|
||||
{
|
||||
printDebugMessage("Switching to write mode");
|
||||
sc_assert(!scheduler->hasPayloads());
|
||||
mode = Mode::write;
|
||||
for(gp* write: writeQueue)
|
||||
scheduler->schedule(write);
|
||||
writeQueue.clear();
|
||||
}
|
||||
|
||||
void ReadWriteGrouper::switchToReadToWriteMode()
|
||||
{
|
||||
printDebugMessage("Switching to read-to-write-mode");
|
||||
mode = Mode::readToWrite;
|
||||
}
|
||||
|
||||
void printDebugMessage(string message)
|
||||
{
|
||||
DebugManager::getInstance().printDebugMessage(ReadWriteGrouper::senderName, message);
|
||||
return *batches[batches.size()-2];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,40 +1,37 @@
|
||||
#ifndef READWRITEGROUPER_H
|
||||
#define READWRITEGROUPER_H
|
||||
#include "Scheduler.h"
|
||||
#include "Fr_Fcfs.h"
|
||||
#include "../core/ControllerCore.h"
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace scheduler{
|
||||
|
||||
/* Scheduler that batches reads and writes to reduce the overhead when switching from
|
||||
* read to write mode (read-to-write constraints)
|
||||
* The scheduler prioritizes reads. It switches to write mode, when stalling a write would induce a data-hazard
|
||||
* or when there are no reads to process.
|
||||
*/
|
||||
class ReadWriteGrouper : public Scheduler
|
||||
{
|
||||
public:
|
||||
ReadWriteGrouper(Scheduler *scheduler);
|
||||
ReadWriteGrouper(core::ControllerCore& controllerCore);
|
||||
~ReadWriteGrouper();
|
||||
virtual void schedule(gp* payload) override;
|
||||
virtual bool hasPayloads() override;
|
||||
virtual gp* getNextPayload() override;
|
||||
virtual void removePayload(gp* payload) override;
|
||||
|
||||
static std::string senderName;
|
||||
|
||||
private:
|
||||
Scheduler *scheduler;
|
||||
std::vector<gp*> readQueue, writeQueue;
|
||||
//Mode readToWrite is used to process the remaining reads in the readScheduler before
|
||||
//switching to write mode (this is used when a potential hazard causes the scheduler to switch modes)
|
||||
enum class Mode{read,readToWrite, write};
|
||||
Mode mode;
|
||||
// contains batches of requests
|
||||
// last element always contains writes
|
||||
// next-to-last element always contains reads
|
||||
// there are always at least two batches
|
||||
// if there are more than two batches, batches[0] is never empty and
|
||||
// getNextPayload and removePayload are forwarded to batches[0]
|
||||
std::vector<std::shared_ptr<FR_FCFS>> batches;
|
||||
core::ControllerCore& controllerCore;
|
||||
|
||||
bool schedulingReadCausesHazardWithQueuedWrite(gp* payload);
|
||||
void switchToReadMode();
|
||||
void switchToWriteMode();
|
||||
void switchToReadToWriteMode();
|
||||
void printDebugMessage(std::string message);
|
||||
FR_FCFS& getLatestWriteBatch();
|
||||
FR_FCFS& getLatestReadBatch();
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -52,7 +52,6 @@ void Simulation::setupDebugManager(const string& traceName)
|
||||
dbg.addToWhiteList(TlmRecorder::senderName);
|
||||
dbg.addToWhiteList(ControllerCore::senderName);
|
||||
dbg.addToWhiteList(PowerDownManagerBankwise::senderName);
|
||||
dbg.addToWhiteList(ReadWriteGrouper::senderName);
|
||||
|
||||
dbg.writeToConsole = true;
|
||||
dbg.writeToFile = true;
|
||||
|
||||
Reference in New Issue
Block a user