Implemented first version of new refresh (no REFB).

This commit is contained in:
Lukas Steiner
2019-10-01 20:53:01 +02:00
parent 04ec683b57
commit 7868af4b51
17 changed files with 280 additions and 272 deletions

View File

@@ -213,8 +213,11 @@ void ConfigurationLoader::loadDDR3(Configuration &config, XMLElement *xmlSpec)
// MemArchitecture
XMLElement *architecture = xmlSpec->FirstChildElement("memarchitecturespec");
memSpec->NumberOfRanks = queryUIntParameter(architecture, "nbrOfRanks");
memSpec->NumberOfBankGroups = memSpec->NumberOfRanks;
memSpec->NumberOfBanks = queryUIntParameter(architecture, "nbrOfBanks") * memSpec->NumberOfRanks;
memSpec->BanksPerRank = queryUIntParameter(architecture, "nbrOfBanks");
memSpec->GroupsPerRank = 1;
memSpec->BanksPerGroup = memSpec->BanksPerRank / memSpec->GroupsPerRank;
memSpec->NumberOfBanks = memSpec->BanksPerRank * memSpec->NumberOfRanks;
memSpec->NumberOfBankGroups = memSpec->GroupsPerRank * memSpec->NumberOfRanks;
// MemTimings specific for DDR3
XMLElement *timings = xmlSpec->FirstChildElement("memtimingspec");
@@ -259,8 +262,11 @@ void ConfigurationLoader::loadDDR4(Configuration &config, XMLElement *xmlSpec)
// MemArchitecture
XMLElement *architecture = xmlSpec->FirstChildElement("memarchitecturespec");
memSpec->NumberOfRanks = queryUIntParameter(architecture, "nbrOfRanks");
memSpec->NumberOfBankGroups = queryUIntParameter(architecture, "nbrOfBankGroups") * memSpec->NumberOfRanks;
memSpec->NumberOfBanks = queryUIntParameter(architecture, "nbrOfBanks") * memSpec->NumberOfRanks;
memSpec->BanksPerRank = queryUIntParameter(architecture, "nbrOfBanks");
memSpec->GroupsPerRank = queryUIntParameter(architecture, "nbrOfBankGroups");
memSpec->BanksPerGroup = memSpec->BanksPerRank / memSpec->GroupsPerRank;
memSpec->NumberOfBanks = memSpec->BanksPerRank * memSpec->NumberOfRanks;
memSpec->NumberOfBankGroups = memSpec->GroupsPerRank * memSpec->NumberOfRanks;
// MemTimings specific for DDR4
XMLElement *timings = xmlSpec->FirstChildElement("memtimingspec");
@@ -328,8 +334,11 @@ void ConfigurationLoader::loadLPDDR4(Configuration &config, XMLElement *xmlSpec)
// MemArchitecture:
XMLElement *architecture = xmlSpec->FirstChildElement("memarchitecturespec");
memSpec->NumberOfRanks = queryUIntParameter(architecture, "nbrOfRanks");
memSpec->NumberOfBankGroups = memSpec->NumberOfRanks;
memSpec->NumberOfBanks = queryUIntParameter(architecture, "nbrOfBanks") * memSpec->NumberOfRanks;
memSpec->BanksPerRank = queryUIntParameter(architecture, "nbrOfBanks");
memSpec->GroupsPerRank = 1;
memSpec->BanksPerGroup = memSpec->BanksPerRank / memSpec->GroupsPerRank;
memSpec->NumberOfBanks = memSpec->BanksPerRank * memSpec->NumberOfRanks;
memSpec->NumberOfBankGroups = memSpec->GroupsPerRank * memSpec->NumberOfRanks;
// MemTimings specific for LPDDR4
XMLElement *timings = xmlSpec->FirstChildElement("memtimingspec");
@@ -383,8 +392,11 @@ void ConfigurationLoader::loadWideIO(Configuration &config, XMLElement *xmlSpec)
// MemArchitecture
XMLElement *architecture = xmlSpec->FirstChildElement("memarchitecturespec");
memSpec->NumberOfRanks = queryUIntParameter(architecture, "nbrOfRanks");
memSpec->NumberOfBankGroups = memSpec->NumberOfRanks;
memSpec->NumberOfBanks = queryUIntParameter(architecture, "nbrOfBanks") * memSpec->NumberOfRanks;
memSpec->BanksPerRank = queryUIntParameter(architecture, "nbrOfBanks");
memSpec->GroupsPerRank = 1;
memSpec->BanksPerGroup = memSpec->BanksPerRank / memSpec->GroupsPerRank;
memSpec->NumberOfBanks = memSpec->BanksPerRank * memSpec->NumberOfRanks;
memSpec->NumberOfBankGroups = memSpec->GroupsPerRank * memSpec->NumberOfRanks;
// MemTimings specific for WideIO
XMLElement *timings = xmlSpec->FirstChildElement("memtimingspec");

