Flexible Refresh Implementation
This commit is contained in:
@@ -9,7 +9,9 @@
|
||||
<PowerDownTimeout value="100" />
|
||||
<!-- Error Modelling -->
|
||||
<ControllerCoreDisableRefresh value="0"/>
|
||||
<ControllerCoreForceMaxRefPostpone value="0"/>
|
||||
<ControllerCoreForceMaxRefBurst value="0"/>
|
||||
<ControllerCoreEnableRefPostpone value="0"/>
|
||||
<ControllerCoreEnableRefPullIn value="0"/>
|
||||
<ControllerCoreMaxPostponedARCmd value="8"/>
|
||||
<ControllerCoreMaxPulledInARCmd value="8"/>
|
||||
</mcconfig>
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
<PowerDownTimeout value="100" />
|
||||
<!-- Error Modelling -->
|
||||
<ControllerCoreDisableRefresh value="0"/>
|
||||
<ControllerCoreForceMaxRefPostpone value="0"/>
|
||||
<ControllerCoreForceMaxRefBurst value="0"/>
|
||||
<ControllerCoreEnableRefPostpone value="0"/>
|
||||
<ControllerCoreEnableRefPullIn value="0"/>
|
||||
<ControllerCoreMaxPostponedARCmd value="8"/>
|
||||
<ControllerCoreMaxPulledInARCmd value="8"/>
|
||||
</mcconfig>
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
<PowerDownTimeout value="100" />
|
||||
<!-- Error Modelling -->
|
||||
<ControllerCoreDisableRefresh value="0"/>
|
||||
<ControllerCoreForceMaxRefPostpone value="0"/>
|
||||
<ControllerCoreForceMaxRefBurst value="0"/>
|
||||
<ControllerCoreEnableRefPostpone value="0"/>
|
||||
<ControllerCoreEnableRefPullIn value="0"/>
|
||||
<ControllerCoreMaxPostponedARCmd value="8"/>
|
||||
<ControllerCoreMaxPulledInARCmd value="8"/>
|
||||
</mcconfig>
|
||||
|
||||
@@ -9,8 +9,10 @@
|
||||
<PowerDownTimeout value="100" />
|
||||
<!-- Error Model: -->
|
||||
<ControllerCoreDisableRefresh value="0"/>
|
||||
<ControllerCoreForceMaxRefPostpone value="0"/>
|
||||
<ControllerCoreForceMaxRefBurst value="0"/>
|
||||
<ControllerCoreEnableRefPostpone value="0"/>
|
||||
<ControllerCoreEnableRefPullIn value="0"/>
|
||||
<ControllerCoreMaxPostponedARCmd value="8"/>
|
||||
<ControllerCoreMaxPulledInARCmd value="8"/>
|
||||
</mcconfig>
|
||||
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
<PowerDownTimeout value="100" />
|
||||
<!-- Error Modelling -->
|
||||
<ControllerCoreDisableRefresh value="0"/>
|
||||
<ControllerCoreForceMaxRefPostpone value="0"/>
|
||||
<ControllerCoreForceMaxRefBurst value="0"/>
|
||||
<ControllerCoreEnableRefPostpone value="0"/>
|
||||
<ControllerCoreEnableRefPullIn value="0"/>
|
||||
<ControllerCoreMaxPostponedARCmd value="8"/>
|
||||
<ControllerCoreMaxPulledInARCmd value="8"/>
|
||||
</mcconfig>
|
||||
|
||||
@@ -13,7 +13,9 @@
|
||||
<!-- Modes: NoStorage, Store (store data without errormodel), ErrorModel (store data with errormodel) -->
|
||||
<StoreMode value="NoStorage" />
|
||||
<ControllerCoreDisableRefresh value="0"/>
|
||||
<ControllerCoreForceMaxRefPostpone value="0"/>
|
||||
<ControllerCoreForceMaxRefBurst value="0"/>
|
||||
<ControllerCoreEnableRefPostpone value="0"/>
|
||||
<ControllerCoreEnableRefPullIn value="0"/>
|
||||
<ControllerCoreMaxPostponedARCmd value="8"/>
|
||||
<ControllerCoreMaxPulledInARCmd value="8"/>
|
||||
</mcconfig>
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Bank, tlm::tlm_generic_payload> 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_ */
|
||||
|
||||
10
README.md
10
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)
|
||||
|
||||
Reference in New Issue
Block a user