diff --git a/DRAMSys/simulator/resources/configs/mcconfigs/fifoStrict.xml b/DRAMSys/simulator/resources/configs/mcconfigs/fifoStrict.xml
index 7ca1a824..79dfe5d5 100644
--- a/DRAMSys/simulator/resources/configs/mcconfigs/fifoStrict.xml
+++ b/DRAMSys/simulator/resources/configs/mcconfigs/fifoStrict.xml
@@ -9,4 +9,7 @@
+
+
+
diff --git a/DRAMSys/simulator/resources/resources.pri b/DRAMSys/simulator/resources/resources.pri
index e2e85724..71cc54aa 100644
--- a/DRAMSys/simulator/resources/resources.pri
+++ b/DRAMSys/simulator/resources/resources.pri
@@ -8,6 +8,7 @@ OTHER_FILES += resources/simulations/wideio-example.xml
OTHER_FILES += resources/simulations/wideio-ecc.xml
OTHER_FILES += resources/simulations/ddr3-ecc.xml
OTHER_FILES += resources/simulations/sms-example.xml
+OTHER_FILES += resources/simulations/ddr3_postpone_test.xml
# Simulator Files
OTHER_FILES += resources/configs/simulator/wideio.xml
@@ -69,6 +70,7 @@ OTHER_FILES += resources/traces/sms_t1.stl
OTHER_FILES += resources/traces/sms_t2.stl
OTHER_FILES += resources/traces/sms_t3.stl
OTHER_FILES += resources/traces/sms_t4.stl
+OTHER_FILES += resources/traces/ddr3_postpone_test.stl
# Memory Controller Configs
OTHER_FILES += resources/configs/mcconfigs/fifoStrict.xml
diff --git a/DRAMSys/simulator/resources/simulations/ddr3_postpone_test.xml b/DRAMSys/simulator/resources/simulations/ddr3_postpone_test.xml
new file mode 100644
index 00000000..bcaee4bf
--- /dev/null
+++ b/DRAMSys/simulator/resources/simulations/ddr3_postpone_test.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ddr3_postpone_test.stl
+
+
diff --git a/DRAMSys/simulator/src/controller/core/configuration/Configuration.cpp b/DRAMSys/simulator/src/controller/core/configuration/Configuration.cpp
index 6cb0ffb9..0d970ba4 100644
--- a/DRAMSys/simulator/src/controller/core/configuration/Configuration.cpp
+++ b/DRAMSys/simulator/src/controller/core/configuration/Configuration.cpp
@@ -202,6 +202,12 @@ 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 == "ControllerCoreEnableRefPostpone")
+ ControllerCoreEnableRefPostpone = string2bool(value);
+ else if (name == "ControllerCoreMaxPostponedARCmd")
+ ControllerCoreMaxPostponedARCmd = string2int(value);
else if (name == "ThermalSimulation")
ThermalSimulation = string2bool(value);
else if(name == "SimulationProgressBar")
diff --git a/DRAMSys/simulator/src/controller/core/configuration/Configuration.h b/DRAMSys/simulator/src/controller/core/configuration/Configuration.h
index 082d7530..5de19ff8 100644
--- a/DRAMSys/simulator/src/controller/core/configuration/Configuration.h
+++ b/DRAMSys/simulator/src/controller/core/configuration/Configuration.h
@@ -83,6 +83,9 @@ struct Configuration
bool Debug = false;
unsigned int NumberOfMemChannels = 1;
bool ControllerCoreDisableRefresh = false;
+ bool ControllerCoreForceMaxRefPostpone = false;
+ bool ControllerCoreEnableRefPostpone = false;
+ unsigned int ControllerCoreMaxPostponedARCmd = 8;
bool ThermalSimulation = false;
bool SimulationProgressBar = false;
unsigned int NumberOfDevicesOnDIMM = 1;
diff --git a/DRAMSys/simulator/src/controller/core/refresh/RefreshManager.cpp b/DRAMSys/simulator/src/controller/core/refresh/RefreshManager.cpp
index 742dfacc..bb5a7a4e 100644
--- a/DRAMSys/simulator/src/controller/core/refresh/RefreshManager.cpp
+++ b/DRAMSys/simulator/src/controller/core/refresh/RefreshManager.cpp
@@ -46,11 +46,15 @@ using namespace tlm;
RefreshManager::RefreshManager(sc_module_name /*name*/, ControllerCore& controller) :
controllerCore(controller), timing(controller.config.memSpec.refreshTimings[Bank(0)]), nextPlannedRefresh(SC_ZERO_TIME)
{
+ if (controllerCore.config.ControllerCoreEnableRefPostpone)
+ {
+ maxpostpone = controllerCore.config.ControllerCoreMaxPostponedARCmd;
+ }
for (Bank bank : controller.getBanks())
{
setUpDummy(refreshPayloads[bank], bank);
}
- planNextRefresh();
+ planNextRefresh(timing.tREFI);
}
RefreshManager::~RefreshManager()
@@ -63,8 +67,7 @@ bool RefreshManager::hasCollision(const ScheduledCommand& command)
return command.getStart() < controllerCore.state->getLastCommand(Command::AutoRefresh).getEnd() || command.getEnd() >= nextPlannedRefresh;
}
-//Schedule and trigger the refresh and plan the next one. AutoRefresh and PrechargeAll are scheduled just once per refresh period.
-void RefreshManager::scheduleRefresh(tlm::tlm_generic_payload& payload __attribute__((unused)), sc_time time)
+void RefreshManager::doRefresh(tlm::tlm_generic_payload& payload __attribute__((unused)), sc_time time)
{
sc_assert(!isInvalidated(payload, time));
@@ -99,20 +102,96 @@ void RefreshManager::scheduleRefresh(tlm::tlm_generic_payload& payload __attribu
controllerCore.state->change(refreshAllMaster);
DramExtension::getExtension(refreshPayloads[Bank(0)]).incrementRow();
controllerCore.controller.send(refreshAllMaster, refreshPayloads[Bank(0)]);
-
- planNextRefresh();
}
-void RefreshManager::planNextRefresh()
+bool RefreshManager::pendingRequests()
{
- nextPlannedRefresh += timing.tREFI;
+ for (Bank bank : controllerCore.getBanks())
+ {
+ if (controllerCore.numberOfPayloads[bank] != 0)
+ return true;
+ }
+ return false;
+}
+
+//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 = pendingRequests();
+
+ 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;
+
+ if (!burst)
+ {
+ arCmdCounter++;
+ }
+
+ evaluateBurstState();
+
+ if (burst)
+ {
+ doRefresh(payload, time);
+ arCmdCounter--;
+ evaluateBurstState();
+ }
+
+ nextRefTiming = getNextRefTiming();
+ planNextRefresh(nextRefTiming);
+}
+
+void RefreshManager::planNextRefresh(sc_time nextRefTiming)
+{
+ nextPlannedRefresh += nextRefTiming;
controllerCore.controller.send(REFTrigger, nextPlannedRefresh, refreshPayloads[Bank(0)]);
}
void RefreshManager::reInitialize(Bank /*bank*/, sc_time time)
{
nextPlannedRefresh = clkAlign(time, Alignment::DOWN);
- planNextRefresh();
+ planNextRefresh(timing.tREFI);
}
bool RefreshManager::isInvalidated(tlm::tlm_generic_payload& payload __attribute__((unused)), sc_time time)
diff --git a/DRAMSys/simulator/src/controller/core/refresh/RefreshManager.h b/DRAMSys/simulator/src/controller/core/refresh/RefreshManager.h
index 0b24236e..ce89474f 100644
--- a/DRAMSys/simulator/src/controller/core/refresh/RefreshManager.h
+++ b/DRAMSys/simulator/src/controller/core/refresh/RefreshManager.h
@@ -59,9 +59,20 @@ private:
RefreshTiming& timing;
sc_time nextPlannedRefresh;
std::map refreshPayloads;
+ unsigned int maxpostpone = 1;
+ unsigned int alignToTrefiValue = 0;
+ unsigned int arCmdCounter = 0;
+ bool burst = false;
+ bool alignToTrefiNeeded = false;
- void planNextRefresh();
+ void doRefresh(tlm::tlm_generic_payload& payload, sc_time time);
+ void planNextRefresh(sc_time time);
void printDebugMessage(std::string message);
+ bool pendingRequests();
+ void burstRefresh();
+ void evaluateBurstState();
+ sc_time getNextRefTiming();
+ sc_time alignToTrefi();
};
#endif /* REFRESHMANAGER_H_ */
diff --git a/DRAMSys/simulator/src/controller/core/scheduling/checker/RefreshChecker.cpp b/DRAMSys/simulator/src/controller/core/scheduling/checker/RefreshChecker.cpp
index 111e3d31..dd6d3869 100644
--- a/DRAMSys/simulator/src/controller/core/scheduling/checker/RefreshChecker.cpp
+++ b/DRAMSys/simulator/src/controller/core/scheduling/checker/RefreshChecker.cpp
@@ -70,6 +70,7 @@ void RefreshChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
}
else if (lastCommandOnBank.getCommand() == Command::AutoRefresh)
{
+ command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tRFC);
}
else
reportFatal("Refresh Checker", "Refresh can not follow " + commandToString(lastCommandOnBank.getCommand()));
@@ -108,6 +109,7 @@ void RefreshChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
}
else if (lastCommand.getCommand() == Command::AutoRefresh)
{
+ command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tRFC);
}
else
reportFatal("Refresh Checker", "Refresh can not follow " + commandToString(lastCommand.getCommand()));
diff --git a/README.md b/README.md
index 75ce2bc9..6025bcc0 100644
--- a/README.md
+++ b/README.md
@@ -741,6 +741,15 @@ 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
+ - "0": normal operation
+ - *ControllerCoreEnableRefPostpone* (boolean)
+ - "1": enables the postpone refresh feature
+ - "0": normal operation
+ - *ControllerCoreMaxPostponedARCmd* (unsigned int)
+ - Max AR commands to be postponed.
+
- **Trace Setups**
- *clkMhz* (unsigned int)