View File

@@ -70,14 +70,18 @@ struct MemSpec
std::string MemoryId = "not defined.";
std::string MemoryType = "not defined.";
unsigned int NumberOfBanks;
unsigned int NumberOfRanks;
unsigned int BurstLength;
unsigned int DataRate;
unsigned int NumberOfBankGroups;
unsigned int NumberOfBanks;
unsigned int NumberOfRows;
unsigned int NumberOfColumns;
unsigned int BurstLength;
unsigned int DataRate;
unsigned int bitWidth;
unsigned int NumberOfBankGroups;
unsigned int BanksPerRank;
unsigned int BanksPerGroup;
unsigned int GroupsPerRank;
// Clock
double clkMHz;

View File

@@ -38,15 +38,13 @@ BankMachine::BankMachine(SchedulerIF *scheduler, CheckerIF *checker, Bank bank)
: scheduler(scheduler), checker(checker), bank(bank)
{
MemSpec *memSpec = Configuration::getInstance().memSpec;
unsigned banksPerRank = memSpec->NumberOfBanks / memSpec->NumberOfRanks;
unsigned banksPerGroup = memSpec->NumberOfBanks / memSpec->NumberOfBankGroups;
rank = Rank(bank.ID() / banksPerRank);
bankgroup = BankGroup(bank.ID() / banksPerGroup);
rank = Rank(bank.ID() / memSpec->BanksPerRank);
bankgroup = BankGroup(bank.ID() / memSpec->BanksPerGroup);
}
std::pair<Command, tlm_generic_payload *> BankMachine::getNextCommand()
{
if (sc_time_stamp() == timeToSchedule)
if (sc_time_stamp() == timeToSchedule && !blocked)
return std::pair<Command, tlm_generic_payload *>(nextCommand, currentPayload);
else
return std::pair<Command, tlm_generic_payload *>(Command::NOP, nullptr);
@@ -59,7 +57,7 @@ void BankMachine::updateState(Command command)
currentState = BmState::Activated;
currentRow = nextRow;
}
else if (command == Command::PRE)
else if (command == Command::PRE || command == Command::PREA)
currentState = BmState::Precharged;
else if (command == Command::RD || command == Command::WR)
currentPayload = nullptr;
@@ -68,19 +66,15 @@ void BankMachine::updateState(Command command)
currentState = BmState::Precharged;
currentPayload = nullptr;
}
else if (command == Command::REFA || command == Command::REFB)
blocked = false;
else
SC_REPORT_FATAL("BankMachine", "Unknown phase");
}
bool BankMachine::forcePrecharge()
void BankMachine::block()
{
if (currentState != BmState::Precharged)
{
currentState = BmState::Precharged;
return true;
}
else
return false;
blocked = true;
}
Rank BankMachine::getRank()

View File

@@ -62,7 +62,7 @@ public:
virtual sc_time startBankMachine() = 0;
std::pair<Command, tlm_generic_payload *> getNextCommand();
void updateState(Command);
bool forcePrecharge();
void block();
Rank getRank();
Bank getBank();
@@ -82,6 +82,7 @@ protected:
Rank rank = Rank(0);
BankGroup bankgroup = BankGroup(0);
Bank bank;
bool blocked = false;
};
class BankMachineOpen final : public BankMachine

View File

