Implemented first version of flexible refresh (only REFA).

This commit is contained in:
Lukas Steiner
2019-10-04 21:46:29 +02:00
parent b22cfa4a94
commit aa6a205872
9 changed files with 94 additions and 44 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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