From 7c538cdcd0815925415e47f7797465ac7373e6a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89der=20F=2E=20Zulian?= Date: Tue, 10 Jul 2018 12:50:22 +0200 Subject: [PATCH] Refresh Manager Bankwise - several improvements Considering initial PRE time for planning next REF when necessary. Postpone burst for a bank shall not be interrupted. Correct number of additional REF are pulled-in/postponed for a bank. Alignment to tREFI. --- .../core/refresh/RefreshManager.cpp | 1 - .../core/refresh/RefreshManagerBankwise.cpp | 131 +++++++++--------- .../core/refresh/RefreshManagerBankwise.h | 20 +-- 3 files changed, 80 insertions(+), 72 deletions(-) diff --git a/DRAMSys/library/src/controller/core/refresh/RefreshManager.cpp b/DRAMSys/library/src/controller/core/refresh/RefreshManager.cpp index 96a24df7..b07ed332 100644 --- a/DRAMSys/library/src/controller/core/refresh/RefreshManager.cpp +++ b/DRAMSys/library/src/controller/core/refresh/RefreshManager.cpp @@ -41,7 +41,6 @@ #include "../ControllerCore.h" #include "../TimingCalculation.h" #include "../../../common/Utils.h" -#include "../TimingCalculation.h" using namespace tlm; diff --git a/DRAMSys/library/src/controller/core/refresh/RefreshManagerBankwise.cpp b/DRAMSys/library/src/controller/core/refresh/RefreshManagerBankwise.cpp index 20239769..abf93c67 100644 --- a/DRAMSys/library/src/controller/core/refresh/RefreshManagerBankwise.cpp +++ b/DRAMSys/library/src/controller/core/refresh/RefreshManagerBankwise.cpp @@ -49,19 +49,19 @@ RefreshManagerBankwise::RefreshManagerBankwise(sc_module_name, auto m = controllerCore.config.getRefMode(); tREFIx = timing.tREFI / m; tRFCx = m == 4 ? timing.tRFC4 : m == 2 ? timing.tRFC2 : timing.tRFC; - if (controllerCore.config.ControllerCoreRefEnablePostpone) - maxpostpone = controllerCore.config.ControllerCoreRefMaxPostponed * m; - if (controllerCore.config.ControllerCoreRefEnablePullIn) - maxpullin = controllerCore.config.ControllerCoreRefMaxPulledIn * m; + postponeEnabled = controllerCore.config.ControllerCoreRefEnablePostpone; + pullInEnabled = controllerCore.config.ControllerCoreRefEnablePullIn; + maxpostpone = controllerCore.config.ControllerCoreRefMaxPostponed * m; + maxpullin = controllerCore.config.ControllerCoreRefMaxPulledIn * m; for (Bank bank : controller.getBanks()) { nextPlannedRefreshs[bank] = SC_ZERO_TIME; - arCmdCounter[bank] = 0; - alignValue[bank] = 0; + pulledin[bank] = 0; + postponed[bank] = 0; currentState[bank] = ST_REFRESH; previousState[bank] = ST_REFRESH; nextState[bank] = ST_REFRESH; setUpDummy(refreshPayloads[bank], bank); - planNextRefresh(bank, tREFIx); + planNextRefresh(bank, tREFIx, false); } } @@ -76,22 +76,31 @@ bool RefreshManagerBankwise::hasCollision(const ScheduledCommand &command) controllerCore.state->getLastCommand(Command::AutoRefresh, bank).getEnd(); bool collisionWithNextRefStart = command.getEnd() >= nextPlannedRefreshs[bank]; if (controllerCore.config.ControllerCoreRefEnablePostpone - && (arCmdCounter[bank] < maxpostpone)) { + && (postponed[bank] < maxpostpone)) { + // Flexible refresh is on and have "credits" to postpone. + // Then there will not be a collision with next refresh because + // nextPlannedRefresh will be updated. collisionWithNextRefStart = false; } + if (currentState[bank] == ST_BURST) { + // A burst due to postponed refreshes shall not be interrupted. + collisionWithNextRefStart = true; + } return collisionWithPreviousRefEnd || collisionWithNextRefStart; } -void RefreshManagerBankwise::doRefresh(tlm::tlm_generic_payload &payload, +bool RefreshManagerBankwise::doRefresh(tlm::tlm_generic_payload &payload, sc_time time) { sc_assert(!isInvalidated(payload, time)); + bool pre = false; tlm::tlm_generic_payload &refreshPayload = refreshPayloads[DramExtension::getExtension(payload).getBank()]; DramExtension &extension = DramExtension::getExtension(refreshPayload); if (controllerCore.state->rowBufferStates->rowBufferIsOpen( extension.getBank())) { + pre = true; ScheduledCommand precharge(Command::Precharge, time, getExecutionTime(Command::Precharge, refreshPayload), extension); controllerCore.getCommandChecker(Command::Precharge).delayToSatisfyConstraints( @@ -107,6 +116,7 @@ void RefreshManagerBankwise::doRefresh(tlm::tlm_generic_payload &payload, controllerCore.state->change(refresh); extension.incrementRow(); controllerCore.controller.send(refresh, refreshPayload); + return pre; } void RefreshManagerBankwise::scheduleRefresh(tlm::tlm_generic_payload &payload, @@ -115,24 +125,29 @@ void RefreshManagerBankwise::scheduleRefresh(tlm::tlm_generic_payload &payload, sc_time nextRefTiming; Bank bank = DramExtension::getExtension(payload).getBank(); bool pendingReq = controllerCore.hasPendingRequests(bank); - bool canPostpone = pendingReq && (arCmdCounter[bank] < maxpostpone); - bool canPullIn = !pendingReq && (arCmdCounter[bank] < maxpullin); + bool canPostpone = postponeEnabled && pendingReq && (postponed[bank] < maxpostpone); + bool canPullIn = pullInEnabled && !pendingReq && (pulledin[bank] < maxpullin); previousState[bank] = currentState[bank]; currentState[bank] = nextState[bank]; + bool align = false; + sc_time nrt; + bool pre; switch (currentState[bank]) { case ST_REFRESH: // Regular Refresh. It's possible to migrate from this to the flexible // refresh states - // The arCmdCounter[bank] should always be equal to zero here - assert(arCmdCounter[bank] == 0); - + assert(pulledin[bank] == 0 && postponed[bank] == 0); if (canPostpone) { - nextState[bank] = ST_POSTPONE; nextRefTiming = SC_ZERO_TIME; + nextState[bank] = ST_POSTPONE; } else if (canPullIn) { + pre = doRefresh(payload, time); + nrt = tRFCx; + if (pre) + nrt += controllerCore.config.memSpec.tRP; + nextRefTiming = nrt; nextState[bank] = ST_PULLIN; - nextRefTiming = SC_ZERO_TIME; // Attempt to burst pull-in } else { doRefresh(payload, time); nextRefTiming = tREFIx; @@ -140,93 +155,85 @@ void RefreshManagerBankwise::scheduleRefresh(tlm::tlm_generic_payload &payload, } break; case ST_PULLIN: - // Pull-In Refresh. Try to pull-in refreshes as long as the limit - // hasn't been reached yet and has credits - + // Pull-in a refresh. Try to pull-in refreshes as long it is possible. if (canPullIn) { - doRefresh(payload, time); - arCmdCounter[bank]++; + pulledin[bank]++; + pre = doRefresh(payload, time); + nrt = tRFCx; + if (pre) + nrt += controllerCore.config.memSpec.tRP; + nextRefTiming = nrt; nextState[bank] = ST_PULLIN; - nextRefTiming = tRFCx; } else { - // Saving value to be used by ST_ALIGN - alignValue[bank] = arCmdCounter[bank]; - nextState[bank] = ST_ALIGN; nextRefTiming = SC_ZERO_TIME; + nextState[bank] = ST_ALIGN; } break; case ST_SKIP: - // Skip Refresh. The arCmdCounter[bank] is used to skip the correct - // amount of refreshes - arCmdCounter[bank]--; - if (arCmdCounter[bank] == 0) { - nextState[bank] = ST_REFRESH; + // Skip the pulled-in refreshes. + if (pulledin[bank] == 0) { nextRefTiming = SC_ZERO_TIME; + nextState[bank] = ST_REFRESH; } else { - nextState[bank] = ST_SKIP; + pulledin[bank]--; nextRefTiming = tREFIx; + nextState[bank] = ST_SKIP; } break; case ST_POSTPONE: // Postpone Refresh. Delaying refreshes as long as there are pending // requests and credits to postpone. Should be followed by a burst // refresh. - if ((arCmdCounter[bank] == maxpostpone) || ((!pendingReq) - && !controllerCore.config.ControllerCoreRefForceMaxPostponeBurst)) { - // Burst conditions met - if (arCmdCounter[bank] < maxpostpone) { - // In case the burst was started by inactivity, need to also - // count the current REF - arCmdCounter[bank]++; - } - // Will start a burst next, so the value is saved to be used by - // ST_ALIGN - alignValue[bank] = arCmdCounter[bank]; - nextState[bank] = ST_BURST; + postponed[bank]++; + if ((postponed[bank] > maxpostpone) || (!pendingReq && !controllerCore.config.ControllerCoreRefForceMaxPostponeBurst)) { + // Burst triggered by inactivity or max postpone value reached. nextRefTiming = SC_ZERO_TIME; + nextState[bank] = ST_BURST; } else { - arCmdCounter[bank]++; - nextState[bank] = ST_POSTPONE; nextRefTiming = tREFIx; + nextState[bank] = ST_POSTPONE; } break; case ST_BURST: - // Burst Refresh. The arCmdCounter[bank] is used to issue the correct - // amount of refreshes - arCmdCounter[bank]--; - doRefresh(payload, time); - if (arCmdCounter[bank] == 0) { - // All bursts issued, next state will align to tREFIx - nextState[bank] = ST_ALIGN; + // Burst postponed refreshes. + pre = doRefresh(payload, time); + postponed[bank]--; + if (postponed[bank] == 0) { + // All refreshes issued, next state will align to tREFIx nextRefTiming = SC_ZERO_TIME; + nextState[bank] = ST_ALIGN; } else { + nrt = tRFCx; + if (pre) + nrt += controllerCore.config.memSpec.tRP; + nextRefTiming = nrt; nextState[bank] = ST_BURST; - nextRefTiming = tRFCx; } break; case ST_ALIGN: // Align Refresh. Adjusting the timing so the next REF timing will be - // a in a time multiple of tREFIx. + // a in a time multiple of tREFIx + nextRefTiming = tREFIx; + align = true; if (previousState[bank] == ST_PULLIN) { - nextRefTiming = tREFIx - (tRFCx * (alignValue[bank])); nextState[bank] = ST_SKIP; } else { - nextRefTiming = tREFIx - (tRFCx * (alignValue[bank] - 1)); nextState[bank] = ST_REFRESH; } break; default: - SC_REPORT_FATAL(this->name(), - "Invalid state in bankwise flexible refresh FSM. Stop."); + SC_REPORT_FATAL(this->name(), "Invalid state in bw flex. ref. FSM."); break; } - - planNextRefresh(bank, nextRefTiming); + planNextRefresh(bank, nextRefTiming, align); } -void RefreshManagerBankwise::planNextRefresh(Bank bank, sc_time nextRefTiming) +void RefreshManagerBankwise::planNextRefresh(Bank bank, sc_time nextRefTiming, bool align) { + if (align) { + nextPlannedRefreshs[bank] = trunc(nextPlannedRefreshs[bank].to_double() / tREFIx.to_double()) * tREFIx; + } nextPlannedRefreshs[bank] += nextRefTiming; controllerCore.controller.send(REFTrigger, nextPlannedRefreshs[bank], refreshPayloads[bank]); @@ -235,7 +242,7 @@ void RefreshManagerBankwise::planNextRefresh(Bank bank, sc_time nextRefTiming) void RefreshManagerBankwise::reInitialize(Bank bank, sc_time time) { nextPlannedRefreshs[bank] = clkAlign(time, Alignment::DOWN); - planNextRefresh(bank, tREFIx); + planNextRefresh(bank, tREFIx, true); } bool RefreshManagerBankwise::isInvalidated(tlm::tlm_generic_payload &payload, diff --git a/DRAMSys/library/src/controller/core/refresh/RefreshManagerBankwise.h b/DRAMSys/library/src/controller/core/refresh/RefreshManagerBankwise.h index c5959616..6b8558a1 100644 --- a/DRAMSys/library/src/controller/core/refresh/RefreshManagerBankwise.h +++ b/DRAMSys/library/src/controller/core/refresh/RefreshManagerBankwise.h @@ -38,9 +38,9 @@ #ifndef BANKWISEREFRESHMANAGER_H_ #define BANKWISEREFRESHMANAGER_H_ -#include "../../../common/dramExtension.h" -#include "../configuration/MemSpec.h" +//#include "../../../common/dramExtension.h" #include "IRefreshManager.h" +#include "../configuration/MemSpec.h" class ControllerCore; @@ -60,20 +60,22 @@ public: private: ControllerCore &controllerCore; RefreshTiming &timing; + std::map nextPlannedRefreshs; sc_time tREFIx; sc_time tRFCx; std::map refreshPayloads; - std::map nextPlannedRefreshs; - unsigned int maxpostpone = 0; - unsigned int maxpullin = 0; - std::map arCmdCounter; - std::map alignValue; + bool postponeEnabled; + bool pullInEnabled; + unsigned int maxpostpone; + unsigned int maxpullin; + std::map pulledin; + std::map postponed; std::map currentState; std::map previousState; std::map nextState; - void doRefresh(tlm::tlm_generic_payload &payload, sc_time time); - void planNextRefresh(Bank bank, sc_time nextRefTiming); + bool doRefresh(tlm::tlm_generic_payload &payload, sc_time time); + void planNextRefresh(Bank bank, sc_time time, bool align); void printDebugMessage(std::string message); };