@@ -58,31 +58,20 @@ Controller::Controller(sc_module_name name) :
dont_initialize();
Configuration config = Configuration::getInstance();
MemSpec *memSpec = config.memSpec;
maxNumberOfPayloads = config.MaxNrOfTransactions;
if (config.memSpec->MemoryType == "DDR3")
if (memSpec->MemoryType == "DDR3")
checker = new CheckerDDR3();
else if (config.memSpec->MemoryType == "DDR4")
else if (memSpec->MemoryType == "DDR4")
checker = new CheckerDDR4();
else if (config.memSpec->MemoryType == "WIDEIO_SDR")
else if (memSpec->MemoryType == "WIDEIO_SDR")
checker = new CheckerWideIO();
else if (config.memSpec->MemoryType == "LPDDR4")
else if (memSpec->MemoryType == "LPDDR4")
checker = new CheckerLPDDR4();
else
SC_REPORT_FATAL("Controller", "Unsupported DRAM type");
if (config.ControllerCoreRefDisable)
refreshManager = new RefreshManagerDummy();
else if (config.BankwiseLogic)
{
refreshManager = new RefreshManagerBankwise(bankMachines);
refreshEvent.notify(refreshManager->getTriggerDelay());
}
else
{
refreshManager = new RefreshManager(bankMachines);
refreshEvent.notify(refreshManager->getTriggerDelay());
}
if (config.Scheduler == "FifoStrict")
{
scheduler = new SchedulerFifo();
@@ -100,12 +89,12 @@ Controller::Controller(sc_module_name name) :
{
if (config.AdaptivePagePolicy)
{
for (unsigned bankID = 0; bankID < config.memSpec->NumberOfBanks; bankID++)
for (unsigned bankID = 0; bankID < memSpec->NumberOfBanks; bankID++)
bankMachines.push_back(new BankMachineOpenAdaptive(scheduler, checker, Bank(bankID)));
}
else
{
for (unsigned bankID = 0; bankID < config.memSpec->NumberOfBanks; bankID++)
for (unsigned bankID = 0; bankID < memSpec->NumberOfBanks; bankID++)
bankMachines.push_back(new BankMachineOpen(scheduler, checker, Bank(bankID)));
}
}
@@ -113,16 +102,45 @@ Controller::Controller(sc_module_name name) :
{
if (config.AdaptivePagePolicy)
{
for (unsigned bankID = 0; bankID < config.memSpec->NumberOfBanks; bankID++)
for (unsigned bankID = 0; bankID < memSpec->NumberOfBanks; bankID++)
bankMachines.push_back(new BankMachineClosedAdaptive(scheduler, checker, Bank(bankID)));
}
else
{
for (unsigned bankID = 0; bankID < config.memSpec->NumberOfBanks; bankID++)
for (unsigned bankID = 0; bankID < memSpec->NumberOfBanks; bankID++)
bankMachines.push_back(new BankMachineClosed(scheduler, checker, Bank(bankID)));
}
}
for (unsigned rankID = 0; rankID < memSpec->NumberOfRanks; rankID++)
{
bankMachinesOnRank.push_back(std::vector<BankMachine *>(bankMachines.begin() + rankID * memSpec->BanksPerRank,
bankMachines.begin() + (rankID + 1) * memSpec->BanksPerRank));
}
if (config.ControllerCoreRefDisable)
refreshManagers.push_back(new RefreshManagerDummy());
else if (config.BankwiseLogic)
{
for (unsigned rankID = 0; rankID < memSpec->NumberOfRanks; rankID++)
{
RefreshManagerIF *manager = new RefreshManagerBankwise
(bankMachinesOnRank[rankID], Rank(rankID), checker);
refreshManagers.push_back(manager);
refreshEvent.notify(manager->startRefreshManager());
}
}
else
{
for (unsigned rankID = 0; rankID < memSpec->NumberOfRanks; rankID++)
{
RefreshManagerIF *manager = new RefreshManager
(bankMachinesOnRank[rankID], Rank(rankID), checker);
refreshManagers.push_back(manager);
refreshEvent.notify(manager->startRefreshManager());
}
}
startBandwidthIdleCollector();
}
@@ -130,18 +148,19 @@ Controller::~Controller()
{
endBandwithIdleCollector();
for (auto it : refreshManagers)
delete it;
for (auto it : bankMachines)
delete it;
delete commandMux;
delete scheduler;
delete refreshManager;
delete checker;
}
void Controller::controllerMethod()
{
// (1) Release payload if arbiter has accepted the result
if (sc_time_stamp() == timeToRelease /*&& payloadToRelease != nullptr*/)
if (sc_time_stamp() == timeToRelease && payloadToRelease != nullptr)
releasePayload();
// (2) Accept new request from arbiter
@@ -170,39 +189,51 @@ void Controller::controllerMethod()
it->startBankMachine();
// (5) Choose one request and send it to DRAM
std::pair<Command, tlm_generic_payload *> result;
// (5.1) Check for refresh command (PREA or REFA)
result = refreshManager->getNextCommand();
refreshEvent.notify(refreshManager->getTriggerDelay());
if (result.second != nullptr)
sendToDram(result.first, result.second);
// (5.2) Check for other commands (PRE, ACT, RD or WR)
else
std::pair<Command, tlm_generic_payload *> commandPair;
std::vector<std::pair<Command, tlm_generic_payload *>> readyCommands;
// (5.1) Check for refresh command (PREA/PRE or REFA/REFB)
for (auto it : refreshManagers)
{
std::vector<std::pair<Command, tlm_generic_payload *>> readyCommands;
for (auto it : bankMachines)
commandPair = it->getNextCommand();
if (commandPair.second != nullptr)
readyCommands.push_back(commandPair);
}
// (5.2) Check for other commands (PRE, ACT, RD or WR)
for (auto it : bankMachines)
{
commandPair = it->getNextCommand();
if (commandPair.second != nullptr)
readyCommands.push_back(commandPair);
}
if (!readyCommands.empty())
{
commandPair = commandMux->selectCommand(readyCommands);
if (commandPair.second != nullptr) // TODO: can happen with FIFO strict
{
result = it->getNextCommand();
if (result.second != nullptr)
readyCommands.push_back(result);
}
if (!readyCommands.empty())
{
result = commandMux->selectCommand(readyCommands);
if (result.second != nullptr)
Rank rank = DramExtension::getRank(commandPair.second);
if (commandPair.first == Command::PREA || commandPair.first == Command::REFA)
{
unsigned bankID = DramExtension::getBank(result.second).ID();
bankMachines[bankID]->updateState(result.first);
sendToDram(result.first, result.second);
for (auto it : bankMachinesOnRank[rank.ID()])
it->updateState(commandPair.first);
}
else
{
Bank bank = DramExtension::getBank(commandPair.second);
bankMachines[bank.ID()]->updateState(commandPair.first);
}
refreshManagers[rank.ID()]->updateState(commandPair.first, commandPair.second);
sendToDram(commandPair.first, commandPair.second);
}
}
// (6) Restart bank machines to issue new requests for the future
// (6) Restart bank machines and refresh managers to issue new requests for the future
for (auto it : refreshManagers)
bankMachineEvent.notify(it->startRefreshManager());
for (auto it : bankMachines)
{
sc_time delay = it->startBankMachine();
if (delay != SC_ZERO_TIME) // must be checked to avoid livelock
if (delay != SC_ZERO_TIME) // TODO: must be checked to avoid livelock
bankMachineEvent.notify(delay);
}
}

