From b8febb434ff6af2e747d4d6dd0c23c1bfaa8c9b9 Mon Sep 17 00:00:00 2001 From: robert Date: Sun, 6 Jul 2014 10:34:46 +0200 Subject: [PATCH] minor refactoring --- dram/dramSys/dramSys.pro | 6 +- dram/resources/configs/memconfigs/fifo.xml | 2 +- dram/resources/configs/memconfigs/fr_fcfs.xml | 2 +- dram/src/common/TlmRecorder.cpp | 28 +- dram/src/common/TlmRecorder.h | 22 +- dram/src/common/Utils.h | 1 + dram/src/common/dramExtension.cpp | 243 ++++++++++-------- dram/src/common/dramExtension.h | 123 ++++----- dram/src/controller/Controller.h | 9 +- dram/src/controller/core/ControllerCore.cpp | 14 +- dram/src/controller/core/ControllerCore.h | 14 +- .../core/refresh/RefreshManager.cpp | 2 +- .../core/refresh/RefreshManagerBankwise.cpp | 2 +- .../core/scheduling/ScheduledCommand.cpp | 6 +- dram/src/controller/scheduler/Fifo.cpp | 2 +- dram/src/controller/scheduler/Fr_Fcfs.cpp | 2 +- dram/src/controller/scheduler/PARBS.h | 2 + dram/src/controller/scheduler/Scheduler.h | 6 - .../controller/scheduler/readwritegrouper.cpp | 121 +++++++++ .../controller/scheduler/readwritegrouper.h | 40 +++ dram/src/simulation/TracePlayer.h | 229 +++++++++-------- 21 files changed, 534 insertions(+), 342 deletions(-) create mode 100644 dram/src/controller/scheduler/readwritegrouper.cpp create mode 100644 dram/src/controller/scheduler/readwritegrouper.h 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_ */