diff --git a/dram/dramSys/dramSys.pro b/dram/dramSys/dramSys.pro
index 8672da99..65291f71 100644
--- a/dram/dramSys/dramSys.pro
+++ b/dram/dramSys/dramSys.pro
@@ -57,7 +57,8 @@ SOURCES += \
../src/simulation/main.cpp \
../src/common/libDRAMPower.cpp \
../src/controller/core/RowBufferStates.cpp \
- ../src/controller/scheduler/Scheduler.cpp
+ ../src/controller/scheduler/Scheduler.cpp \
+ ../src/controller/scheduler/readwritegrouper.cpp
HEADERS += \
../src/common/third_party/tinyxml2.h \
@@ -112,6 +113,7 @@ HEADERS += \
../src/simulation/Dram.h \
../src/simulation/Arbiter.h \
../src/common/libDRAMPower.h \
- ../src/controller/core/RowBufferStates.h
+ ../src/controller/core/RowBufferStates.h \
+ ../src/controller/scheduler/readwritegrouper.h
diff --git a/dram/resources/configs/memconfigs/fifo.xml b/dram/resources/configs/memconfigs/fifo.xml
index 3bf15c45..2e23e330 100644
--- a/dram/resources/configs/memconfigs/fifo.xml
+++ b/dram/resources/configs/memconfigs/fifo.xml
@@ -10,6 +10,6 @@
-
+
diff --git a/dram/resources/configs/memconfigs/fr_fcfs.xml b/dram/resources/configs/memconfigs/fr_fcfs.xml
index a57c0e84..b126adb1 100644
--- a/dram/resources/configs/memconfigs/fr_fcfs.xml
+++ b/dram/resources/configs/memconfigs/fr_fcfs.xml
@@ -10,6 +10,6 @@
-
+
diff --git a/dram/src/common/TlmRecorder.cpp b/dram/src/common/TlmRecorder.cpp
index 56c2cee6..1b69b89a 100644
--- a/dram/src/common/TlmRecorder.cpp
+++ b/dram/src/common/TlmRecorder.cpp
@@ -17,7 +17,7 @@ bool TlmRecorder::recordingEnabled = true;
// ------------- public -----------------------
TlmRecorder::TlmRecorder() :
- transactionIDCounter(1), recordingEndTime(SC_ZERO_TIME)
+ totalNumTransactions(1), simulationTimeCoveredByRecording(SC_ZERO_TIME)
{
if(recordingEnabled)
{
@@ -73,7 +73,7 @@ void TlmRecorder::recordPhase(tlm::tlm_generic_payload& trans, tlm::tlm_phase ph
if (phaseTerminatesTransaction)
removeTransactionFromSystem(trans);
- recordingEndTime = time;
+ simulationTimeCoveredByRecording = time;
}
}
@@ -100,7 +100,7 @@ void TlmRecorder::recordDebugMessage(std::string message, sc_time time)
void TlmRecorder::introduceTransactionSystem(tlm::tlm_generic_payload& trans)
{
- unsigned int id = transactionIDCounter++;
+ unsigned int id = totalNumTransactions++;
currentTransactionsInSystem[&trans].id = id;
currentTransactionsInSystem[&trans].address = trans.get_address();
currentTransactionsInSystem[&trans].burstlength = trans.get_streaming_width();
@@ -124,7 +124,7 @@ void TlmRecorder::removeTransactionFromSystem(tlm::tlm_generic_payload& trans)
{
assert(currentTransactionsInSystem.count(&trans) != 0);
- RecordingData& recordingData = currentTransactionsInSystem[&trans];
+ Transaction& recordingData = currentTransactionsInSystem[&trans];
recordedData.push_back(recordingData);
currentTransactionsInSystem.erase(&trans);
}
@@ -132,11 +132,11 @@ void TlmRecorder::removeTransactionFromSystem(tlm::tlm_generic_payload& trans)
void TlmRecorder::commitRecordedDataToDB()
{
sqlite3_exec(db, "BEGIN;", 0, 0, 0);
- for(RecordingData& recordingData: recordedData)
+ for(Transaction& recordingData: recordedData)
{
assert(recordingData.recordedPhases.size() > 0);
insertTransactionInDB(recordingData);
- for(RecordingData::PhaseData& phaseData: recordingData.recordedPhases)
+ for(Transaction::Phase& phaseData: recordingData.recordedPhases)
{
insertPhaseInDB(phaseData.name,phaseData.interval.start,phaseData.interval.end,recordingData.id);
}
@@ -151,14 +151,14 @@ void TlmRecorder::commitRecordedDataToDB()
}
-void TlmRecorder::RecordingData::insertPhase(string name, sc_time begin)
+void TlmRecorder::Transaction::insertPhase(string name, sc_time begin)
{
- recordedPhases.push_back(PhaseData(name,begin));
+ recordedPhases.push_back(Phase(name,begin));
}
-void TlmRecorder::RecordingData::setPhaseEnd(string name, sc_time end)
+void TlmRecorder::Transaction::setPhaseEnd(string name, sc_time end)
{
- for(PhaseData& data: recordedPhases)
+ for(Phase& data: recordedPhases)
{
if(data.name == name)
{
@@ -233,8 +233,8 @@ void TlmRecorder::insertDebugMessageInDB(string message, const sc_time& time)
void TlmRecorder::insertGeneralInfo()
{
- sqlite3_bind_int64(insertGeneralInfoStatement, 1, transactionIDCounter - 1);
- sqlite3_bind_int64(insertGeneralInfoStatement, 2, recordingEndTime.value());
+ sqlite3_bind_int64(insertGeneralInfoStatement, 1, totalNumTransactions - 1);
+ sqlite3_bind_int64(insertGeneralInfoStatement, 2, simulationTimeCoveredByRecording.value());
sqlite3_bind_int(insertGeneralInfoStatement, 3,
core::Configuration::getInstance().NumberOfBanks);
sqlite3_bind_int(insertGeneralInfoStatement, 4, core::Configuration::getInstance().Timings.clk.value());
@@ -245,7 +245,7 @@ void TlmRecorder::insertGeneralInfo()
executeSqlStatement(insertGeneralInfoStatement);
}
-void TlmRecorder::insertTransactionInDB(RecordingData& recordingData)
+void TlmRecorder::insertTransactionInDB(Transaction& recordingData)
{
sqlite3_bind_int(insertTransactionStatement, 1, recordingData.id);
sqlite3_bind_int(insertTransactionStatement, 2, recordingData.id);
@@ -319,7 +319,7 @@ void TlmRecorder::closeConnection()
commitRecordedDataToDB();
insertGeneralInfo();
printDebugMessage(
- "Number of transactions written to DB: " + std::to_string(transactionIDCounter - 1));
+ "Number of transactions written to DB: " + std::to_string(totalNumTransactions - 1));
printDebugMessage("tlmPhaseRecorder:\tEnd Recording");
sqlite3_close(db);
db = NULL;
diff --git a/dram/src/common/TlmRecorder.h b/dram/src/common/TlmRecorder.h
index 3a4e83bf..e832e744 100755
--- a/dram/src/common/TlmRecorder.h
+++ b/dram/src/common/TlmRecorder.h
@@ -43,10 +43,10 @@ public:
private:
- struct RecordingData
+ struct Transaction
{
- RecordingData(){}
- RecordingData(unsigned int id):id(id){}
+ Transaction(){}
+ Transaction(unsigned int id):id(id){}
unsigned int id;
unsigned int address;
@@ -55,13 +55,13 @@ private:
sc_time timeOfGeneration;
TimeInterval timeOnDataStrobe;
- struct PhaseData
+ struct Phase
{
- PhaseData(string name,sc_time begin): name(name), interval(begin,SC_ZERO_TIME){}
+ Phase(string name,sc_time begin): name(name), interval(begin,SC_ZERO_TIME){}
string name;
TimeInterval interval;
};
- std::vector recordedPhases;
+ std::vector recordedPhases;
void insertPhase(string name,sc_time begin);
void setPhaseEnd(string name,sc_time end);
@@ -85,7 +85,7 @@ private:
void commitRecordedDataToDB();
void insertGeneralInfo();
- void insertTransactionInDB(RecordingData& recordingData);
+ void insertTransactionInDB(Transaction& recordingData);
void insertRangeInDB(unsigned int id, const sc_time& begin, const sc_time& end);
void insertPhaseInDB(string phaseName, const sc_time& begin, const sc_time& end, unsigned int transactionID);
void insertDebugMessageInDB(string message, const sc_time& time);
@@ -93,11 +93,11 @@ private:
void printDebugMessage(std::string message);
static const int transactionCommitRate = 1000;
- vector recordedData;
- map currentTransactionsInSystem;
+ vector recordedData;
+ map currentTransactionsInSystem;
- unsigned int transactionIDCounter;
- sc_time recordingEndTime;
+ unsigned int totalNumTransactions;
+ sc_time simulationTimeCoveredByRecording;
std::vector transactionTerminatingPhases;
sqlite3 *db;
diff --git a/dram/src/common/Utils.h b/dram/src/common/Utils.h
index c13aab22..acb5b93b 100644
--- a/dram/src/common/Utils.h
+++ b/dram/src/common/Utils.h
@@ -19,6 +19,7 @@
//TODO : move to timing specific header
sc_time getDistance(sc_time a, sc_time b);
+
struct TimeInterval
{
sc_time start,end;
diff --git a/dram/src/common/dramExtension.cpp b/dram/src/common/dramExtension.cpp
index a3ac2202..8b9d34d3 100644
--- a/dram/src/common/dramExtension.cpp
+++ b/dram/src/common/dramExtension.cpp
@@ -5,9 +5,22 @@
using namespace tlm;
-/* Static methods
- *
- */
+
+DramExtension::DramExtension() :
+ thread(0), channel(0), bank(0), bankgroup(0), row(0), column(0), burstlength(0)
+{
+}
+
+DramExtension::DramExtension(const Thread &thread, const Bank &bank, const BankGroup &bankgroup, const Row &row, const Column &column, unsigned int burstlength) :
+ thread(thread), channel(0), bank(bank), bankgroup(bankgroup), row(row), column(column), burstlength(burstlength)
+{
+}
+
+DramExtension::DramExtension(const Thread &thread, const Channel &channel, const Bank &bank, const BankGroup &bankgroup, const Row &row, const Column &column, unsigned int burstlength) :
+ thread(thread), channel(channel), bank(bank), bankgroup(bankgroup), row(row), column(column), burstlength(burstlength)
+{
+}
+
DramExtension& DramExtension::getExtension(const tlm_generic_payload *payload)
{
DramExtension *result = NULL;
@@ -22,108 +35,12 @@ DramExtension& DramExtension::getExtension(const tlm_generic_payload &payload)
return DramExtension::getExtension(&payload);
}
-bool operator ==(const Thread& lhs, const Thread& rhs)
-{
- return lhs.ID() == rhs.ID();
-}
-
-bool operator !=(const Thread& lhs, const Thread& rhs)
-{
- return !(lhs == rhs);
-}
-
-bool operator <(const Thread& lhs, const Thread& rhs)
-{
- return lhs.ID() < rhs.ID();
-}
-
-bool operator ==(const Channel& lhs, const Channel& rhs)
-{
- return lhs.ID() == rhs.ID();
-}
-
-bool operator !=(const Channel& lhs, const Channel& rhs)
-{
- return !(lhs == rhs);
-}
-
-BankGroup Bank::getBankGroup()
-{
- static std::map bankgroups;
- if (bankgroups.size() == 0)
- {
- core::Configuration& config = core::Configuration::getInstance();
- sc_assert(config.NumberOfBanks % config.NumberOfBankGroups == 0);
-
- for (unsigned int bank = 0; bank < config.NumberOfBanks; bank++)
- {
- unsigned int group = bank % config.NumberOfBankGroups;
- bankgroups.insert(std::pair(Bank(bank), BankGroup(group)));
- }
- }
-
- return getElementFromMap(bankgroups, *this);
-}
-
-bool operator ==(const Bank& lhs, const Bank& rhs)
-{
- return lhs.ID() == rhs.ID();
-}
-
-bool operator !=(const Bank& lhs, const Bank& rhs)
-{
- return !(lhs == rhs);
-}
-
-bool operator ==(const BankGroup& lhs, const BankGroup& rhs)
-{
- return lhs.ID() == rhs.ID();
-}
-
-bool operator !=(const BankGroup& lhs, const BankGroup& rhs)
-{
- return !(lhs == rhs);
-}
-
-bool operator <(const Bank& lhs, const Bank& rhs)
-{
- return lhs.ID() < rhs.ID();
-}
-
-const Row Row::NO_ROW;
-
-const Row Row::operator ++()
-{
- id = (id + 1) % core::Configuration::getInstance().NumberOfRows;
- return *this;
-}
-
-bool operator ==(const Row& lhs, const Row& rhs)
-{
- if (lhs.isNoRow != rhs.isNoRow)
- return false;
- return lhs.ID() == rhs.ID();
-}
-
-bool operator !=(const Row& lhs, const Row& rhs)
-{
- return !(lhs == rhs);
-}
-
-bool operator ==(const Column& lhs, const Column& rhs)
-{
- return lhs.ID() == rhs.ID();
-}
-
-bool operator !=(const Column& lhs, const Column& rhs)
-{
- return !(lhs == rhs);
-}
tlm_extension_base* DramExtension::clone() const
{
return new DramExtension(thread, bank, bankgroup, row, column, burstlength);
}
+
void DramExtension::copy_from(const tlm_extension_base& ext)
{
const DramExtension& cpyFrom = static_cast(ext);
@@ -135,29 +52,32 @@ void DramExtension::copy_from(const tlm_extension_base& ext)
burstlength = cpyFrom.burstlength;
}
-const Thread& DramExtension::getThread() const
+Thread DramExtension::getThread() const
{
return thread;
}
-const Channel& DramExtension::getChannel() const
+
+Channel DramExtension::getChannel() const
{
return channel;
}
-const Bank& DramExtension::getBank() const
+
+Bank DramExtension::getBank() const
{
return bank;
}
-const BankGroup& DramExtension::getBankGroup() const
+
+BankGroup DramExtension::getBankGroup() const
{
return bankgroup;
}
-const Row& DramExtension::getRow() const
+Row DramExtension::getRow() const
{
return row;
}
-const Column& DramExtension::getColumn() const
+Column DramExtension::getColumn() const
{
return column;
}
@@ -167,7 +87,7 @@ unsigned int DramExtension::getBurstlength() const
return burstlength;
}
-void DramExtension::increaseRow()
+void DramExtension::incrementRow()
{
++row;
}
@@ -191,3 +111,112 @@ GenerationExtension& GenerationExtension::getExtension(const tlm::tlm_generic_pa
sc_assert(result!=NULL);
return *result;
}
+
+
+//TODO remove this nonsense, put it in xml
+BankGroup Bank::getBankGroup()
+{
+ static std::map bankgroups;
+ if (bankgroups.size() == 0)
+ {
+ core::Configuration& config = core::Configuration::getInstance();
+ sc_assert(config.NumberOfBanks % config.NumberOfBankGroups == 0);
+
+ for (unsigned int bank = 0; bank < config.NumberOfBanks; bank++)
+ {
+ unsigned int group = bank % config.NumberOfBankGroups;
+ bankgroups.insert(std::pair(Bank(bank), BankGroup(group)));
+ }
+ }
+
+ return getElementFromMap(bankgroups, *this);
+}
+
+
+//THREAD
+bool operator ==(const Thread& lhs, const Thread& rhs)
+{
+ return lhs.ID() == rhs.ID();
+}
+
+bool operator !=(const Thread& lhs, const Thread& rhs)
+{
+ return !(lhs == rhs);
+}
+
+bool operator <(const Thread& lhs, const Thread& rhs)
+{
+ return lhs.ID() < rhs.ID();
+}
+
+//CHANNEL
+bool operator ==(const Channel& lhs, const Channel& rhs)
+{
+ return lhs.ID() == rhs.ID();
+}
+
+bool operator !=(const Channel& lhs, const Channel& rhs)
+{
+ return !(lhs == rhs);
+}
+
+
+//BANKGROUP
+bool operator ==(const BankGroup& lhs, const BankGroup& rhs)
+{
+ return lhs.ID() == rhs.ID();
+}
+
+bool operator !=(const BankGroup& lhs, const BankGroup& rhs)
+{
+ return !(lhs == rhs);
+}
+
+//BANK
+bool operator ==(const Bank& lhs, const Bank& rhs)
+{
+ return lhs.ID() == rhs.ID();
+}
+
+bool operator !=(const Bank& lhs, const Bank& rhs)
+{
+ return !(lhs == rhs);
+}
+
+bool operator <(const Bank& lhs, const Bank& rhs)
+{
+ return lhs.ID() < rhs.ID();
+}
+
+//ROW
+const Row Row::NO_ROW;
+
+bool operator ==(const Row& lhs, const Row& rhs)
+{
+ if (lhs.isNoRow != rhs.isNoRow)
+ return false;
+ return lhs.ID() == rhs.ID();
+}
+
+bool operator !=(const Row& lhs, const Row& rhs)
+{
+ return !(lhs == rhs);
+}
+
+const Row Row::operator ++()
+{
+ id = (id + 1) % core::Configuration::getInstance().NumberOfRows;
+ return *this;
+}
+
+
+//COLUMN
+bool operator ==(const Column& lhs, const Column& rhs)
+{
+ return lhs.ID() == rhs.ID();
+}
+
+bool operator !=(const Column& lhs, const Column& rhs)
+{
+ return !(lhs == rhs);
+}
diff --git a/dram/src/common/dramExtension.h b/dram/src/common/dramExtension.h
index 526d659f..607daab3 100644
--- a/dram/src/common/dramExtension.h
+++ b/dram/src/common/dramExtension.h
@@ -12,6 +12,7 @@
#include
#include
+
class Thread
{
public:
@@ -124,6 +125,59 @@ private:
unsigned int id;
};
+
+class DramExtension: public tlm::tlm_extension
+{
+public:
+ DramExtension();
+ DramExtension(const Thread& thread, const Bank& bank, const BankGroup& bankgroup, const Row& row, const Column& column,
+ unsigned int burstlength = 0);
+ DramExtension(const Thread& thread, const Channel& channel, const Bank& bank, const BankGroup& bankgroup, const Row& row,
+ const Column& column, unsigned int burstlength = 0);
+
+ virtual tlm_extension_base* clone() const;
+ virtual void copy_from(const tlm_extension_base& ext);
+ static DramExtension& getExtension(const tlm::tlm_generic_payload *payload);
+ static DramExtension& getExtension(const tlm::tlm_generic_payload &payload);
+
+ Thread getThread() const;
+ Channel getChannel() const;
+ Bank getBank() const;
+ BankGroup getBankGroup() const;
+ Row getRow() const;
+ Column getColumn() const;
+
+ unsigned int getBurstlength() const;
+ void incrementRow();
+
+private:
+ Thread thread;
+ Channel channel;
+ Bank bank;
+ BankGroup bankgroup;
+ Row row;
+ Column column;
+ unsigned int burstlength;
+};
+
+
+// Used to indicate the time when a payload is created (in a traceplayer or in a core)
+// Note that this time can be different from the time the payload enters the DRAM system
+//(at that time the phase BEGIN_REQ is recorded), so timeOfGeneration =< time(BEGIN_REQ)
+class GenerationExtension : public tlm::tlm_extension
+{
+public:
+ GenerationExtension(sc_time timeOfGeneration) : timeOfGeneration(timeOfGeneration) {}
+ virtual tlm_extension_base* clone() const;
+ virtual void copy_from(const tlm_extension_base& ext);
+ static GenerationExtension& getExtension(const tlm::tlm_generic_payload *payload);
+ sc_time TimeOfGeneration() const {return timeOfGeneration;}
+
+private:
+ sc_time timeOfGeneration;
+};
+
+
bool operator==(const Thread &lhs, const Thread &rhs);
bool operator!=(const Thread &lhs, const Thread &rhs);
bool operator<(const Thread &lhs, const Thread &rhs);
@@ -144,73 +198,4 @@ bool operator!=(const Row &lhs, const Row &rhs);
bool operator==(const Column &lhs, const Column &rhs);
bool operator!=(const Column &lhs, const Column &rhs);
-class DramExtension: public tlm::tlm_extension
-{
-private:
- Thread thread;
- Channel channel;
- Bank bank;
- BankGroup bankgroup;
- Row row;
- Column column;
- unsigned int burstlength;
-public:
-
- DramExtension() :
- thread(0), channel(0), bank(0), bankgroup(0), row(0), column(0), burstlength(0)
- {
- }
- DramExtension(const Thread& thread, const Bank& bank, const BankGroup& bankgroup, const Row& row, const Column& column,
- unsigned int burstlength = 0) :
- thread(thread), channel(0), bank(bank), bankgroup(bankgroup), row(row), column(column), burstlength(burstlength)
- {
- }
- DramExtension(const Thread& thread, const Channel& channel, const Bank& bank, const BankGroup& bankgroup, const Row& row,
- const Column& column, unsigned int burstlength = 0) :
- thread(thread), channel(channel), bank(bank), bankgroup(bankgroup), row(row), column(column), burstlength(burstlength)
- {
- }
-
- ~DramExtension()
- {
- }
-
- virtual tlm_extension_base* clone() const;
- virtual void copy_from(const tlm_extension_base& ext);
-
- const Thread& getThread() const;
-
- const Channel& getChannel() const;
-
- const Bank& getBank() const;
-
- const BankGroup& getBankGroup() const;
-
- const Row& getRow() const;
-
- const Column& getColumn() const;
-
- unsigned int getBurstlength() const;
-
- void increaseRow();
-
- static DramExtension& getExtension(const tlm::tlm_generic_payload *payload);
- static DramExtension& getExtension(const tlm::tlm_generic_payload &payload);
-};
-
-
-class GenerationExtension : public tlm::tlm_extension
-{
-public:
- GenerationExtension(sc_time timeOfGeneration) : timeOfGeneration(timeOfGeneration) {}
- virtual tlm_extension_base* clone() const;
- virtual void copy_from(const tlm_extension_base& ext);
- static GenerationExtension& getExtension(const tlm::tlm_generic_payload *payload);
-
-
- sc_time TimeOfGeneration() const {return timeOfGeneration;}
-private:
- sc_time timeOfGeneration;
-};
-
#endif /* DRAMEXTENSION_H_ */
diff --git a/dram/src/controller/Controller.h b/dram/src/controller/Controller.h
index 5342a992..34a1c4e8 100644
--- a/dram/src/controller/Controller.h
+++ b/dram/src/controller/Controller.h
@@ -35,6 +35,7 @@
#include "scheduler/Fifo.h"
#include "scheduler/Fr_Fcfs.h"
#include "scheduler/PARBS.h"
+#include "scheduler/readwritegrouper.h"
using namespace std;
using namespace tlm;
@@ -54,6 +55,7 @@ public:
iSocket.register_nb_transport_bw(this, &Controller::nb_transport_bw);
tSocket.register_nb_transport_fw(this, &Controller::nb_transport_fw);
}
+
~Controller()
{
delete controllerCore;
@@ -118,8 +120,9 @@ void Controller::buildScheduler()
if (selectedScheduler == "FR_FCFS")
{
- scheduler = new FR_FCFS(*controllerCore, Configuration::getInstance().RefreshAwareScheduling,
+ Scheduler* s = new FR_FCFS(*controllerCore, Configuration::getInstance().RefreshAwareScheduling,
Configuration::getInstance().AdaptiveOpenPagePolicy);
+ scheduler = new ReadWriteGrouper(s);
}
else if (selectedScheduler == "PAR_BS")
{
@@ -222,7 +225,7 @@ void Controller::controllerCorePEQCallback(tlm_generic_payload &payloa
{
if (phase == REF_TRIGGER)
{
- controllerCore->triggerRefresh(payload, sc_time_stamp());
+ controllerCore->triggerRefresh(payload);
}
else if (phase == PDN_TRIGGER)
{
@@ -347,7 +350,7 @@ void Controller::scheduleNextPayload()
if(payload != NULL)
{
controllerCore->powerDownManager->wakeUp(DramExtension::getExtension(payload).getBank(), sc_time_stamp());
- bool wasScheduledByCore = controllerCore->scheduleRequest(sc_time_stamp(), *payload);
+ bool wasScheduledByCore = controllerCore->scheduleRequest(*payload);
if (wasScheduledByCore)
{
scheduler->removePayload(payload);
diff --git a/dram/src/controller/core/ControllerCore.cpp b/dram/src/controller/core/ControllerCore.cpp
index 168521e0..7d41ed0a 100644
--- a/dram/src/controller/core/ControllerCore.cpp
+++ b/dram/src/controller/core/ControllerCore.cpp
@@ -91,8 +91,9 @@ void ControllerCore::resetState()
state = savedState;
}
-void ControllerCore::triggerRefresh(tlm::tlm_generic_payload& payload, sc_time time)
+void ControllerCore::triggerRefresh(tlm::tlm_generic_payload& payload)
{
+ sc_time time = sc_time_stamp();
Bank bank = DramExtension::getExtension(payload).getBank();
state.cleanUp(time);
@@ -105,9 +106,9 @@ void ControllerCore::triggerRefresh(tlm::tlm_generic_payload& payload, sc_time t
}
}
-bool ControllerCore::scheduleRequest(sc_time start, tlm::tlm_generic_payload& payload)
+bool ControllerCore::scheduleRequest(tlm::tlm_generic_payload& payload)
{
- start = clkAlign(start);
+ sc_time start = clkAlign(sc_time_stamp());
state.cleanUp(start);
saveState();
@@ -127,8 +128,9 @@ bool ControllerCore::scheduleRequest(sc_time start, tlm::tlm_generic_payload& pa
}
}
-bool ControllerCore::bankIsBusy(sc_time time, Bank bank)
+bool ControllerCore::bankIsBusy(Bank bank)
{
+ sc_time time = sc_time_stamp();
ScheduledCommand lastScheduledCommand = state.getLastScheduledCommand(bank);
if (lastScheduledCommand.isNoCommand())
@@ -173,12 +175,12 @@ const std::vector& ControllerCore::getBanks()
return banks;
}
-std::vector ControllerCore::getFreeBanks(sc_time currentTime)
+std::vector ControllerCore::getFreeBanks()
{
std::vector freeBanks;
for(Bank bank: getBanks())
{
- if(!bankIsBusy(currentTime, bank))
+ if(!bankIsBusy(bank))
freeBanks.push_back(bank);
}
return freeBanks;
diff --git a/dram/src/controller/core/ControllerCore.h b/dram/src/controller/core/ControllerCore.h
index 66238e67..7f4b7f52 100644
--- a/dram/src/controller/core/ControllerCore.h
+++ b/dram/src/controller/core/ControllerCore.h
@@ -27,15 +27,11 @@ public:
ControllerCore(IWrapperConnector& wrapper, std::map& numberOfPayloads);
virtual ~ControllerCore() ;
- bool bankIsBusy(sc_time currentTime, Bank bank);
- bool scheduleRequest(sc_time currentTime, tlm::tlm_generic_payload& payload);
- void triggerRefresh(tlm::tlm_generic_payload& payload, sc_time time);
-
- void saveState();
- void resetState();
+ bool scheduleRequest(tlm::tlm_generic_payload& payload);
+ void triggerRefresh(tlm::tlm_generic_payload& payload);
const std::vector& getBanks();
- std::vector getFreeBanks(sc_time currentTime);
+ std::vector getFreeBanks();
const RowBufferState& getRowBufferStates(){return state.rowBufferStates;}
ICommandChecker& getCommandChecker(Command command);
@@ -44,7 +40,6 @@ public:
Configuration config;
ControllerState state;
IWrapperConnector& wrapper;
-
IPowerDownManager* powerDownManager;
IRefreshManager* refreshManager;
std::map& numberOfPayloads;
@@ -52,6 +47,9 @@ public:
private:
void send(const CommandSchedule& schedule, tlm::tlm_generic_payload& payload) const;
+ bool bankIsBusy(Bank bank);
+ void saveState();
+ void resetState();
std::map commandChecker;
ControllerState savedState;
diff --git a/dram/src/controller/core/refresh/RefreshManager.cpp b/dram/src/controller/core/refresh/RefreshManager.cpp
index d46c147b..57f26bdc 100644
--- a/dram/src/controller/core/refresh/RefreshManager.cpp
+++ b/dram/src/controller/core/refresh/RefreshManager.cpp
@@ -55,7 +55,7 @@ void RefreshManager::scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time
for (Bank bank : controller.getBanks())
{
- DramExtension::getExtension(refreshPayloads[bank]).increaseRow();
+ DramExtension::getExtension(refreshPayloads[bank]).incrementRow();
}
planNextRefresh();
diff --git a/dram/src/controller/core/refresh/RefreshManagerBankwise.cpp b/dram/src/controller/core/refresh/RefreshManagerBankwise.cpp
index e50bc250..215da8dd 100644
--- a/dram/src/controller/core/refresh/RefreshManagerBankwise.cpp
+++ b/dram/src/controller/core/refresh/RefreshManagerBankwise.cpp
@@ -61,7 +61,7 @@ void RefreshManagerBankwise::scheduleRefresh(tlm::tlm_generic_payload& payload,
controller.state.change(nextRefresh);
controller.wrapper.send(nextRefresh, refreshPayload);
- extension.increaseRow();
+ extension.incrementRow();
planNextRefresh(extension.getBank());
}
diff --git a/dram/src/controller/core/scheduling/ScheduledCommand.cpp b/dram/src/controller/core/scheduling/ScheduledCommand.cpp
index bcef806b..8e793ed6 100644
--- a/dram/src/controller/core/scheduling/ScheduledCommand.cpp
+++ b/dram/src/controller/core/scheduling/ScheduledCommand.cpp
@@ -90,8 +90,8 @@ bool ScheduledCommand::commandIsIn(const std::vector& commandSet) const
TimeInterval ScheduledCommand::getIntervalOnDataStrobe() const
{
- sc_assert(
- getCommand() == Command::Read || getCommand() == Command::ReadA
+ //only read and write commands have an assoicated time on the data strobe
+ sc_assert(getCommand() == Command::Read || getCommand() == Command::ReadA
|| getCommand() == Command::Write
|| getCommand() == Command::WriteA);
@@ -99,7 +99,7 @@ TimeInterval ScheduledCommand::getIntervalOnDataStrobe() const
if (getCommand() == Command::Read || getCommand() == Command::ReadA)
{
- return TimeInterval(getStart() + timings.tRL,getStart() + timings.tRL + getReadAccessTime());
+ return TimeInterval(getStart() + timings.tRL, getStart() + timings.tRL + getReadAccessTime());
}
else
{
diff --git a/dram/src/controller/scheduler/Fifo.cpp b/dram/src/controller/scheduler/Fifo.cpp
index cc501769..aef1ecd9 100644
--- a/dram/src/controller/scheduler/Fifo.cpp
+++ b/dram/src/controller/scheduler/Fifo.cpp
@@ -22,7 +22,7 @@ void Fifo::schedule(gp* payload)
gp* Fifo::getNextPayload()
{
- for(Bank bank: controllerCore.getFreeBanks(sc_time_stamp()))
+ for(Bank bank: controllerCore.getFreeBanks())
{
if(!buffer[bank].empty())
{
diff --git a/dram/src/controller/scheduler/Fr_Fcfs.cpp b/dram/src/controller/scheduler/Fr_Fcfs.cpp
index b2fefae7..5635cc33 100644
--- a/dram/src/controller/scheduler/Fr_Fcfs.cpp
+++ b/dram/src/controller/scheduler/Fr_Fcfs.cpp
@@ -38,7 +38,7 @@ void FR_FCFS::schedule(std::vector payloads)
gp* FR_FCFS::getNextPayload()
{
- for(Bank bank: controllerCore.getFreeBanks(sc_time_stamp()))
+ for(Bank bank: controllerCore.getFreeBanks())
{
if(!buffer[bank].empty())
{
diff --git a/dram/src/controller/scheduler/PARBS.h b/dram/src/controller/scheduler/PARBS.h
index 2c6f9398..3d472011 100644
--- a/dram/src/controller/scheduler/PARBS.h
+++ b/dram/src/controller/scheduler/PARBS.h
@@ -18,6 +18,7 @@ class PAR_BS : public Scheduler
public:
PAR_BS(core::ControllerCore& controllerCore, bool useExternalBankstates, unsigned int capsize);
virtual ~PAR_BS();
+
virtual bool hasPayloads() override;
virtual void schedule(gp* payload) override;
virtual gp* getNextPayload() override;
@@ -25,6 +26,7 @@ public:
private:
void formBatch();
+
core::ControllerCore& controllerCore;
bool useExternalBankstates;
core::RowBufferState internalBankstates;
diff --git a/dram/src/controller/scheduler/Scheduler.h b/dram/src/controller/scheduler/Scheduler.h
index 85fd552b..c117f760 100644
--- a/dram/src/controller/scheduler/Scheduler.h
+++ b/dram/src/controller/scheduler/Scheduler.h
@@ -11,14 +11,8 @@ class Scheduler
{
public:
virtual ~Scheduler(){}
-
virtual void schedule(gp* payload) = 0;
-
- //TODO Rename to payload
virtual bool hasPayloads() = 0;
- /*
- *Test
- */
virtual gp* getNextPayload() = 0;
virtual void removePayload(gp* payload) = 0;
static std::string sendername;
diff --git a/dram/src/controller/scheduler/readwritegrouper.cpp b/dram/src/controller/scheduler/readwritegrouper.cpp
new file mode 100644
index 00000000..5797fddb
--- /dev/null
+++ b/dram/src/controller/scheduler/readwritegrouper.cpp
@@ -0,0 +1,121 @@
+#include "readwritegrouper.h"
+
+namespace scheduler{
+
+using namespace tlm;
+
+ReadWriteGrouper::ReadWriteGrouper(Scheduler *scheduler):
+ scheduler(scheduler), mode(Mode::read)
+{
+
+}
+
+ReadWriteGrouper::~ReadWriteGrouper()
+{
+ delete scheduler;
+}
+
+
+void ReadWriteGrouper::removePayload(gp *payload)
+{
+ scheduler->removePayload(payload);
+
+ //if scheduler is empty now
+ if(!scheduler->hasPayloads())
+ {
+ if(mode == Mode::read && !writeQueue.empty())
+ switchToWriteMode();
+ else if(mode == Mode::readToWrite)
+ switchToWriteMode();
+ else
+ switchToReadMode();
+ }
+}
+
+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)
+ {
+ //if scheduling the read would cause a hazard switch to readToWriteMode and put the read into the readQueue
+ if(schedulingReadCausesHazard(payload))
+ {
+ switchToReadToWriteMode();
+ readQueue.push_back(payload);
+ }
+ else
+ scheduler->schedule(payload);
+ }
+ else
+ {
+ writeQueue.push_back(payload);
+ if(!scheduler->hasPayloads())
+ //there are no reads in the scheduler, so switch directly to write mode
+ switchToWriteMode();
+ }
+}
+else if(mode == Mode::readToWrite)
+{
+ if(command == TLM_READ_COMMAND)
+ readQueue.push_back(payload);
+ else
+ writeQueue.push_back(payload);
+}
+else if(mode == Mode::write)
+{
+ if(command == TLM_READ_COMMAND)
+ readQueue.push_back(payload);
+ else
+ scheduler->schedule(payload);
+}
+
+}
+
+gp *ReadWriteGrouper::getNextPayload()
+{
+ return scheduler->getNextPayload();
+}
+
+bool ReadWriteGrouper::hasPayloads()
+{
+ return scheduler->hasPayloads();
+}
+
+
+bool ReadWriteGrouper::schedulingReadCausesHazard(gp *payload)
+{
+ sc_assert(payload->is_read());
+ for(gp* write: writeQueue)
+ {
+ if(payload->get_address()==write->get_address())
+ return true;
+ }
+ return false;
+}
+
+void ReadWriteGrouper::switchToReadMode()
+{
+ mode = Mode::read;
+ for(gp* read: readQueue)
+ scheduler->schedule(read);
+ readQueue.clear();
+}
+
+void ReadWriteGrouper::switchToWriteMode()
+{
+ mode = Mode::write;
+ for(gp* write: writeQueue)
+ scheduler->schedule(write);
+ writeQueue.clear();
+}
+
+void ReadWriteGrouper::switchToReadToWriteMode()
+{
+ mode = Mode::readToWrite;
+}
+
+}
diff --git a/dram/src/controller/scheduler/readwritegrouper.h b/dram/src/controller/scheduler/readwritegrouper.h
new file mode 100644
index 00000000..4e8b359f
--- /dev/null
+++ b/dram/src/controller/scheduler/readwritegrouper.h
@@ -0,0 +1,40 @@
+#ifndef READWRITEGROUPER_H
+#define READWRITEGROUPER_H
+#include "Scheduler.h"
+#include
+
+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();
+ virtual void schedule(gp* payload) override;
+ virtual bool hasPayloads() override;
+ virtual gp* getNextPayload() override;
+ virtual void removePayload(gp* payload) override;
+
+private:
+ Scheduler *scheduler;
+ std::vector 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;
+
+ bool schedulingReadCausesHazard(gp* payload);
+ void switchToReadMode();
+ void switchToWriteMode();
+ void switchToReadToWriteMode();
+};
+
+
+}
+
+#endif // READWRITEGROUPER_H
diff --git a/dram/src/simulation/TracePlayer.h b/dram/src/simulation/TracePlayer.h
index 20aa8c6d..1c76277a 100644
--- a/dram/src/simulation/TracePlayer.h
+++ b/dram/src/simulation/TracePlayer.h
@@ -32,29 +32,17 @@ struct TracePlayer: public sc_module
public:
tlm_utils::simple_initiator_socket iSocket;
TracePlayer(sc_module_name /*name*/, string pathToTrace, unsigned int burstLength,
- simulation::ISimulation* simulationManager) :
- payloadEventQueue(this, &TracePlayer::peqCallback), file(pathToTrace), burstlenght(burstLength), numberOfPendingTransactions(
- 0), transactionsSent(0), transactionsReceived(0), simulationManager(
- simulationManager)
- {
- if (!file.is_open())
- SC_REPORT_FATAL(0, (string("Could not open trace ") + pathToTrace).c_str());
+ simulation::ISimulation* simulationManager);
- this->burstlenght = core::Configuration::getInstance().BurstLength;
- iSocket.register_nb_transport_bw(this, &TracePlayer::nb_transport_bw);
- }
-
- void start()
- {
- bool fileIsEmpty = file.peek() == std::ifstream::traits_type::eof();
- if (!fileIsEmpty)
- {
- scheduleNextPayload();
- }
- }
+ void start();
private:
+ void generateNextPayload();
+ tlm_sync_enum nb_transport_bw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& bwDelay);
+ void peqCallback(tlm_generic_payload& payload, const tlm_phase& phase);
+ void sendToTarget(tlm_generic_payload& payload, const tlm_phase& phase, const sc_time& delay);
tlm_utils::peq_with_cb_and_phase payloadEventQueue;
+
MemoryManager memoryManager;
ifstream file;
unsigned int burstlenght;
@@ -62,108 +50,135 @@ private:
unsigned int transactionsSent;
unsigned int transactionsReceived;
simulation::ISimulation* simulationManager;
+};
- void scheduleNextPayload()
+
+template
+TracePlayer::TracePlayer(sc_module_name, string pathToTrace, unsigned int burstLength, simulation::ISimulation *simulationManager) :
+ payloadEventQueue(this, &TracePlayer::peqCallback), file(pathToTrace), burstlenght(burstLength),
+ numberOfPendingTransactions(0), transactionsSent(0), transactionsReceived(0), simulationManager(simulationManager)
+{
+ if (!file.is_open())
+ SC_REPORT_FATAL(0, (string("Could not open trace ") + pathToTrace).c_str());
+
+ this->burstlenght = core::Configuration::getInstance().BurstLength;
+ iSocket.register_nb_transport_bw(this, &TracePlayer::nb_transport_bw);
+}
+
+template
+void TracePlayer::start()
+{
+ bool fileIsEmpty = file.peek() == std::ifstream::traits_type::eof();
+ if (!fileIsEmpty)
{
- if (file)
- {
- string time, command, address;
- file >> time >> command >> address;
-
- //if there is a newline at the end of the .stl
- if (time.empty() || command.empty() || address.empty())
- return;
-
- long parsedAdress = std::stoi(address.c_str(), 0, 16);
-
- gp* payload = memoryManager.allocate();
- payload->set_address(parsedAdress);
-
- if (command == "read")
- {
- payload->set_command(TLM_READ_COMMAND);
- }
- else if (command == "write")
- {
- payload->set_command(TLM_WRITE_COMMAND);
- }
- else
- {
- SC_REPORT_FATAL(0,
- (string("Corrupted tracefile, command ") + command + string(" unknown")).c_str());
- }
-
- payload->set_data_length(BUSWIDTH / 8);
- payload->set_response_status(TLM_INCOMPLETE_RESPONSE);
- payload->set_dmi_allowed(false);
- payload->set_byte_enable_length(0);
- payload->set_streaming_width(burstlenght);
-
- sc_time sendingTime = sc_time(std::stoi(time.c_str()), SC_NS);
- GenerationExtension* genExtension = new GenerationExtension(sendingTime);
- payload->set_auto_extension(genExtension);
-
- if (sendingTime <= sc_time_stamp())
- {
- payloadEventQueue.notify(*payload, BEGIN_REQ, SC_ZERO_TIME);
- }
- else
- {
- payloadEventQueue.notify(*payload, BEGIN_REQ, sendingTime - sc_time_stamp());
- }
- numberOfPendingTransactions++;
- }
+ generateNextPayload();
}
+}
- tlm_sync_enum nb_transport_bw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& bwDelay)
+template
+void TracePlayer::generateNextPayload()
+{
+ if (file)
{
- payloadEventQueue.notify(payload, phase, bwDelay);
- return TLM_ACCEPTED;
- }
+ string time, command, address;
+ file >> time >> command >> address;
- void peqCallback(tlm_generic_payload& payload, const tlm_phase& phase)
- {
- if (phase == BEGIN_REQ)
+ //if there is a newline at the end of the .stl
+ if (time.empty() || command.empty() || address.empty())
+ return;
+
+ long parsedAdress = std::stoi(address.c_str(), 0, 16);
+
+ gp* payload = memoryManager.allocate();
+ payload->set_address(parsedAdress);
+
+ if (command == "read")
{
- payload.acquire();
- sendToTarget(payload, phase, SC_ZERO_TIME);
-
- transactionsSent++;
- DebugManager::getInstance().printDebugMessage(name(),
- "Sending transaction number: " + std::to_string(transactionsSent));
+ payload->set_command(TLM_READ_COMMAND);
}
- else if (phase == END_REQ)
- {
- scheduleNextPayload();
- }
- else if (phase == BEGIN_RESP)
- {
- sendToTarget(payload, END_RESP, SC_ZERO_TIME);
- payload.release();
-
- simulationManager->transactionFinished();
- numberOfPendingTransactions--;
- transactionsReceived++;
-
- DebugManager::getInstance().printDebugMessage(name(),
- "Pending transactions in core: "
- + std::to_string(transactionsSent - transactionsReceived));
- }
- else if (phase == END_RESP)
+ else if (command == "write")
{
+ payload->set_command(TLM_WRITE_COMMAND);
}
else
{
- SC_REPORT_FATAL(0, "TracePlayer PEQ was triggered with unknown phase");
+ SC_REPORT_FATAL(0,
+ (string("Corrupted tracefile, command ") + command + string(" unknown")).c_str());
}
- }
- void sendToTarget(tlm_generic_payload& payload, const tlm_phase& phase, const sc_time& delay)
- {
- tlm_phase TPhase = phase;
- sc_time TDelay = delay;
- iSocket->nb_transport_fw(payload, TPhase, TDelay);
+ payload->set_data_length(BUSWIDTH / 8);
+ payload->set_response_status(TLM_INCOMPLETE_RESPONSE);
+ payload->set_dmi_allowed(false);
+ payload->set_byte_enable_length(0);
+ payload->set_streaming_width(burstlenght);
+
+ sc_time sendingTime = sc_time(std::stoi(time.c_str()), SC_NS);
+ GenerationExtension* genExtension = new GenerationExtension(sendingTime);
+ payload->set_auto_extension(genExtension);
+
+ if (sendingTime <= sc_time_stamp())
+ {
+ payloadEventQueue.notify(*payload, BEGIN_REQ, SC_ZERO_TIME);
+ }
+ else
+ {
+ payloadEventQueue.notify(*payload, BEGIN_REQ, sendingTime - sc_time_stamp());
+ }
+ numberOfPendingTransactions++;
}
-};
+}
+
+template
+tlm_sync_enum TracePlayer::nb_transport_bw(tlm_generic_payload &payload, tlm_phase &phase, sc_time &bwDelay)
+{
+ payloadEventQueue.notify(payload, phase, bwDelay);
+ return TLM_ACCEPTED;
+}
+
+template
+void TracePlayer::peqCallback(tlm_generic_payload &payload, const tlm_phase &phase)
+{
+ if (phase == BEGIN_REQ)
+ {
+ payload.acquire();
+ sendToTarget(payload, phase, SC_ZERO_TIME);
+
+ transactionsSent++;
+ DebugManager::getInstance().printDebugMessage(name(),
+ "Sending transaction number: " + std::to_string(transactionsSent));
+ }
+ else if (phase == END_REQ)
+ {
+ generateNextPayload();
+ }
+ else if (phase == BEGIN_RESP)
+ {
+ sendToTarget(payload, END_RESP, SC_ZERO_TIME);
+ payload.release();
+
+ simulationManager->transactionFinished();
+ numberOfPendingTransactions--;
+ transactionsReceived++;
+
+ DebugManager::getInstance().printDebugMessage(name(),
+ "Pending transactions in core: "
+ + std::to_string(transactionsSent - transactionsReceived));
+ }
+ else if (phase == END_RESP)
+ {
+ }
+ else
+ {
+ SC_REPORT_FATAL(0, "TracePlayer PEQ was triggered with unknown phase");
+ }
+}
+
+template
+void TracePlayer::sendToTarget(tlm_generic_payload &payload, const tlm_phase &phase, const sc_time &delay)
+{
+ tlm_phase TPhase = phase;
+ sc_time TDelay = delay;
+ iSocket->nb_transport_fw(payload, TPhase, TDelay);
+}
#endif /* TRACEPLAYER_H_ */