View File

@@ -73,6 +73,7 @@ protected:
private:
unsigned numberOfPayloads = 0;
unsigned maxNumberOfPayloads;
tlm_generic_payload *payloadToAcquire = nullptr;
sc_time timeToAcquire = SC_ZERO_TIME;
tlm_generic_payload *payloadToRelease = nullptr;
@@ -80,10 +81,11 @@ private:
std::queue<std::pair<sc_time, tlm_generic_payload *>> responseQueue;
std::vector<BankMachine *> bankMachines;
std::vector<std::vector<BankMachine *>> bankMachinesOnRank;
CmdMuxIF *commandMux;
SchedulerIF *scheduler;
CheckerIF *checker;
RefreshManagerIF *refreshManager;
std::vector<RefreshManagerIF *> refreshManagers;
void releasePayload();
void acquirePayload();

View File

@@ -41,13 +41,6 @@ CheckerDDR3::CheckerDDR3()
if (memSpec == nullptr)
SC_REPORT_FATAL("CheckerDDR3", "Wrong MemSpec chosen");
if (config.ControllerCoreRefDisable)
refreshChecker = new RefreshCheckerDDR3Dummy(memSpec);
else if (config.BankwiseLogic)
refreshChecker = new RefreshCheckerDDR3Bankwise(memSpec);
else
refreshChecker = new RefreshCheckerDDR3(memSpec);
lastScheduledByCommandAndBank = std::vector<std::vector<sc_time>>
(numberOfCommands(), std::vector<sc_time>(memSpec->NumberOfBanks));
lastScheduledByCommandAndRank = std::vector<std::vector<sc_time>>
@@ -57,11 +50,6 @@ CheckerDDR3::CheckerDDR3()
lastActivates = std::vector<std::queue<sc_time>>(memSpec->NumberOfRanks);
}
CheckerDDR3::~CheckerDDR3()
{
delete refreshChecker;
}
sc_time CheckerDDR3::delayToSatisfyConstraints(Command command, Rank rank, BankGroup, Bank bank) const
{
sc_time lastCommandStart;
@@ -75,12 +63,17 @@ sc_time CheckerDDR3::delayToSatisfyConstraints(Command command, Rank rank, BankG
lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + memSpec->tCCD + memSpec->tWR + memSpec->tRP);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + memSpec->BurstLength / 2 * memSpec->clk + memSpec->tWR + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC);
@@ -93,14 +86,12 @@ sc_time CheckerDDR3::delayToSatisfyConstraints(Command command, Rank rank, BankG
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC);
lastCommandStart = lastScheduledByCommandAndBank[Command::REFB][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC);
// lastCommandStart = lastScheduledByCommandAndBank[Command::REFB][bank.ID()];
// if (lastCommandStart != SC_ZERO_TIME)
// earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC);
if (lastActivates[rank.ID()].size() >= 4)
earliestTimeToStart = std::max(earliestTimeToStart, lastActivates[rank.ID()].front() + memSpec->tFAW);
refreshChecker->delayToSatisfyACT(bank, earliestTimeToStart);
}
else if (command == Command::RD || command == Command::RDA)
{
@@ -117,13 +108,13 @@ sc_time CheckerDDR3::delayToSatisfyConstraints(Command command, Rank rank, BankG
lastCommandStart = lastScheduledByCommand[Command::WR];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + memSpec->tCCD + memSpec->tWTR);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + memSpec->BurstLength / 2 * memSpec->clk + memSpec->tWTR);
lastCommandStart = lastScheduledByCommand[Command::WRA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + memSpec->tCCD + memSpec->tWTR);
refreshChecker->delayToSatisfyRD(bank, earliestTimeToStart);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + memSpec->BurstLength / 2 * memSpec->clk + memSpec->tWTR);
}
else if (command == Command::WR || command == Command::WRA)
{
@@ -132,11 +123,13 @@ sc_time CheckerDDR3::delayToSatisfyConstraints(Command command, Rank rank, BankG
lastCommandStart = lastScheduledByCommand[Command::RD];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRL + memSpec->tCCD + 2 * memSpec->clk - memSpec->tWL);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tRL + memSpec->BurstLength / 2 * memSpec->clk + 2 * memSpec->clk - memSpec->tWL);
lastCommandStart = lastScheduledByCommand[Command::RDA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRL + memSpec->tCCD + 2 * memSpec->clk - memSpec->tWL);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tRL + memSpec->BurstLength / 2 * memSpec->clk + 2 * memSpec->clk - memSpec->tWL);
lastCommandStart = lastScheduledByCommand[Command::WR];
if (lastCommandStart != SC_ZERO_TIME)
@@ -145,8 +138,6 @@ sc_time CheckerDDR3::delayToSatisfyConstraints(Command command, Rank rank, BankG
lastCommandStart = lastScheduledByCommand[Command::WRA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD);
refreshChecker->delayToSatisfyWR(bank, earliestTimeToStart);
}
else if (command == Command::PRE)
{
@@ -159,9 +150,58 @@ sc_time CheckerDDR3::delayToSatisfyConstraints(Command command, Rank rank, BankG
lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + memSpec->tCCD + memSpec->tWR);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + memSpec->BurstLength / 2 * memSpec->clk + memSpec->tWR);
}
else if (command == Command::PREA)
{
lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()];
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS);
refreshChecker->delayToSatisfyPRE(bank, earliestTimeToStart);
lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP);
lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP);
lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + memSpec->BurstLength / 2 * memSpec->clk + memSpec->tWR);
lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + memSpec->BurstLength / 2 * memSpec->clk + memSpec->tWR);
}
else if (command == Command::REFA)
{
lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC);
lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + memSpec->BurstLength / 2 * memSpec->clk + memSpec->tWR + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC);
}
else
{
@@ -189,75 +229,4 @@ void CheckerDDR3::insert(Command command, Rank rank, BankGroup, Bank bank)
lastActivates[rank.ID()].pop();
lastActivates[rank.ID()].push(sc_time_stamp());
}
else if (command == Command::REFA || command == Command::REFB)
refreshChecker->insert(bank);
}
// TODO: max(earliestTimeToStart, ...) needed?
void RefreshCheckerDDR3::delayToSatisfyACT(Bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timeForNextPREA - memSpec->tRAS))
earliestTimeToStart = timeForNextREFA + memSpec->tRFC;
}
void RefreshCheckerDDR3::delayToSatisfyRD(Bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timeForNextPREA - memSpec->tRTP))
earliestTimeToStart = timeForNextREFA + memSpec->tRFC;
}
void RefreshCheckerDDR3::delayToSatisfyWR(Bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timeForNextPREA - memSpec->tWL - memSpec->tCCD - memSpec->tWR))
earliestTimeToStart = timeForNextREFA + memSpec->tRFC;
}
void RefreshCheckerDDR3::delayToSatisfyPRE(Bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= timeForNextPREA)
earliestTimeToStart = timeForNextREFA + memSpec->tRFC;
}
void RefreshCheckerDDR3::insert(Bank)
{
timeForNextREFA += memSpec->tREFI;
timeForNextPREA += memSpec->tREFI;
}
RefreshCheckerDDR3Bankwise::RefreshCheckerDDR3Bankwise(const MemSpecDDR3 *memSpec)
: RefreshCheckerDDR3Dummy(memSpec)
{
sc_time currentREFB = memSpec->tREFI - memSpec->clk * (memSpec->NumberOfBanks - 1);
sc_time currentPRE = currentREFB - std::max(memSpec->clk * memSpec->NumberOfBanks, memSpec->tRP);
for (unsigned bankID = 0; bankID < memSpec->NumberOfBanks; bankID++)
{
timesForNextREFB.push_back(currentREFB);
timesForNextPRE.push_back(currentPRE);
currentREFB += memSpec->clk;
currentPRE += memSpec->clk;
}
}
void RefreshCheckerDDR3Bankwise::delayToSatisfyACT(Bank bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timesForNextPRE[bank.ID()] - memSpec->tRAS))
earliestTimeToStart = timesForNextREFB[bank.ID()] + memSpec->tRFC;
}
void RefreshCheckerDDR3Bankwise::delayToSatisfyRD(Bank bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timesForNextPRE[bank.ID()] - memSpec->tRTP))
earliestTimeToStart = timesForNextREFB[bank.ID()] + memSpec->tRFC;
}
void RefreshCheckerDDR3Bankwise::delayToSatisfyWR(Bank bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timesForNextPRE[bank.ID()] - memSpec->tWL - memSpec->tCCD - memSpec->tWR))
earliestTimeToStart = timesForNextREFB[bank.ID()] + memSpec->tRFC;
}
void RefreshCheckerDDR3Bankwise::insert(Bank bank)
{
timesForNextREFB[bank.ID()] += memSpec->tREFI;
timesForNextPRE[bank.ID()] += memSpec->tREFI;
}

