Improved flexible refresh, implemented first version of bankwise flexible refresh.

This commit is contained in:
Lukas Steiner
2019-10-06 18:56:13 +02:00
parent aa6a205872
commit d1f6bc6233
6 changed files with 203 additions and 61 deletions

View File

@@ -82,6 +82,11 @@ Rank BankMachine::getRank()
return rank;
}
BankGroup BankMachine::getBankGroup()
{
return bankgroup;
}
Bank BankMachine::getBank()
{
return bank;

View File

@@ -65,6 +65,7 @@ public:
void block();
Rank getRank();
BankGroup getBankGroup();
Bank getBank();
Row getOpenRow();
BmState getState();

View File

@@ -64,56 +64,68 @@ sc_time RefreshManager::start()
if (sc_time_stamp() >= timeForNextTrigger)
{
sc_time delay;
if (state == RmState::IDLE)
if (state == RmState::Regular)
{
if (flexibleCounter != maxPostponed || isPulledinRefresh)
bool forcedRefresh = (flexibilityCounter == maxPostponed);
if (!forcedRefresh)
{
for (auto it : bankMachines)
{
if (!it->isIdle())
{
if (!isPulledinRefresh)
flexibleCounter++;
isPulledinRefresh = false;
flexibilityCounter++;
timeForNextTrigger += memSpec->getRefreshIntervalAB();
return timeForNextTrigger - sc_time_stamp();
}
}
}
else
else // regular refresh that cannot be postponed -> force precharge
{
for (auto it : bankMachines)
it->block();
}
// TODO: If we do not block the bankmachines we have to check this each time
bool doPrecharge = false;
for (auto it : bankMachines)
{
if (it->getState() == BmState::Activated)
doPrecharge = true;
{
nextCommand = Command::PREA;
delay = checker->delayToSatisfyConstraints(Command::PREA, rank, BankGroup(0), Bank(0));
timeToSchedule = sc_time_stamp() + delay;
return delay;
}
}
if (doPrecharge)
{
delay = checker->delayToSatisfyConstraints(Command::PREA, rank, BankGroup(0), Bank(0));
nextCommand = Command::PREA;
}
else
{
delay = checker->delayToSatisfyConstraints(Command::REFA, rank, BankGroup(0), Bank(0));
nextCommand = Command::REFA;
if (flexibleCounter == maxPostponed)
state = RmState::PRECHARGED;
}
}
else // if (state == RmState::PRECHARGED)
{
delay = checker->delayToSatisfyConstraints(Command::REFA, rank, BankGroup(0), Bank(0));
if (forcedRefresh) // if refresh is forced all banks will remain precharged state
state = RmState::Precharged;
nextCommand = Command::REFA;
delay = checker->delayToSatisfyConstraints(Command::REFA, rank, BankGroup(0), Bank(0));
timeToSchedule = sc_time_stamp() + delay;
return delay;
}
else if (state == RmState::Pulledin)
{
for (auto it : bankMachines)
{
if (!it->isIdle())
{
state = RmState::Regular;
timeForNextTrigger += memSpec->getRefreshIntervalAB();
return timeForNextTrigger - sc_time_stamp();
}
}
delay = checker->delayToSatisfyConstraints(Command::REFA, rank, BankGroup(0), Bank(0));
timeToSchedule = sc_time_stamp() + delay;
return delay;
}
else // if (state == RmState::Precharged)
{
nextCommand = Command::REFA;
delay = checker->delayToSatisfyConstraints(Command::REFA, rank, BankGroup(0), Bank(0));
timeToSchedule = sc_time_stamp() + delay;
return delay;
}
timeToSchedule = sc_time_stamp() + delay;
return delay;
}
else
return timeForNextTrigger - sc_time_stamp();
@@ -123,23 +135,24 @@ void RefreshManager::updateState(Command command, tlm_generic_payload *)
{
if (command == Command::REFA)
{
state = RmState::IDLE;
if (isPulledinRefresh)
flexibleCounter--;
if (state == RmState::Pulledin)
flexibilityCounter--;
else
isPulledinRefresh = true;
state = RmState::Pulledin;
if (flexibleCounter == maxPulledin)
if ((flexibilityCounter == maxPulledin) ||
((sc_time_stamp() + memSpec->getExecutionTime(Command::REFA)
>= (timeForNextTrigger + memSpec->getRefreshIntervalAB()))))
{
isPulledinRefresh = false;
state = RmState::Regular;
timeForNextTrigger += memSpec->getRefreshIntervalAB();
}
}
else if (command == Command::PREA)
{
// if PREA was successful we will refresh in any case
for (auto it : bankMachines)
it->block();
state = RmState::PRECHARGED;
state = RmState::Precharged;
}
}

View File

@@ -52,7 +52,7 @@ public:
void updateState(Command, tlm_generic_payload *);
private:
enum class RmState {IDLE, PRECHARGED} state = RmState::IDLE;
enum class RmState {Regular, Precharged, Pulledin} state = RmState::Regular;
const MemSpec *memSpec;
std::vector<BankMachine *> bankMachines;
tlm_generic_payload refreshPayload;
@@ -62,10 +62,9 @@ private:
CheckerIF *checker;
Command nextCommand;
int flexibleCounter = 0;
int flexibilityCounter = 0;
int maxPostponed = 0;
int maxPulledin = 0;
bool isPulledinRefresh = false;
};
#endif // REFRESHMANAGER_H

