diff --git a/DRAMSys/library/src/controller/BankMachine.cpp b/DRAMSys/library/src/controller/BankMachine.cpp index c3e2688e..99bd9809 100644 --- a/DRAMSys/library/src/controller/BankMachine.cpp +++ b/DRAMSys/library/src/controller/BankMachine.cpp @@ -82,6 +82,11 @@ Rank BankMachine::getRank() return rank; } +BankGroup BankMachine::getBankGroup() +{ + return bankgroup; +} + Bank BankMachine::getBank() { return bank; diff --git a/DRAMSys/library/src/controller/BankMachine.h b/DRAMSys/library/src/controller/BankMachine.h index bf36ef47..bf7ca2f5 100644 --- a/DRAMSys/library/src/controller/BankMachine.h +++ b/DRAMSys/library/src/controller/BankMachine.h @@ -65,6 +65,7 @@ public: void block(); Rank getRank(); + BankGroup getBankGroup(); Bank getBank(); Row getOpenRow(); BmState getState(); diff --git a/DRAMSys/library/src/controller/refresh/RefreshManager.cpp b/DRAMSys/library/src/controller/refresh/RefreshManager.cpp index 962206c2..3c8dc00d 100644 --- a/DRAMSys/library/src/controller/refresh/RefreshManager.cpp +++ b/DRAMSys/library/src/controller/refresh/RefreshManager.cpp @@ -64,56 +64,68 @@ sc_time RefreshManager::start() if (sc_time_stamp() >= timeForNextTrigger) { sc_time delay; - if (state == RmState::IDLE) + if (state == RmState::Regular) { - if (flexibleCounter != maxPostponed || isPulledinRefresh) + bool forcedRefresh = (flexibilityCounter == maxPostponed); + if (!forcedRefresh) { for (auto it : bankMachines) { if (!it->isIdle()) { - if (!isPulledinRefresh) - flexibleCounter++; - isPulledinRefresh = false; + flexibilityCounter++; timeForNextTrigger += memSpec->getRefreshIntervalAB(); return timeForNextTrigger - sc_time_stamp(); } } } - else + else // regular refresh that cannot be postponed -> force precharge { for (auto it : bankMachines) it->block(); } - // TODO: If we do not block the bankmachines we have to check this each time - bool doPrecharge = false; for (auto it : bankMachines) { if (it->getState() == BmState::Activated) - doPrecharge = true; + { + nextCommand = Command::PREA; + delay = checker->delayToSatisfyConstraints(Command::PREA, rank, BankGroup(0), Bank(0)); + timeToSchedule = sc_time_stamp() + delay; + return delay; + } } - if (doPrecharge) - { - delay = checker->delayToSatisfyConstraints(Command::PREA, rank, BankGroup(0), Bank(0)); - nextCommand = Command::PREA; - } - else - { - delay = checker->delayToSatisfyConstraints(Command::REFA, rank, BankGroup(0), Bank(0)); - nextCommand = Command::REFA; - if (flexibleCounter == maxPostponed) - state = RmState::PRECHARGED; - } - } - else // if (state == RmState::PRECHARGED) - { - delay = checker->delayToSatisfyConstraints(Command::REFA, rank, BankGroup(0), Bank(0)); + if (forcedRefresh) // if refresh is forced all banks will remain precharged state + state = RmState::Precharged; nextCommand = Command::REFA; + delay = checker->delayToSatisfyConstraints(Command::REFA, rank, BankGroup(0), Bank(0)); + timeToSchedule = sc_time_stamp() + delay; + return delay; + } + else if (state == RmState::Pulledin) + { + for (auto it : bankMachines) + { + if (!it->isIdle()) + { + state = RmState::Regular; + timeForNextTrigger += memSpec->getRefreshIntervalAB(); + return timeForNextTrigger - sc_time_stamp(); + } + } + + delay = checker->delayToSatisfyConstraints(Command::REFA, rank, BankGroup(0), Bank(0)); + timeToSchedule = sc_time_stamp() + delay; + return delay; + } + else // if (state == RmState::Precharged) + { + nextCommand = Command::REFA; + delay = checker->delayToSatisfyConstraints(Command::REFA, rank, BankGroup(0), Bank(0)); + timeToSchedule = sc_time_stamp() + delay; + return delay; } - timeToSchedule = sc_time_stamp() + delay; - return delay; } else return timeForNextTrigger - sc_time_stamp(); @@ -123,23 +135,24 @@ void RefreshManager::updateState(Command command, tlm_generic_payload *) { if (command == Command::REFA) { - state = RmState::IDLE; - - if (isPulledinRefresh) - flexibleCounter--; + if (state == RmState::Pulledin) + flexibilityCounter--; else - isPulledinRefresh = true; + state = RmState::Pulledin; - if (flexibleCounter == maxPulledin) + if ((flexibilityCounter == maxPulledin) || + ((sc_time_stamp() + memSpec->getExecutionTime(Command::REFA) + >= (timeForNextTrigger + memSpec->getRefreshIntervalAB())))) { - isPulledinRefresh = false; + state = RmState::Regular; timeForNextTrigger += memSpec->getRefreshIntervalAB(); } } else if (command == Command::PREA) { + // if PREA was successful we will refresh in any case for (auto it : bankMachines) it->block(); - state = RmState::PRECHARGED; + state = RmState::Precharged; } } diff --git a/DRAMSys/library/src/controller/refresh/RefreshManager.h b/DRAMSys/library/src/controller/refresh/RefreshManager.h index 0bfe6d69..e30ebc83 100644 --- a/DRAMSys/library/src/controller/refresh/RefreshManager.h +++ b/DRAMSys/library/src/controller/refresh/RefreshManager.h @@ -52,7 +52,7 @@ public: void updateState(Command, tlm_generic_payload *); private: - enum class RmState {IDLE, PRECHARGED} state = RmState::IDLE; + enum class RmState {Regular, Precharged, Pulledin} state = RmState::Regular; const MemSpec *memSpec; std::vector bankMachines; tlm_generic_payload refreshPayload; @@ -62,10 +62,9 @@ private: CheckerIF *checker; Command nextCommand; - int flexibleCounter = 0; + int flexibilityCounter = 0; int maxPostponed = 0; int maxPulledin = 0; - bool isPulledinRefresh = false; }; #endif // REFRESHMANAGER_H diff --git a/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.cpp b/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.cpp index ac6b4158..950a153f 100644 --- a/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.cpp +++ b/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.cpp @@ -40,19 +40,27 @@ RefreshManagerBankwise::RefreshManagerBankwise(std::vector &bankMachines, Rank rank, CheckerIF *checker) : bankMachines(bankMachines), rank(rank), checker(checker) { - memSpec = Configuration::getInstance().memSpec; + Configuration &config = Configuration::getInstance(); + memSpec = config.memSpec; timeForNextTrigger = memSpec->getRefreshIntervalPB(); refreshPayloads = std::vector(memSpec->BanksPerRank); - //states = std::vector(memSpec->NumberOfBanks, RmState::IDLE); for (unsigned bankID = 0; bankID < memSpec->BanksPerRank; bankID++) + { setUpDummy(refreshPayloads[bankID], rank, bankMachines[bankID]->getBank()); + remainingBankMachines.push_back(bankMachines[bankID]); + } + + if (config.ControllerCoreRefEnablePostpone) + maxPostponed = config.ControllerCoreRefMaxPostponed * memSpec->BanksPerRank; + if (config.ControllerCoreRefEnablePullIn) + maxPulledin = -(config.ControllerCoreRefMaxPulledIn * memSpec->BanksPerRank); } std::pair RefreshManagerBankwise::getNextCommand() { if (sc_time_stamp() == timeToSchedule) - return std::pair(nextCommand, &refreshPayloads[nextBankID]); + return std::pair(nextCommand, &refreshPayloads[currentBankMachine->getBank().ID() % memSpec->BanksPerRank]); else return std::pair(Command::NOP, nullptr); } @@ -62,33 +70,140 @@ sc_time RefreshManagerBankwise::start() if (sc_time_stamp() >= timeForNextTrigger) { sc_time delay; - bankMachines[nextBankID]->block(); - if (bankMachines[nextBankID]->getState() == BmState::Activated) + if (state == RmState::Regular) { - delay = checker->delayToSatisfyConstraints(Command::PRE, rank, BankGroup(0), - bankMachines[nextBankID]->getBank()); - nextCommand = Command::PRE; - } - else - { - delay = checker->delayToSatisfyConstraints(Command::REFB, rank, BankGroup(0), - bankMachines[nextBankID]->getBank()); + bool allBanksBusy = true; + currentIterator = remainingBankMachines.begin(); + currentBankMachine = *remainingBankMachines.begin(); + + for (auto it = remainingBankMachines.begin(); it != remainingBankMachines.end(); it++) + { + if ((*it)->isIdle()) + { + currentIterator = it; + currentBankMachine = *it; + allBanksBusy = false; + break; + } + } + + bool forcedRefresh = (flexibilityCounter == maxPostponed); + if (allBanksBusy && !forcedRefresh) + { + flexibilityCounter++; + timeForNextTrigger += memSpec->getRefreshIntervalPB(); + return timeForNextTrigger - sc_time_stamp(); + } + else if (forcedRefresh) + currentBankMachine->block(); + + if (currentBankMachine->getState() == BmState::Activated) + { + nextCommand = Command::PRE; + delay = checker->delayToSatisfyConstraints(Command::PRE, rank, + currentBankMachine->getBankGroup(), currentBankMachine->getBank()); + timeToSchedule = sc_time_stamp() + delay; + return delay; + } + + if (forcedRefresh) + state = RmState::Precharged; nextCommand = Command::REFB; + delay = checker->delayToSatisfyConstraints(Command::REFB, rank, + currentBankMachine->getBankGroup(), currentBankMachine->getBank()); + timeToSchedule = sc_time_stamp() + delay; + return delay; + } + else if (state == RmState::Pulledin) + { + bool allBanksBusy = true; + for (auto it = remainingBankMachines.begin(); it != remainingBankMachines.end(); it++) + { + if ((*it)->isIdle()) + { + currentIterator = it; + currentBankMachine = *it; + allBanksBusy = false; + break; + } + } + + if (allBanksBusy) + { + state = RmState::Regular; + timeForNextTrigger += memSpec->getRefreshIntervalPB(); + return timeForNextTrigger - sc_time_stamp(); + } + + if (currentBankMachine->getState() == BmState::Activated) + { + nextCommand = Command::PRE; + delay = checker->delayToSatisfyConstraints(Command::PRE, rank, + currentBankMachine->getBankGroup(), currentBankMachine->getBank()); + } + else + { + nextCommand = Command::REFB; + delay = checker->delayToSatisfyConstraints(Command::REFB, rank, + currentBankMachine->getBankGroup(), currentBankMachine->getBank()); + } + timeToSchedule = sc_time_stamp() + delay; + return delay; + } + else // if (state == RmState::Precharged) + { + nextCommand = Command::REFB; + delay = checker->delayToSatisfyConstraints(Command::REFB, rank, + currentBankMachine->getBankGroup(), currentBankMachine->getBank()); + timeToSchedule = sc_time_stamp() + delay; + return delay; } - timeToSchedule = sc_time_stamp() + delay; - return delay; } else return timeForNextTrigger - sc_time_stamp(); } -void RefreshManagerBankwise::updateState(Command command, tlm_generic_payload *) +void RefreshManagerBankwise::updateState(Command command, tlm_generic_payload *payload) { + // distinguish between PRE from BM and RM!!!!! if (command == Command::REFB) { - //state = RmState::IDLE; - nextBankID = (nextBankID + 1) % memSpec->BanksPerRank; - timeForNextTrigger += memSpec->getRefreshIntervalPB(); + remainingBankMachines.erase(currentIterator); + if (remainingBankMachines.empty()) + { + for (unsigned bankID = 0; bankID < memSpec->BanksPerRank; bankID++) + remainingBankMachines.push_back(bankMachines[bankID]); + } + + if (state == RmState::Pulledin) + flexibilityCounter--; + else + state = RmState::Pulledin; + + if ((flexibilityCounter == maxPulledin) || + ((sc_time_stamp() + memSpec->getExecutionTime(Command::REFB) + >= (timeForNextTrigger + memSpec->getRefreshIntervalPB())))) + { + state = RmState::Regular; + timeForNextTrigger += memSpec->getRefreshIntervalPB(); + } + } + else if (command == Command::PRE && nextCommand == Command::PRE) + { + // TODO: remove all this + if (DramExtension::getBank(payload) == currentBankMachine->getBank()) + { + if ((sc_time_stamp() + memSpec->getExecutionTime(Command::PRE) + >= (timeForNextTrigger + memSpec->getRefreshIntervalPB()))) + { + state = RmState::Regular; + timeForNextTrigger += memSpec->getRefreshIntervalAB(); + } + else + { + currentBankMachine->block(); + state = RmState::Precharged; + } + } } - //else if (command == Command::PRE) do nothing? } diff --git a/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.h b/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.h index d3ff44e7..4b176148 100644 --- a/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.h +++ b/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.h @@ -40,7 +40,9 @@ #include "../BankMachine.h" #include #include -#include +#include + +using namespace tlm; class RefreshManagerBankwise final : public RefreshManagerIF { @@ -52,7 +54,7 @@ public: void updateState(Command, tlm_generic_payload *); private: - enum class RmState {IDLE, PRECHARGED} state = RmState::IDLE; + enum class RmState {Regular, Precharged, Pulledin} state = RmState::Regular; const MemSpec *memSpec; std::vector bankMachines; std::vector refreshPayloads; @@ -61,7 +63,14 @@ private: Rank rank; CheckerIF *checker; Command nextCommand; - unsigned nextBankID = 0; + + std::list remainingBankMachines; + std::list::iterator currentIterator; + BankMachine *currentBankMachine; + + int flexibilityCounter = 0; + int maxPostponed = 0; + int maxPulledin = 0; }; #endif // REFRESHMANAGERBANKWISE_H