View File

@@ -41,13 +41,10 @@
#include "../../configuration/memspec/MemSpecDDR3.h"
#include "../../configuration/Configuration.h"
class RefreshCheckerDDR3Dummy;
class CheckerDDR3 final : public CheckerIF
{
public:
CheckerDDR3();
~CheckerDDR3();
sc_time delayToSatisfyConstraints(Command, Rank, BankGroup, Bank) const;
void insert(Command, Rank, BankGroup, Bank);
@@ -62,58 +59,8 @@ private:
// Four activate window
std::vector<std::queue<sc_time>> lastActivates;
RefreshCheckerDDR3Dummy *refreshChecker;
// PowerDown TODO: Implement this method?
//sc_time getTimeConstraintToEnterPowerDown(Command lastCmd, Command pdnCmd) const;
};
class RefreshCheckerDDR3Dummy
{
protected:
friend class CheckerDDR3;
RefreshCheckerDDR3Dummy(const MemSpecDDR3 *memSpec) : memSpec(memSpec) {}
virtual ~RefreshCheckerDDR3Dummy() {}
virtual void delayToSatisfyACT(Bank, sc_time &) {}
virtual void delayToSatisfyRD(Bank, sc_time &) {}
virtual void delayToSatisfyWR(Bank, sc_time &) {}
virtual void delayToSatisfyPRE(Bank, sc_time &) {}
virtual void insert(Bank) {}
const MemSpecDDR3 *memSpec;
};
class RefreshCheckerDDR3 final : public RefreshCheckerDDR3Dummy
{
private:
friend class CheckerDDR3;
RefreshCheckerDDR3(const MemSpecDDR3 *memSpec)
: RefreshCheckerDDR3Dummy(memSpec) {}
void delayToSatisfyACT(Bank, sc_time &);
void delayToSatisfyRD(Bank, sc_time &);
void delayToSatisfyWR(Bank, sc_time &);
void delayToSatisfyPRE(Bank, sc_time &);
void insert(Bank);
sc_time timeForNextREFA = memSpec->tREFI;
sc_time timeForNextPREA = timeForNextREFA - memSpec->tRP;
};
class RefreshCheckerDDR3Bankwise final : public RefreshCheckerDDR3Dummy
{
private:
friend class CheckerDDR3;
RefreshCheckerDDR3Bankwise(const MemSpecDDR3 *);
void delayToSatisfyACT(Bank, sc_time &);
void delayToSatisfyRD(Bank, sc_time &);
void delayToSatisfyWR(Bank, sc_time &);
void insert(Bank);
std::vector<sc_time> timesForNextREFB;
std::vector<sc_time> timesForNextPRE;
};
#endif // CHECKERDDR3_H

