diff --git a/DRAMSys/library/resources/configs/mcconfigs/fifo.xml b/DRAMSys/library/resources/configs/mcconfigs/fifo.xml index 6264ac2c..c8252d2c 100644 --- a/DRAMSys/library/resources/configs/mcconfigs/fifo.xml +++ b/DRAMSys/library/resources/configs/mcconfigs/fifo.xml @@ -9,7 +9,9 @@ - + + + diff --git a/DRAMSys/library/resources/configs/mcconfigs/fifoStrict.xml b/DRAMSys/library/resources/configs/mcconfigs/fifoStrict.xml index 79dfe5d5..c49cb635 100644 --- a/DRAMSys/library/resources/configs/mcconfigs/fifoStrict.xml +++ b/DRAMSys/library/resources/configs/mcconfigs/fifoStrict.xml @@ -9,7 +9,9 @@ - + + + diff --git a/DRAMSys/library/resources/configs/mcconfigs/fifo_ecc.xml b/DRAMSys/library/resources/configs/mcconfigs/fifo_ecc.xml index 6264ac2c..c8252d2c 100644 --- a/DRAMSys/library/resources/configs/mcconfigs/fifo_ecc.xml +++ b/DRAMSys/library/resources/configs/mcconfigs/fifo_ecc.xml @@ -9,7 +9,9 @@ - + + + diff --git a/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs.xml b/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs.xml index 9a5d09d6..c008de01 100644 --- a/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs.xml +++ b/DRAMSys/library/resources/configs/mcconfigs/fr_fcfs.xml @@ -9,8 +9,10 @@ - + + + diff --git a/DRAMSys/library/resources/configs/mcconfigs/par_bs.xml b/DRAMSys/library/resources/configs/mcconfigs/par_bs.xml index 5d8d06ae..0985157f 100644 --- a/DRAMSys/library/resources/configs/mcconfigs/par_bs.xml +++ b/DRAMSys/library/resources/configs/mcconfigs/par_bs.xml @@ -9,7 +9,9 @@ - + + + diff --git a/DRAMSys/library/resources/configs/mcconfigs/sms.xml b/DRAMSys/library/resources/configs/mcconfigs/sms.xml index 943023fd..049b8a45 100644 --- a/DRAMSys/library/resources/configs/mcconfigs/sms.xml +++ b/DRAMSys/library/resources/configs/mcconfigs/sms.xml @@ -13,7 +13,9 @@ - + + + diff --git a/DRAMSys/library/src/controller/core/configuration/Configuration.cpp b/DRAMSys/library/src/controller/core/configuration/Configuration.cpp index 7000c1ae..93a1d523 100644 --- a/DRAMSys/library/src/controller/core/configuration/Configuration.cpp +++ b/DRAMSys/library/src/controller/core/configuration/Configuration.cpp @@ -202,8 +202,8 @@ void Configuration::setParameter(std::string name, std::string value) } else if (name == "ControllerCoreDisableRefresh") ControllerCoreDisableRefresh = string2bool(value); - else if (name == "ControllerCoreForceMaxRefPostpone") - ControllerCoreForceMaxRefPostpone = string2bool(value); + else if (name == "ControllerCoreForceMaxRefBurst") + ControllerCoreForceMaxRefBurst = string2bool(value); else if (name == "ControllerCoreEnableRefPostpone") { ControllerCoreEnableRefPostpone = string2bool(value); @@ -213,8 +213,19 @@ void Configuration::setParameter(std::string name, std::string value) SC_REPORT_FATAL("Configuration", (name + " requires memory type DDR3.").c_str()); } } + else if (name == "ControllerCoreEnableRefPullIn") + { + ControllerCoreEnableRefPullIn = string2bool(value); + // Refresh pull-in feature available for DDR3 only in the current + // version of DRAMsys. + if (ControllerCoreEnableRefPullIn && memSpec.MemoryType != "DDR3") { + SC_REPORT_FATAL("Configuration", (name + " requires memory type DDR3.").c_str()); + } + } else if (name == "ControllerCoreMaxPostponedARCmd") ControllerCoreMaxPostponedARCmd = string2int(value); + else if (name == "ControllerCoreMaxPulledInARCmd") + ControllerCoreMaxPulledInARCmd = string2int(value); else if (name == "ThermalSimulation") ThermalSimulation = string2bool(value); else if(name == "SimulationProgressBar") diff --git a/DRAMSys/library/src/controller/core/configuration/Configuration.h b/DRAMSys/library/src/controller/core/configuration/Configuration.h index 5de19ff8..a0c449be 100644 --- a/DRAMSys/library/src/controller/core/configuration/Configuration.h +++ b/DRAMSys/library/src/controller/core/configuration/Configuration.h @@ -83,9 +83,11 @@ struct Configuration bool Debug = false; unsigned int NumberOfMemChannels = 1; bool ControllerCoreDisableRefresh = false; - bool ControllerCoreForceMaxRefPostpone = false; + bool ControllerCoreForceMaxRefBurst = false; bool ControllerCoreEnableRefPostpone = false; + bool ControllerCoreEnableRefPullIn = false; unsigned int ControllerCoreMaxPostponedARCmd = 8; + unsigned int ControllerCoreMaxPulledInARCmd = 8; bool ThermalSimulation = false; bool SimulationProgressBar = false; unsigned int NumberOfDevicesOnDIMM = 1; diff --git a/DRAMSys/library/src/controller/core/refresh/RefreshManager.cpp b/DRAMSys/library/src/controller/core/refresh/RefreshManager.cpp index 18e74409..beb54cda 100644 --- a/DRAMSys/library/src/controller/core/refresh/RefreshManager.cpp +++ b/DRAMSys/library/src/controller/core/refresh/RefreshManager.cpp @@ -51,6 +51,10 @@ RefreshManager::RefreshManager(sc_module_name /*name*/, ControllerCore& controll { maxpostpone = controllerCore.config.ControllerCoreMaxPostponedARCmd; } + if (controllerCore.config.ControllerCoreEnableRefPullIn) + { + maxpullin = controllerCore.config.ControllerCoreMaxPulledInARCmd; + } for (Bank bank : controller.getBanks()) { setUpDummy(refreshPayloads[bank], bank); @@ -112,71 +116,134 @@ void RefreshManager::doRefresh(tlm::tlm_generic_payload& payload __attribute__(( controllerCore.controller.send(refreshAllMaster, refreshPayloads[Bank(0)]); } -//This function is sensitive to state transitions only. For multiple calls of this function we ensure that burst is only updated on a state change -void RefreshManager::evaluateBurstState() -{ - bool pendingReq = controllerCore.hasPendingRequests(); - if ((arCmdCounter == maxpostpone) || ((!pendingReq&&!burst) && !controllerCore.config.ControllerCoreForceMaxRefPostpone)) - { - burst = true; - if (arCmdCounter>1) //A single refresh is considered a special case of a burst. It's only necessary to align if the burst consists of more than 1 AR command - { - alignToTrefiNeeded=true; - alignToTrefiValue=arCmdCounter-1; //For a burst consisting of multiple AR the gaps between the start of the burst and the last AR must be subtracted in order to align the next burst to tREFI - } - } - if (arCmdCounter == 0) //Burst is done. All AR commands are issued already - { - burst = false; - } -} - -sc_time RefreshManager::alignToTrefi() -{ - if (alignToTrefiNeeded) //Alignment is only needed when the previous burst consisted of more than 1 AR command - { - alignToTrefiNeeded = false; //This happens only for the first AR of the burst that follows - return alignToTrefiValue*timing.tRFC; - } - else - { - return SC_ZERO_TIME; - } -} - -sc_time RefreshManager::getNextRefTiming() -{ - if (burst) - { - return timing.tRFC; - } - else - { - return timing.tREFI-alignToTrefi(); - } -} - -//Depending on burst state, either schedule a refresh or postpone it. Check burst state before and after triggering a refresh to check if state changes are needed void RefreshManager::scheduleRefresh(tlm::tlm_generic_payload& payload __attribute__((unused)), sc_time time) { sc_time nextRefTiming; + bool pendingReq = controllerCore.hasPendingRequests(); + bool canPostpone = pendingReq && (arCmdCounter < maxpostpone); + bool canPullIn = !pendingReq && (arCmdCounter < maxpullin); - if (!burst) + previousState = currentState; + currentState = nextState; + + switch(currentState) { - arCmdCounter++; + case ST_REFRESH: + // Regular Refresh. It's possible to migrate from this to the flexible refresh states + + assert(arCmdCounter == 0); // The arCmdCounter should always be equal to zero here + + if(canPostpone) + { + nextState = ST_POSTPONE; + nextRefTiming = SC_ZERO_TIME; + } + else if(canPullIn) + { + nextState = ST_PULLIN; + nextRefTiming = SC_ZERO_TIME; // Attempt to burst pull-in + } + else + { + doRefresh(payload, time); + nextRefTiming = timing.tREFI; + nextState = ST_REFRESH; + } + 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 + + if(canPullIn) + { + doRefresh(payload, time); + arCmdCounter++; + nextState = ST_PULLIN; + nextRefTiming = timing.tRFC; + } + else + { + alignValue = arCmdCounter; // Saving value to be used by ST_ALIGN + nextState = ST_ALIGN; + nextRefTiming = SC_ZERO_TIME; + } + break; + + case ST_SKIP: + // Skip Refresh. The arCmdCounter is used to skip the correct amount of refreshes + + arCmdCounter--; + if(arCmdCounter == 0) + { + nextState = ST_REFRESH; + nextRefTiming = SC_ZERO_TIME; + } + else + { + nextState = ST_SKIP; + nextRefTiming = timing.tREFI; + } + 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 == maxpostpone) || ((!pendingReq) && !controllerCore.config.ControllerCoreForceMaxRefBurst)) // Burst conditions met + { + if(arCmdCounter < maxpostpone) // In case the burst was started by inactivity, need to also count the current REF + { + arCmdCounter++; + } + alignValue = arCmdCounter; // Will start a burst next, so the value is saved to be used by ST_ALIGN + nextState = ST_BURST; + nextRefTiming = SC_ZERO_TIME; + } + else + { + arCmdCounter++; + nextState = ST_POSTPONE; + nextRefTiming = timing.tREFI; + } + break; + + case ST_BURST: + // Burst Refresh. The arCmdCounter is used to issue the correct amount of refreshes + + arCmdCounter--; + doRefresh(payload, time); + if(arCmdCounter == 0) // All bursts issued, next state will align to tREFI + { + nextState = ST_ALIGN; + nextRefTiming = timing.tREFI; + } + else + { + nextState = ST_BURST; + nextRefTiming = timing.tRFC; + } + break; + + case ST_ALIGN: + // Align Refresh. Adjusting the timing so the next REF timing will be a in a time multiple of tREFI + + if(previousState == ST_PULLIN) + { + nextRefTiming = timing.tREFI-(timing.tRFC*(alignValue)); + nextState = ST_SKIP; + } + else + { + nextRefTiming = timing.tREFI-(timing.tRFC*(alignValue-1)); + nextState = ST_REFRESH; + } + break; + + default: + SC_REPORT_FATAL(this->name(),"Invalid State in Flexible Refresh FSM. Stop."); + break; } - evaluateBurstState(); - - if (burst) - { - doRefresh(payload, time); - arCmdCounter--; - evaluateBurstState(); - } - - nextRefTiming = getNextRefTiming(); planNextRefresh(nextRefTiming); } diff --git a/DRAMSys/library/src/controller/core/refresh/RefreshManager.h b/DRAMSys/library/src/controller/core/refresh/RefreshManager.h index 2c701467..32216527 100644 --- a/DRAMSys/library/src/controller/core/refresh/RefreshManager.h +++ b/DRAMSys/library/src/controller/core/refresh/RefreshManager.h @@ -40,6 +40,15 @@ #include "IRefreshManager.h" #include "../configuration/MemSpec.h" +typedef enum +{ + ST_REFRESH = 0, + ST_PULLIN, + ST_POSTPONE, + ST_SKIP, + ST_BURST, + ST_ALIGN +} ref_fsm_state_t; class ControllerCore; @@ -59,19 +68,18 @@ private: RefreshTiming& timing; sc_time nextPlannedRefresh; std::map refreshPayloads; - unsigned int maxpostpone = 1; + unsigned int maxpostpone = 0; + unsigned int maxpullin = 0; unsigned int alignToTrefiValue = 0; unsigned int arCmdCounter = 0; - bool burst = false; - bool alignToTrefiNeeded = false; + unsigned int alignValue = 0; + ref_fsm_state_t currentState = ST_REFRESH; + ref_fsm_state_t previousState = ST_REFRESH; + ref_fsm_state_t nextState = ST_REFRESH; void doRefresh(tlm::tlm_generic_payload& payload, sc_time time); void planNextRefresh(sc_time time); void printDebugMessage(std::string message); - void burstRefresh(); - void evaluateBurstState(); - sc_time getNextRefTiming(); - sc_time alignToTrefi(); }; #endif /* REFRESHMANAGER_H_ */ diff --git a/README.md b/README.md index d5782fa4..13b08968 100644 --- a/README.md +++ b/README.md @@ -621,15 +621,19 @@ Below, the sub-configurations are listed and explained. - *ControllerCoreDisableRefresh* (boolean) - "1": disables refreshes - "0": normal operation (refreshes enabled) - - *ControllerCoreForceMaxRefPostpone* (boolean) - - "1": force the value on ControllerCoreMaxPostponedARCmd always. Requires ControllerCoreEnableRefPostpone to be enabled + - *ControllerCoreForceMaxRefBurst* (boolean) + - "1": always postpone, resulting in a ControllerCoreMaxPostponedARCmd burst - "0": normal operation - *ControllerCoreEnableRefPostpone* (boolean) - "1": enables the postpone refresh feature - "0": normal operation + - *ControllerCoreEnableRefPullIn* (boolean) + - "1": enables the pull-in refresh feature + - "0": normal operation - *ControllerCoreMaxPostponedARCmd* (unsigned int) - Max AR commands to be postponed. - + - *ControllerCoreMaxPulledInARCmd* (unsigned int) + - Max AR commands to be pulled-in. - **Trace Setups** - *clkMhz* (unsigned int)