View File

@@ -40,19 +40,27 @@
RefreshManagerBankwise::RefreshManagerBankwise(std::vector<BankMachine *> &bankMachines, Rank rank, CheckerIF *checker)
: bankMachines(bankMachines), rank(rank), checker(checker)
{
memSpec = Configuration::getInstance().memSpec;
Configuration &config = Configuration::getInstance();
memSpec = config.memSpec;
timeForNextTrigger = memSpec->getRefreshIntervalPB();
refreshPayloads = std::vector<tlm_generic_payload>(memSpec->BanksPerRank);
//states = std::vector<RmState>(memSpec->NumberOfBanks, RmState::IDLE);
for (unsigned bankID = 0; bankID < memSpec->BanksPerRank; bankID++)
{
setUpDummy(refreshPayloads[bankID], rank, bankMachines[bankID]->getBank());
remainingBankMachines.push_back(bankMachines[bankID]);
}
if (config.ControllerCoreRefEnablePostpone)
maxPostponed = config.ControllerCoreRefMaxPostponed * memSpec->BanksPerRank;
if (config.ControllerCoreRefEnablePullIn)
maxPulledin = -(config.ControllerCoreRefMaxPulledIn * memSpec->BanksPerRank);
}
std::pair<Command, tlm_generic_payload *> RefreshManagerBankwise::getNextCommand()
{
if (sc_time_stamp() == timeToSchedule)
return std::pair<Command, tlm_generic_payload *>(nextCommand, &refreshPayloads[nextBankID]);
return std::pair<Command, tlm_generic_payload *>(nextCommand, &refreshPayloads[currentBankMachine->getBank().ID() % memSpec->BanksPerRank]);
else
return std::pair<Command, tlm_generic_payload *>(Command::NOP, nullptr);
}
@@ -62,33 +70,140 @@ sc_time RefreshManagerBankwise::start()
if (sc_time_stamp() >= timeForNextTrigger)
{
sc_time delay;
bankMachines[nextBankID]->block();
if (bankMachines[nextBankID]->getState() == BmState::Activated)
if (state == RmState::Regular)
{
delay = checker->delayToSatisfyConstraints(Command::PRE, rank, BankGroup(0),
bankMachines[nextBankID]->getBank());
nextCommand = Command::PRE;
}
else
{
delay = checker->delayToSatisfyConstraints(Command::REFB, rank, BankGroup(0),
bankMachines[nextBankID]->getBank());
bool allBanksBusy = true;
currentIterator = remainingBankMachines.begin();
currentBankMachine = *remainingBankMachines.begin();
for (auto it = remainingBankMachines.begin(); it != remainingBankMachines.end(); it++)
{
if ((*it)->isIdle())
{
currentIterator = it;
currentBankMachine = *it;
allBanksBusy = false;
break;
}
}
bool forcedRefresh = (flexibilityCounter == maxPostponed);
if (allBanksBusy && !forcedRefresh)
{
flexibilityCounter++;
timeForNextTrigger += memSpec->getRefreshIntervalPB();
return timeForNextTrigger - sc_time_stamp();
}
else if (forcedRefresh)
currentBankMachine->block();
if (currentBankMachine->getState() == BmState::Activated)
{
nextCommand = Command::PRE;
delay = checker->delayToSatisfyConstraints(Command::PRE, rank,
currentBankMachine->getBankGroup(), currentBankMachine->getBank());
timeToSchedule = sc_time_stamp() + delay;
return delay;
}
if (forcedRefresh)
state = RmState::Precharged;
nextCommand = Command::REFB;
delay = checker->delayToSatisfyConstraints(Command::REFB, rank,
currentBankMachine->getBankGroup(), currentBankMachine->getBank());
timeToSchedule = sc_time_stamp() + delay;
return delay;
}
else if (state == RmState::Pulledin)
{
bool allBanksBusy = true;
for (auto it = remainingBankMachines.begin(); it != remainingBankMachines.end(); it++)
{
if ((*it)->isIdle())
{
currentIterator = it;
currentBankMachine = *it;
allBanksBusy = false;
break;
}
}
if (allBanksBusy)
{
state = RmState::Regular;
timeForNextTrigger += memSpec->getRefreshIntervalPB();
return timeForNextTrigger - sc_time_stamp();
}
if (currentBankMachine->getState() == BmState::Activated)
{
nextCommand = Command::PRE;
delay = checker->delayToSatisfyConstraints(Command::PRE, rank,
currentBankMachine->getBankGroup(), currentBankMachine->getBank());
}
else
{
nextCommand = Command::REFB;
delay = checker->delayToSatisfyConstraints(Command::REFB, rank,
currentBankMachine->getBankGroup(), currentBankMachine->getBank());
}
timeToSchedule = sc_time_stamp() + delay;
return delay;
}
else // if (state == RmState::Precharged)
{
nextCommand = Command::REFB;
delay = checker->delayToSatisfyConstraints(Command::REFB, rank,
currentBankMachine->getBankGroup(), currentBankMachine->getBank());
timeToSchedule = sc_time_stamp() + delay;
return delay;
}
timeToSchedule = sc_time_stamp() + delay;
return delay;
}
else
return timeForNextTrigger - sc_time_stamp();
}
void RefreshManagerBankwise::updateState(Command command, tlm_generic_payload *)
void RefreshManagerBankwise::updateState(Command command, tlm_generic_payload *payload)
{
// distinguish between PRE from BM and RM!!!!!
if (command == Command::REFB)
{
//state = RmState::IDLE;
nextBankID = (nextBankID + 1) % memSpec->BanksPerRank;
timeForNextTrigger += memSpec->getRefreshIntervalPB();
remainingBankMachines.erase(currentIterator);
if (remainingBankMachines.empty())
{
for (unsigned bankID = 0; bankID < memSpec->BanksPerRank; bankID++)
remainingBankMachines.push_back(bankMachines[bankID]);
}
if (state == RmState::Pulledin)
flexibilityCounter--;
else
state = RmState::Pulledin;
if ((flexibilityCounter == maxPulledin) ||
((sc_time_stamp() + memSpec->getExecutionTime(Command::REFB)
>= (timeForNextTrigger + memSpec->getRefreshIntervalPB()))))
{
state = RmState::Regular;
timeForNextTrigger += memSpec->getRefreshIntervalPB();
}
}
else if (command == Command::PRE && nextCommand == Command::PRE)
{
// TODO: remove all this
if (DramExtension::getBank(payload) == currentBankMachine->getBank())
{
if ((sc_time_stamp() + memSpec->getExecutionTime(Command::PRE)
>= (timeForNextTrigger + memSpec->getRefreshIntervalPB())))
{
state = RmState::Regular;
timeForNextTrigger += memSpec->getRefreshIntervalAB();
}
else
{
currentBankMachine->block();
state = RmState::Precharged;
}
}
}
//else if (command == Command::PRE) do nothing?
}

View File

@@ -40,7 +40,9 @@
#include "../BankMachine.h"
#include <vector>
#include <utility>
#include <map>
#include <list>
using namespace tlm;
class RefreshManagerBankwise final : public RefreshManagerIF
{
@@ -52,7 +54,7 @@ public:
void updateState(Command, tlm_generic_payload *);
private:
enum class RmState {IDLE, PRECHARGED} state = RmState::IDLE;
enum class RmState {Regular, Precharged, Pulledin} state = RmState::Regular;
const MemSpec *memSpec;
std::vector<BankMachine *> bankMachines;
std::vector<tlm_generic_payload> refreshPayloads;
@@ -61,7 +63,14 @@ private:
Rank rank;
CheckerIF *checker;
Command nextCommand;
unsigned nextBankID = 0;
std::list<BankMachine *> remainingBankMachines;
std::list<BankMachine *>::iterator currentIterator;
BankMachine *currentBankMachine;
int flexibilityCounter = 0;
int maxPostponed = 0;
int maxPulledin = 0;
};
#endif // REFRESHMANAGERBANKWISE_H