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)