View File

@@ -39,11 +39,6 @@
std::pair<Command, tlm_generic_payload *>
CmdMuxStrict::selectCommand(std::vector<std::pair<Command, tlm_generic_payload *>> &readyCommands)
{
for (auto it : readyCommands)
{
if (it.first == Command::ACT || it.first == Command::PRE)
return it;
}
for (auto it : readyCommands)
{
if (commandIsIn(it.first, {Command::RD, Command::RDA, Command::WR, Command::WRA}))
@@ -55,5 +50,11 @@ CmdMuxStrict::selectCommand(std::vector<std::pair<Command, tlm_generic_payload *
}
}
}
for (auto it : readyCommands)
{
if (commandIsIn(it.first, {Command::ACT, Command::PRE,
Command::PREA, Command::REFA, Command::REFB}))
return it;
}
return std::pair<Command, tlm_generic_payload *>(Command::NOP, nullptr);
}

View File

@@ -37,41 +37,69 @@
#include "../../configuration/Configuration.h"
#include "../../common/utils.h"
RefreshManager::RefreshManager(std::vector<BankMachine *> &bankMachines) : bankMachines(bankMachines)
RefreshManager::RefreshManager(std::vector<BankMachine *> &bankMachines, Rank rank, CheckerIF *checker)
: bankMachines(bankMachines), rank(rank), checker(checker)
{
memSpec = Configuration::getInstance().memSpec;
setUpDummy(refreshPayload);
setUpDummy(refreshPayload, rank);
timeForNextTrigger = memSpec->getRefreshIntervalAB() - memSpec->getExecutionTime(Command::PREA);
}
std::pair<Command, tlm_generic_payload *> RefreshManager::getNextCommand()
{
if (sc_time_stamp() == timeForNextTrigger)
{
if (state == RmState::IDLE)
{
state = RmState::REFRESHING;
timeForNextTrigger += memSpec->getExecutionTime(Command::PREA);
bool forcedPrecharges = false;
for (auto it : bankMachines)
forcedPrecharges |= it->forcePrecharge();
if (forcedPrecharges)
return std::pair<Command, tlm_generic_payload *>(Command::PREA, &refreshPayload);
else
return std::pair<Command, tlm_generic_payload *>(Command::NOP, nullptr);
}
else
{
state = RmState::IDLE;
timeForNextTrigger += (memSpec->getRefreshIntervalAB() - memSpec->getExecutionTime(Command::PREA));
return std::pair<Command, tlm_generic_payload *>(Command::REFA, &refreshPayload);
}
}
if (sc_time_stamp() == timeToSchedule)
return std::pair<Command, tlm_generic_payload *>(nextCommand, &refreshPayload);
else
return std::pair<Command, tlm_generic_payload *>(Command::NOP, nullptr);
}
sc_time RefreshManager::getTriggerDelay()
sc_time RefreshManager::startRefreshManager()
{
return timeForNextTrigger - sc_time_stamp();
if (sc_time_stamp() >= timeForNextTrigger)
{
sc_time delay;
if (state == RmState::IDLE)
{
// 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;
}
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;
state = RmState::PRECHARGED;
}
}
else
{
delay = checker->delayToSatisfyConstraints(Command::REFA, rank, BankGroup(0), Bank(0));
nextCommand = Command::REFA;
}
timeToSchedule = sc_time_stamp() + delay;
return delay;
}
else
return timeForNextTrigger - sc_time_stamp();
}
void RefreshManager::updateState(Command command, tlm_generic_payload *)
{
if (command == Command::REFA)
{
state = RmState::IDLE;
timeForNextTrigger += memSpec->getRefreshIntervalAB();
}
else if (command == Command::PREA)
state = RmState::PRECHARGED;
}

