Add flexible same-bank refresh management.
This commit is contained in:
@@ -140,16 +140,21 @@ Row BankMachine::getOpenRow() const
|
||||
return openRow;
|
||||
}
|
||||
|
||||
BankMachine::State BankMachine::getState() const
|
||||
{
|
||||
return state;
|
||||
}
|
||||
|
||||
bool BankMachine::isIdle() const
|
||||
{
|
||||
return (currentPayload == nullptr);
|
||||
}
|
||||
|
||||
bool BankMachine::isActivated() const
|
||||
{
|
||||
return state == State::Activated;
|
||||
}
|
||||
|
||||
bool BankMachine::isPrecharged() const
|
||||
{
|
||||
return state == State::Precharged;
|
||||
}
|
||||
|
||||
BankMachineOpen::BankMachineOpen(SchedulerIF *scheduler, CheckerIF *checker, Bank bank)
|
||||
: BankMachine(scheduler, checker, bank) {}
|
||||
|
||||
|
||||
@@ -52,24 +52,23 @@ public:
|
||||
void updateState(Command);
|
||||
void block();
|
||||
|
||||
enum class State {Precharged, Activated};
|
||||
|
||||
Rank getRank() const;
|
||||
BankGroup getBankGroup() const;
|
||||
Bank getBank() const;
|
||||
Row getOpenRow() const;
|
||||
State getState() const;
|
||||
bool isIdle() const;
|
||||
bool isActivated() const;
|
||||
bool isPrecharged() const;
|
||||
uint64_t getRefreshManagementCounter() const;
|
||||
|
||||
protected:
|
||||
enum class State {Precharged, Activated} state = State::Precharged;
|
||||
BankMachine(SchedulerIF *, CheckerIF *, Bank);
|
||||
const MemSpec* memSpec;
|
||||
tlm::tlm_generic_payload *currentPayload = nullptr;
|
||||
SchedulerIF *scheduler;
|
||||
CheckerIF *checker;
|
||||
Command nextCommand = Command::NOP;
|
||||
State state = State::Precharged;
|
||||
Row openRow;
|
||||
sc_core::sc_time timeToSchedule = sc_core::sc_max_time();
|
||||
Rank rank = Rank(0);
|
||||
|
||||
@@ -99,7 +99,7 @@ sc_time PowerDownManagerStaggered::start()
|
||||
nextCommand = Command::PDEP;
|
||||
for (auto it : bankMachinesOnRank)
|
||||
{
|
||||
if (it->getState() == BankMachine::State::Activated)
|
||||
if (it->isActivated())
|
||||
{
|
||||
nextCommand = Command::PDEA;
|
||||
break;
|
||||
|
||||
@@ -117,7 +117,7 @@ sc_time RefreshManagerPerBank::start()
|
||||
}
|
||||
else
|
||||
{
|
||||
if (currentBankMachine->getState() == BankMachine::State::Activated)
|
||||
if (currentBankMachine->isActivated())
|
||||
nextCommand = Command::PRE;
|
||||
else
|
||||
{
|
||||
@@ -158,7 +158,7 @@ sc_time RefreshManagerPerBank::start()
|
||||
}
|
||||
else
|
||||
{
|
||||
if (currentBankMachine->getState() == BankMachine::State::Activated)
|
||||
if (currentBankMachine->isActivated())
|
||||
nextCommand = Command::PRE;
|
||||
else
|
||||
nextCommand = Command::REFB;
|
||||
|
||||
@@ -73,6 +73,8 @@ RefreshManagerSameBank::RefreshManagerSameBank(std::vector<BankMachine *> &bankM
|
||||
|
||||
maxPostponed = static_cast<int>(config.refreshMaxPostponed * memSpec->banksPerGroup);
|
||||
maxPulledin = -static_cast<int>(config.refreshMaxPulledin * memSpec->banksPerGroup);
|
||||
|
||||
refreshManagement = config.refreshManagement;
|
||||
}
|
||||
|
||||
CommandTuple::Type RefreshManagerSameBank::getNextCommand()
|
||||
@@ -102,7 +104,7 @@ sc_time RefreshManagerSameBank::start()
|
||||
if (state == State::Regular)
|
||||
{
|
||||
bool forcedRefresh = (flexibilityCounter == maxPostponed);
|
||||
bool allBanksBusy = true;
|
||||
bool allGroupsBusy = true;
|
||||
|
||||
if (!skipSelection)
|
||||
{
|
||||
@@ -120,31 +122,31 @@ sc_time RefreshManagerSameBank::start()
|
||||
}
|
||||
if (!groupIsBusy)
|
||||
{
|
||||
allBanksBusy = false;
|
||||
allGroupsBusy = false;
|
||||
currentIterator = bankIt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (allBanksBusy && !forcedRefresh)
|
||||
if (allGroupsBusy && !forcedRefresh)
|
||||
{
|
||||
flexibilityCounter++;
|
||||
timeForNextTrigger += memSpec->getRefreshIntervalSB();
|
||||
return timeForNextTrigger;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextCommand = Command::REFSB;
|
||||
for (auto it : *currentIterator)
|
||||
{
|
||||
if (it->getState() == BankMachine::State::Activated)
|
||||
if (it->isActivated())
|
||||
{
|
||||
nextCommand = Command::PRESB;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// only check for forced refresh, also block for PRESB
|
||||
if (nextCommand == Command::REFSB && forcedRefresh)
|
||||
{
|
||||
for (auto it : *currentIterator)
|
||||
@@ -159,7 +161,7 @@ sc_time RefreshManagerSameBank::start()
|
||||
}
|
||||
else // if (state == RmState::Pulledin)
|
||||
{
|
||||
bool allBanksBusy = true;
|
||||
bool allGroupsBusy = true;
|
||||
|
||||
currentIterator = remainingBankMachines.begin();
|
||||
for (auto bankIt = remainingBankMachines.begin(); bankIt != remainingBankMachines.end(); bankIt++)
|
||||
@@ -175,24 +177,23 @@ sc_time RefreshManagerSameBank::start()
|
||||
}
|
||||
if (!groupIsBusy)
|
||||
{
|
||||
allBanksBusy = false;
|
||||
allGroupsBusy = false;
|
||||
currentIterator = bankIt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (allBanksBusy)
|
||||
if (allGroupsBusy)
|
||||
{
|
||||
state = State::Regular;
|
||||
timeForNextTrigger += memSpec->getRefreshIntervalSB();
|
||||
return timeForNextTrigger;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextCommand = Command::REFSB;
|
||||
for (auto it : *currentIterator)
|
||||
{
|
||||
if (it->getState() == BankMachine::State::Activated)
|
||||
if (it->isActivated())
|
||||
{
|
||||
nextCommand = Command::PRESB;
|
||||
break;
|
||||
@@ -205,49 +206,83 @@ sc_time RefreshManagerSameBank::start()
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if (refreshManagement)
|
||||
{
|
||||
bool RFMRequired = false;
|
||||
if (Configuration::getInstance().refreshManagement == true)
|
||||
bool mmtReached = false;
|
||||
std::vector<std::list<std::vector<BankMachine*>>::iterator> imtCandidates;
|
||||
|
||||
for (auto bankIt = allBankMachines.begin(); bankIt != allBankMachines.end(); bankIt++)
|
||||
{
|
||||
for (auto bankIt = allBankMachines.begin(); bankIt != allBankMachines.end(); bankIt++)
|
||||
for (auto groupIt: *bankIt)
|
||||
{
|
||||
for (auto bm : *bankIt)
|
||||
if (groupIt->getRefreshManagementCounter() >= memSpec->getRAAMMT())
|
||||
{
|
||||
uint64_t threshold = memSpec->getRAAIMT() * memSpec->getRAAMMT();
|
||||
if (bm->getRefreshManagementCounter() >= threshold)
|
||||
mmtReached = true;
|
||||
currentIterator = bankIt;
|
||||
break;
|
||||
}
|
||||
else if (groupIt->getRefreshManagementCounter() >= memSpec->getRAAMMT())
|
||||
{
|
||||
imtCandidates.emplace_back(currentIterator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mmtReached)
|
||||
{
|
||||
nextCommand = Command::RFMSB;
|
||||
for (auto groupIt: *currentIterator)
|
||||
{
|
||||
groupIt->block();
|
||||
if (groupIt->isActivated())
|
||||
nextCommand = Command::PRESB;
|
||||
}
|
||||
timeToSchedule = checker->timeToSatisfyConstraints(nextCommand,
|
||||
&refreshPayloads[currentIterator->front()->getBank().ID() % memSpec->banksPerGroup]);
|
||||
return timeToSchedule;
|
||||
}
|
||||
else if (!imtCandidates.empty())
|
||||
{
|
||||
// search for IMT candidates and check if all banks idle
|
||||
bool allGroupsBusy = true;
|
||||
for (auto candidateIt: imtCandidates)
|
||||
{
|
||||
bool groupIsBusy = false;
|
||||
for (auto groupIt: *candidateIt)
|
||||
{
|
||||
if (!groupIt->isIdle())
|
||||
{
|
||||
RFMRequired = true;
|
||||
currentIterator = bankIt;
|
||||
groupIsBusy = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (RFMRequired)
|
||||
{
|
||||
nextCommand = Command::RFMSB;
|
||||
for (auto it : *currentIterator)
|
||||
{
|
||||
if (it->getState() == BankMachine::State::Activated)
|
||||
if (!groupIsBusy)
|
||||
{
|
||||
nextCommand = Command::PRESB;
|
||||
allGroupsBusy = false;
|
||||
currentIterator = candidateIt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it : *currentIterator)
|
||||
it->block();
|
||||
|
||||
timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, &refreshPayloads[currentIterator->front()->getBank().ID() % memSpec->banksPerGroup]);
|
||||
return timeToSchedule;
|
||||
}
|
||||
else
|
||||
{
|
||||
return timeForNextTrigger;
|
||||
if (!allGroupsBusy)
|
||||
{
|
||||
nextCommand = Command::RFMSB;
|
||||
for (auto it: *currentIterator)
|
||||
{
|
||||
if (it->isActivated())
|
||||
{
|
||||
nextCommand = Command::PRESB;
|
||||
break;
|
||||
}
|
||||
}
|
||||
timeToSchedule = checker->timeToSatisfyConstraints(nextCommand,
|
||||
&refreshPayloads[currentIterator->front()->getBank().ID() % memSpec->banksPerGroup]);
|
||||
return timeToSchedule;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return timeForNextTrigger;
|
||||
}
|
||||
|
||||
void RefreshManagerSameBank::updateState(Command command)
|
||||
|
||||
@@ -74,6 +74,8 @@ private:
|
||||
|
||||
bool sleeping = false;
|
||||
bool skipSelection = false;
|
||||
|
||||
bool refreshManagement = false;
|
||||
};
|
||||
|
||||
#endif // REFRESHMANAGERSAMEBANK_H
|
||||
|
||||
@@ -88,7 +88,7 @@ tlm_generic_payload *SchedulerFrFcfs::getNextRequest(BankMachine *bankMachine) c
|
||||
unsigned bankID = bankMachine->getBank().ID();
|
||||
if (!buffer[bankID].empty())
|
||||
{
|
||||
if (bankMachine->getState() == BankMachine::State::Activated)
|
||||
if (bankMachine->isActivated())
|
||||
{
|
||||
// Search for row hit
|
||||
Row openRow = bankMachine->getOpenRow();
|
||||
|
||||
@@ -89,7 +89,7 @@ tlm_generic_payload *SchedulerFrFcfsGrp::getNextRequest(BankMachine *bankMachine
|
||||
unsigned bankID = bankMachine->getBank().ID();
|
||||
if (!buffer[bankID].empty())
|
||||
{
|
||||
if (bankMachine->getState() == BankMachine::State::Activated)
|
||||
if (bankMachine->isActivated())
|
||||
{
|
||||
// Filter all row hits
|
||||
Row openRow = bankMachine->getOpenRow();
|
||||
|
||||
Reference in New Issue
Block a user