Improved flexible refresh, implemented first version of bankwise flexible refresh.
This commit is contained in:
@@ -82,6 +82,11 @@ Rank BankMachine::getRank()
|
||||
return rank;
|
||||
}
|
||||
|
||||
BankGroup BankMachine::getBankGroup()
|
||||
{
|
||||
return bankgroup;
|
||||
}
|
||||
|
||||
Bank BankMachine::getBank()
|
||||
{
|
||||
return bank;
|
||||
|
||||
@@ -65,6 +65,7 @@ public:
|
||||
void block();
|
||||
|
||||
Rank getRank();
|
||||
BankGroup getBankGroup();
|
||||
Bank getBank();
|
||||
Row getOpenRow();
|
||||
BmState getState();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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?
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user