View File

@@ -38,23 +38,29 @@
#include "RefreshManagerIF.h"
#include "../../configuration/memspec/MemSpec.h"
#include "../BankMachine.h"
#include "../checker/CheckerIF.h"
using namespace tlm;
class RefreshManager final : public RefreshManagerIF
{
public:
RefreshManager(std::vector<BankMachine *> &);
RefreshManager(std::vector<BankMachine *> &, Rank, CheckerIF *);
std::pair<Command, tlm_generic_payload *> getNextCommand();
sc_time getTriggerDelay();
sc_time startRefreshManager();
void updateState(Command, tlm_generic_payload *);
private:
enum class RmState {IDLE, REFRESHING} state = RmState::IDLE;
enum class RmState {IDLE, PRECHARGED} state = RmState::IDLE;
const MemSpec *memSpec;
std::vector<BankMachine *> &bankMachines;
std::vector<BankMachine *> bankMachines;
tlm_generic_payload refreshPayload;
sc_time timeForNextTrigger;
sc_time timeToSchedule = SC_ZERO_TIME;
CheckerIF *checker;
Rank rank;
Command nextCommand;
};
#endif // REFRESHMANAGER_H

View File

@@ -37,8 +37,8 @@
#include "../../common/utils.h"
#include "../../common/dramExtensions.h"
RefreshManagerBankwise::RefreshManagerBankwise(std::vector<BankMachine *> &bankMachines)
: bankMachines(bankMachines)
RefreshManagerBankwise::RefreshManagerBankwise(std::vector<BankMachine *> &bankMachines, Rank, CheckerIF *checker)
: bankMachines(bankMachines), checker(checker)
{
memSpec = Configuration::getInstance().memSpec;
// TODO: implement for multiple ranks
@@ -70,7 +70,7 @@ std::pair<Command, tlm_generic_payload *> RefreshManagerBankwise::getNextCommand
if (states[bank.ID()] == RmState::IDLE)
{
states[bank.ID()] = RmState::REFRESHING;
bool forcedPrecharge = bankMachines[bank.ID()]->forcePrecharge();
bool forcedPrecharge = true;/*= bankMachines[bank.ID()]->forcePrecharge();*/
if (forcedPrecharge)
return std::pair<Command, tlm_generic_payload *>(Command::PRE, &refreshPayloads[bank.ID()]);
else
@@ -86,7 +86,12 @@ std::pair<Command, tlm_generic_payload *> RefreshManagerBankwise::getNextCommand
return std::pair<Command, tlm_generic_payload *>(Command::NOP, nullptr);
}
sc_time RefreshManagerBankwise::getTriggerDelay()
sc_time RefreshManagerBankwise::startRefreshManager()
{
return timeForNextTrigger - sc_time_stamp();
}
void RefreshManagerBankwise::updateState(Command, tlm_generic_payload *)
{
}

View File

@@ -45,19 +45,21 @@
class RefreshManagerBankwise final : public RefreshManagerIF
{
public:
RefreshManagerBankwise(std::vector<BankMachine *> &);
RefreshManagerBankwise(std::vector<BankMachine *> &, Rank, CheckerIF *);
std::pair<Command, tlm_generic_payload *> getNextCommand();
sc_time getTriggerDelay();
sc_time startRefreshManager();
void updateState(Command, tlm_generic_payload *);
private:
const MemSpec *memSpec;
std::vector<BankMachine *> &bankMachines;
std::vector<BankMachine *> bankMachines;
std::vector<tlm_generic_payload> refreshPayloads;
std::map<sc_time, Bank> triggerTimes;
sc_time timeForNextTrigger;
enum class RmState {IDLE, REFRESHING};
std::vector<RmState> states;
CheckerIF *checker;
};
#endif // REFRESHMANAGERBANKWISE_H

View File

@@ -39,7 +39,7 @@ std::pair<Command, tlm_generic_payload *> RefreshManagerDummy::getNextCommand()
return std::pair<Command, tlm_generic_payload *>(Command::NOP, nullptr);
}
sc_time RefreshManagerDummy::getTriggerDelay()
sc_time RefreshManagerDummy::startRefreshManager()
{
return sc_max_time() - sc_time_stamp();
}

