Flexible Refresh Implementation

This commit is contained in:
Ana Mativi
2018-01-18 19:25:37 +01:00
parent f6194d28fd
commit de0fca0148
11 changed files with 180 additions and 76 deletions

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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")

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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_ */

View File

@@ -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)