Implemented first version of flexible refresh (only REFA).
This commit is contained in:
@@ -53,11 +53,10 @@ Controller::Controller(sc_module_name name) :
|
||||
GenericController(name)
|
||||
{
|
||||
SC_METHOD(controllerMethod);
|
||||
sensitive << beginReqEvent << endRespEvent << bankMachineEvent
|
||||
<< refreshEvent << dataResponseEventQueue;
|
||||
sensitive << beginReqEvent << endRespEvent << controllerEvent << dataResponseEventQueue;
|
||||
dont_initialize();
|
||||
|
||||
Configuration config = Configuration::getInstance();
|
||||
Configuration &config = Configuration::getInstance();
|
||||
MemSpec *memSpec = config.memSpec;
|
||||
maxNumberOfPayloads = config.MaxNrOfTransactions;
|
||||
|
||||
@@ -127,7 +126,7 @@ Controller::Controller(sc_module_name name) :
|
||||
RefreshManagerIF *manager = new RefreshManagerBankwise
|
||||
(bankMachinesOnRank[rankID], Rank(rankID), checker);
|
||||
refreshManagers.push_back(manager);
|
||||
refreshEvent.notify(manager->start());
|
||||
controllerEvent.notify(manager->start());
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -137,7 +136,7 @@ Controller::Controller(sc_module_name name) :
|
||||
RefreshManagerIF *manager = new RefreshManager
|
||||
(bankMachinesOnRank[rankID], Rank(rankID), checker);
|
||||
refreshManagers.push_back(manager);
|
||||
refreshEvent.notify(manager->start());
|
||||
controllerEvent.notify(manager->start());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,18 +189,22 @@ void Controller::controllerMethod()
|
||||
PRINTDEBUGMESSAGE(name(), "Total number of payloads exceeded, backpressure!");
|
||||
}
|
||||
|
||||
// (4) Choose one request and send it to DRAM
|
||||
// (4) Start refresh managers to issue requests for the current time
|
||||
for (auto it : refreshManagers)
|
||||
it->start();
|
||||
|
||||
// (5) Choose one request and send it to DRAM
|
||||
std::pair<Command, tlm_generic_payload *> commandPair;
|
||||
std::vector<std::pair<Command, tlm_generic_payload *>> readyCommands;
|
||||
// (4.1) Check for refresh command (PREA/PRE or REFA/REFB)
|
||||
for (auto it : refreshManagers)
|
||||
// (5.1) Check for bank commands (PRE, ACT, RD/RDA or WR/WRA)
|
||||
for (auto it : bankMachines)
|
||||
{
|
||||
commandPair = it->getNextCommand();
|
||||
if (commandPair.second != nullptr)
|
||||
readyCommands.push_back(commandPair);
|
||||
}
|
||||
// (4.2) Check for other commands (PRE, ACT, RD or WR)
|
||||
for (auto it : bankMachines)
|
||||
// (5.2) Check for refresh commands (PREA/PRE or REFA/REFB)
|
||||
for (auto it : refreshManagers)
|
||||
{
|
||||
commandPair = it->getNextCommand();
|
||||
if (commandPair.second != nullptr)
|
||||
@@ -228,16 +231,15 @@ void Controller::controllerMethod()
|
||||
}
|
||||
}
|
||||
|
||||
// (5) Restart bank machines and refresh managers to issue new requests for the future
|
||||
for (auto it : refreshManagers)
|
||||
bankMachineEvent.notify(it->start());
|
||||
// TODO: order, first BM then RM?
|
||||
// (6) Restart bank machines and refresh managers to issue new requests for the future
|
||||
for (auto it : bankMachines)
|
||||
{
|
||||
sc_time delay = it->start();
|
||||
if (delay != SC_ZERO_TIME) // TODO: must be checked to avoid livelock
|
||||
bankMachineEvent.notify(delay);
|
||||
controllerEvent.notify(delay);
|
||||
}
|
||||
for (auto it : refreshManagers)
|
||||
controllerEvent.notify(it->start());
|
||||
}
|
||||
|
||||
tlm_sync_enum Controller::nb_transport_fw(tlm_generic_payload &trans,
|
||||
|
||||
@@ -91,7 +91,7 @@ private:
|
||||
void acquirePayload();
|
||||
|
||||
void controllerMethod();
|
||||
sc_event beginReqEvent, endRespEvent, bankMachineEvent, refreshEvent;
|
||||
sc_event beginReqEvent, endRespEvent, controllerEvent;
|
||||
sc_event_queue dataResponseEventQueue;
|
||||
|
||||
// Bandwidth related
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
CheckerDDR3::CheckerDDR3()
|
||||
{
|
||||
Configuration config = Configuration::getInstance();
|
||||
Configuration &config = Configuration::getInstance();
|
||||
memSpec = dynamic_cast<MemSpecDDR3 *>(config.memSpec);
|
||||
if (memSpec == nullptr)
|
||||
SC_REPORT_FATAL("CheckerDDR3", "Wrong MemSpec chosen");
|
||||
@@ -208,7 +208,7 @@ sc_time CheckerDDR3::delayToSatisfyConstraints(Command command, Rank rank, BankG
|
||||
reportFatal("CheckerDDR3", "Unknown command!");
|
||||
}
|
||||
// Check if command bus is free
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastScheduled + memSpec->clk);
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk);
|
||||
|
||||
return (earliestTimeToStart - sc_time_stamp());
|
||||
}
|
||||
@@ -221,7 +221,7 @@ void CheckerDDR3::insert(Command command, Rank rank, BankGroup, Bank bank)
|
||||
lastScheduledByCommandAndBank[command][bank.ID()] = sc_time_stamp();
|
||||
lastScheduledByCommandAndRank[command][rank.ID()] = sc_time_stamp();
|
||||
lastScheduledByCommand[command] = sc_time_stamp();
|
||||
lastScheduled = sc_time_stamp();
|
||||
lastCommandOnBus = sc_time_stamp();
|
||||
|
||||
if (command == Command::ACT)
|
||||
{
|
||||
|
||||
@@ -54,7 +54,7 @@ private:
|
||||
std::vector<std::vector<sc_time>> lastScheduledByCommandAndBank;
|
||||
std::vector<std::vector<sc_time>> lastScheduledByCommandAndRank;
|
||||
std::vector<sc_time> lastScheduledByCommand;
|
||||
sc_time lastScheduled;
|
||||
sc_time lastCommandOnBus;
|
||||
|
||||
// Four activate window
|
||||
std::vector<std::queue<sc_time>> lastActivates;
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
CheckerDDR4::CheckerDDR4()
|
||||
{
|
||||
Configuration config = Configuration::getInstance();
|
||||
Configuration &config = Configuration::getInstance();
|
||||
memSpec = dynamic_cast<MemSpecDDR4 *>(config.memSpec);
|
||||
if (memSpec == nullptr)
|
||||
SC_REPORT_FATAL("CheckerDDR4", "Wrong MemSpec chosen");
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
CheckerLPDDR4::CheckerLPDDR4()
|
||||
{
|
||||
Configuration config = Configuration::getInstance();
|
||||
Configuration &config = Configuration::getInstance();
|
||||
memSpec = dynamic_cast<MemSpecLPDDR4 *>(config.memSpec);
|
||||
if (memSpec == nullptr)
|
||||
SC_REPORT_FATAL("CheckerLPDDR4", "Wrong MemSpec chosen");
|
||||
@@ -94,8 +94,8 @@ sc_time CheckerLPDDR4::delayToSatisfyConstraints(Command command, Rank rank, Ban
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRD - 2 * memSpec->clk);
|
||||
|
||||
if (lastActivates[rank.ID()].size() >= 4)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastActivates[rank.ID()].front() + memSpec->tFAW);
|
||||
if (lastActivates[rank.ID()].size() == 4)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastActivates[rank.ID()].front() + memSpec->tFAW - 3 * memSpec->clk);
|
||||
}
|
||||
else if (command == Command::RD || command == Command::RDA)
|
||||
{
|
||||
@@ -177,9 +177,9 @@ sc_time CheckerLPDDR4::delayToSatisfyConstraints(Command command, Rank rank, Ban
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + memSpec->tCCD + memSpec->tWR + 3 * memSpec->clk);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCpb);
|
||||
// lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()];
|
||||
// if (lastCommandStart != SC_ZERO_TIME)
|
||||
// earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCpb);
|
||||
}
|
||||
else if (command == Command::REFA)
|
||||
{
|
||||
@@ -208,9 +208,9 @@ sc_time CheckerLPDDR4::delayToSatisfyConstraints(Command command, Rank rank, Ban
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCab);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()]; // remove this if REFA and REFB are not mixed
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCpb);
|
||||
// lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()];
|
||||
// if (lastCommandStart != SC_ZERO_TIME)
|
||||
// earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCpb);
|
||||
}
|
||||
else if (command == Command::REFB)
|
||||
{
|
||||
@@ -235,17 +235,20 @@ sc_time CheckerLPDDR4::delayToSatisfyConstraints(Command command, Rank rank, Ban
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRPpb);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; // remove this
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRPab);
|
||||
// lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()];
|
||||
// if (lastCommandStart != SC_ZERO_TIME)
|
||||
// earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRPab);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; // remove this
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCab);
|
||||
// lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()];
|
||||
// if (lastCommandStart != SC_ZERO_TIME)
|
||||
// earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCab);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCpb);
|
||||
|
||||
if (lastActivates[rank.ID()].size() == 4)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastActivates[rank.ID()].front() + memSpec->tFAW - memSpec->clk);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -267,10 +270,10 @@ void CheckerLPDDR4::insert(Command command, Rank rank, BankGroup, Bank bank)
|
||||
lastScheduledByCommand[command] = sc_time_stamp();
|
||||
lastCommandOnBus = sc_time_stamp() + (memSpec->getCommandLength(command) - 1) * memSpec->clk;
|
||||
|
||||
if (command == Command::ACT) // TODO: FAW for REFB
|
||||
if (command == Command::ACT || command == Command::REFB)
|
||||
{
|
||||
if (lastActivates[rank.ID()].size() == 4)
|
||||
lastActivates[rank.ID()].pop();
|
||||
lastActivates[rank.ID()].push(sc_time_stamp());
|
||||
lastActivates[rank.ID()].push(lastCommandOnBus);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
CheckerWideIO::CheckerWideIO()
|
||||
{
|
||||
Configuration config = Configuration::getInstance();
|
||||
Configuration &config = Configuration::getInstance();
|
||||
memSpec = dynamic_cast<MemSpecWideIO *>(config.memSpec);
|
||||
if (memSpec == nullptr)
|
||||
SC_REPORT_FATAL("CheckerWideIO", "Wrong MemSpec chosen");
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
RefreshManager::RefreshManager(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->getRefreshIntervalAB();
|
||||
setUpDummy(refreshPayload, rank);
|
||||
|
||||
if (config.ControllerCoreRefEnablePostpone)
|
||||
maxPostponed = config.ControllerCoreRefMaxPostponed;
|
||||
if (config.ControllerCoreRefEnablePullIn)
|
||||
maxPulledin = -config.ControllerCoreRefMaxPulledIn;
|
||||
}
|
||||
|
||||
std::pair<Command, tlm_generic_payload *> RefreshManager::getNextCommand()
|
||||
@@ -60,11 +66,30 @@ sc_time RefreshManager::start()
|
||||
sc_time delay;
|
||||
if (state == RmState::IDLE)
|
||||
{
|
||||
if (flexibleCounter != maxPostponed || isPulledinRefresh)
|
||||
{
|
||||
for (auto it : bankMachines)
|
||||
{
|
||||
if (!it->isIdle())
|
||||
{
|
||||
if (!isPulledinRefresh)
|
||||
flexibleCounter++;
|
||||
isPulledinRefresh = false;
|
||||
timeForNextTrigger += memSpec->getRefreshIntervalAB();
|
||||
return timeForNextTrigger - sc_time_stamp();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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)
|
||||
{
|
||||
it->block();
|
||||
if (it->getState() == BmState::Activated)
|
||||
doPrecharge = true;
|
||||
}
|
||||
@@ -78,10 +103,11 @@ sc_time RefreshManager::start()
|
||||
{
|
||||
delay = checker->delayToSatisfyConstraints(Command::REFA, rank, BankGroup(0), Bank(0));
|
||||
nextCommand = Command::REFA;
|
||||
state = RmState::PRECHARGED;
|
||||
if (flexibleCounter == maxPostponed)
|
||||
state = RmState::PRECHARGED;
|
||||
}
|
||||
}
|
||||
else
|
||||
else // if (state == RmState::PRECHARGED)
|
||||
{
|
||||
delay = checker->delayToSatisfyConstraints(Command::REFA, rank, BankGroup(0), Bank(0));
|
||||
nextCommand = Command::REFA;
|
||||
@@ -98,8 +124,22 @@ void RefreshManager::updateState(Command command, tlm_generic_payload *)
|
||||
if (command == Command::REFA)
|
||||
{
|
||||
state = RmState::IDLE;
|
||||
timeForNextTrigger += memSpec->getRefreshIntervalAB();
|
||||
|
||||
if (isPulledinRefresh)
|
||||
flexibleCounter--;
|
||||
else
|
||||
isPulledinRefresh = true;
|
||||
|
||||
if (flexibleCounter == maxPulledin)
|
||||
{
|
||||
isPulledinRefresh = false;
|
||||
timeForNextTrigger += memSpec->getRefreshIntervalAB();
|
||||
}
|
||||
}
|
||||
else if (command == Command::PREA)
|
||||
{
|
||||
for (auto it : bankMachines)
|
||||
it->block();
|
||||
state = RmState::PRECHARGED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +61,11 @@ private:
|
||||
Rank rank;
|
||||
CheckerIF *checker;
|
||||
Command nextCommand;
|
||||
|
||||
int flexibleCounter = 0;
|
||||
int maxPostponed = 0;
|
||||
int maxPulledin = 0;
|
||||
bool isPulledinRefresh = false;
|
||||
};
|
||||
|
||||
#endif // REFRESHMANAGER_H
|
||||
|
||||
Reference in New Issue
Block a user