View File

@@ -47,7 +47,8 @@ class RefreshManagerDummy final : public RefreshManagerIF
{
public:
std::pair<Command, tlm_generic_payload *> getNextCommand();
sc_time getTriggerDelay();
sc_time startRefreshManager();
void updateState(Command, tlm_generic_payload *) {}
};
#endif // REFRESHMANAGERDUMMY_H

View File

@@ -48,7 +48,8 @@ public:
virtual ~RefreshManagerIF() {}
virtual std::pair<Command, tlm_generic_payload *> getNextCommand() = 0;
virtual sc_time getTriggerDelay() = 0;
virtual sc_time startRefreshManager() = 0;
virtual void updateState(Command, tlm_generic_payload *) = 0;
};
#endif // REFRESHMANAGERIF_H

View File

@@ -349,14 +349,18 @@ def timing_constraint(FirstPhase, SecondPhase):
return max(dramconfig.tCCD_L, burstlength/dramconfig.dataRate)
elif (FirstPhaseName == "RDA"):
if (SecondPhaseName in ["ACT", "PREA", "REFA"]):
if (SecondPhaseName in ["ACT", "REFA"]):
return dramconfig.tRTP + dramconfig.tRP
elif (SecondPhaseName == "PREA"):
return dramconfig.tRTP
elif (SecondPhaseName in ["PDNA", "PDNP"]):
return dramconfig.tRL + dramconfig.getReadAccessTime() + dramconfig.clk
elif (FirstPhaseName == "WRA"):
if (SecondPhaseName in ["ACT", "PREA", "REFA"]):
if (SecondPhaseName in ["ACT", "REFA"]):
return dramconfig.tWL + dramconfig.getWriteAccessTime() + dramconfig.tWR + dramconfig.tRP
elif (SecondPhaseName == "PREA"):
return dramconfig.tWL + dramconfig.getWriteAccessTime() + dramconfig.tWR
elif (SecondPhaseName in ["PDNA", "PDNP"]):
return dramconfig.tWL + dramconfig.getWriteAccessTime() + dramconfig.tWR + dramconfig.clk