From 7868af4b5118af336f349dbec4031d3298dab16f Mon Sep 17 00:00:00 2001 From: Lukas Steiner Date: Tue, 1 Oct 2019 20:53:01 +0200 Subject: [PATCH] Implemented first version of new refresh (no REFB). --- .../src/configuration/ConfigurationLoader.cpp | 28 ++- .../src/configuration/memspec/MemSpec.h | 12 +- .../library/src/controller/BankMachine.cpp | 22 +-- DRAMSys/library/src/controller/BankMachine.h | 3 +- DRAMSys/library/src/controller/Controller.cpp | 123 ++++++++----- DRAMSys/library/src/controller/Controller.h | 4 +- .../src/controller/checker/CheckerDDR3.cpp | 167 +++++++----------- .../src/controller/checker/CheckerDDR3.h | 53 ------ .../src/controller/cmdmux/CmdMuxStrict.cpp | 11 +- .../src/controller/refresh/RefreshManager.cpp | 78 +++++--- .../src/controller/refresh/RefreshManager.h | 14 +- .../refresh/RefreshManagerBankwise.cpp | 13 +- .../refresh/RefreshManagerBankwise.h | 8 +- .../refresh/RefreshManagerDummy.cpp | 2 +- .../controller/refresh/RefreshManagerDummy.h | 3 +- .../src/controller/refresh/RefreshManagerIF.h | 3 +- DRAMSys/traceAnalyzer/scripts/tests.py | 8 +- 17 files changed, 280 insertions(+), 272 deletions(-) diff --git a/DRAMSys/library/src/configuration/ConfigurationLoader.cpp b/DRAMSys/library/src/configuration/ConfigurationLoader.cpp index e21b9552..36f8ee10 100644 --- a/DRAMSys/library/src/configuration/ConfigurationLoader.cpp +++ b/DRAMSys/library/src/configuration/ConfigurationLoader.cpp @@ -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"); diff --git a/DRAMSys/library/src/configuration/memspec/MemSpec.h b/DRAMSys/library/src/configuration/memspec/MemSpec.h index 84ae02ba..d14f6029 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpec.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpec.h @@ -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; diff --git a/DRAMSys/library/src/controller/BankMachine.cpp b/DRAMSys/library/src/controller/BankMachine.cpp index 836edb97..1953dd30 100644 --- a/DRAMSys/library/src/controller/BankMachine.cpp +++ b/DRAMSys/library/src/controller/BankMachine.cpp @@ -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 BankMachine::getNextCommand() { - if (sc_time_stamp() == timeToSchedule) + if (sc_time_stamp() == timeToSchedule && !blocked) return std::pair(nextCommand, currentPayload); else return std::pair(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() diff --git a/DRAMSys/library/src/controller/BankMachine.h b/DRAMSys/library/src/controller/BankMachine.h index af4ac52d..eed17816 100644 --- a/DRAMSys/library/src/controller/BankMachine.h +++ b/DRAMSys/library/src/controller/BankMachine.h @@ -62,7 +62,7 @@ public: virtual sc_time startBankMachine() = 0; std::pair 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 diff --git a/DRAMSys/library/src/controller/Controller.cpp b/DRAMSys/library/src/controller/Controller.cpp index 612acac8..ead8b620 100644 --- a/DRAMSys/library/src/controller/Controller.cpp +++ b/DRAMSys/library/src/controller/Controller.cpp @@ -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(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 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 commandPair; + std::vector> readyCommands; + // (5.1) Check for refresh command (PREA/PRE or REFA/REFB) + for (auto it : refreshManagers) { - std::vector> 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); } } diff --git a/DRAMSys/library/src/controller/Controller.h b/DRAMSys/library/src/controller/Controller.h index 64daab41..1ceca538 100644 --- a/DRAMSys/library/src/controller/Controller.h +++ b/DRAMSys/library/src/controller/Controller.h @@ -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> responseQueue; std::vector bankMachines; + std::vector> bankMachinesOnRank; CmdMuxIF *commandMux; SchedulerIF *scheduler; CheckerIF *checker; - RefreshManagerIF *refreshManager; + std::vector refreshManagers; void releasePayload(); void acquirePayload(); diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR3.cpp b/DRAMSys/library/src/controller/checker/CheckerDDR3.cpp index e1c85404..2cf18177 100644 --- a/DRAMSys/library/src/controller/checker/CheckerDDR3.cpp +++ b/DRAMSys/library/src/controller/checker/CheckerDDR3.cpp @@ -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> (numberOfCommands(), std::vector(memSpec->NumberOfBanks)); lastScheduledByCommandAndRank = std::vector> @@ -57,11 +50,6 @@ CheckerDDR3::CheckerDDR3() lastActivates = std::vector>(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; } diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR3.h b/DRAMSys/library/src/controller/checker/CheckerDDR3.h index 169f5878..b901abf9 100644 --- a/DRAMSys/library/src/controller/checker/CheckerDDR3.h +++ b/DRAMSys/library/src/controller/checker/CheckerDDR3.h @@ -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> 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 timesForNextREFB; - std::vector timesForNextPRE; -}; - #endif // CHECKERDDR3_H diff --git a/DRAMSys/library/src/controller/cmdmux/CmdMuxStrict.cpp b/DRAMSys/library/src/controller/cmdmux/CmdMuxStrict.cpp index c640bd64..ff558678 100644 --- a/DRAMSys/library/src/controller/cmdmux/CmdMuxStrict.cpp +++ b/DRAMSys/library/src/controller/cmdmux/CmdMuxStrict.cpp @@ -39,11 +39,6 @@ std::pair CmdMuxStrict::selectCommand(std::vector> &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(Command::NOP, nullptr); } diff --git a/DRAMSys/library/src/controller/refresh/RefreshManager.cpp b/DRAMSys/library/src/controller/refresh/RefreshManager.cpp index 1dad68de..8f64f59c 100644 --- a/DRAMSys/library/src/controller/refresh/RefreshManager.cpp +++ b/DRAMSys/library/src/controller/refresh/RefreshManager.cpp @@ -37,41 +37,69 @@ #include "../../configuration/Configuration.h" #include "../../common/utils.h" -RefreshManager::RefreshManager(std::vector &bankMachines) : bankMachines(bankMachines) +RefreshManager::RefreshManager(std::vector &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 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::PREA, &refreshPayload); - else - return std::pair(Command::NOP, nullptr); - } - else - { - state = RmState::IDLE; - timeForNextTrigger += (memSpec->getRefreshIntervalAB() - memSpec->getExecutionTime(Command::PREA)); - return std::pair(Command::REFA, &refreshPayload); - } - } + if (sc_time_stamp() == timeToSchedule) + return std::pair(nextCommand, &refreshPayload); else return std::pair(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; } diff --git a/DRAMSys/library/src/controller/refresh/RefreshManager.h b/DRAMSys/library/src/controller/refresh/RefreshManager.h index e18192b4..c3a73988 100644 --- a/DRAMSys/library/src/controller/refresh/RefreshManager.h +++ b/DRAMSys/library/src/controller/refresh/RefreshManager.h @@ -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 &); + RefreshManager(std::vector &, Rank, CheckerIF *); std::pair 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 &bankMachines; + std::vector bankMachines; tlm_generic_payload refreshPayload; sc_time timeForNextTrigger; + sc_time timeToSchedule = SC_ZERO_TIME; + CheckerIF *checker; + Rank rank; + Command nextCommand; }; #endif // REFRESHMANAGER_H diff --git a/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.cpp b/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.cpp index 6ebd7d16..39666a69 100644 --- a/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.cpp +++ b/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.cpp @@ -37,8 +37,8 @@ #include "../../common/utils.h" #include "../../common/dramExtensions.h" -RefreshManagerBankwise::RefreshManagerBankwise(std::vector &bankMachines) - : bankMachines(bankMachines) +RefreshManagerBankwise::RefreshManagerBankwise(std::vector &bankMachines, Rank, CheckerIF *checker) + : bankMachines(bankMachines), checker(checker) { memSpec = Configuration::getInstance().memSpec; // TODO: implement for multiple ranks @@ -70,7 +70,7 @@ std::pair 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::PRE, &refreshPayloads[bank.ID()]); else @@ -86,7 +86,12 @@ std::pair RefreshManagerBankwise::getNextCommand return std::pair(Command::NOP, nullptr); } -sc_time RefreshManagerBankwise::getTriggerDelay() +sc_time RefreshManagerBankwise::startRefreshManager() { return timeForNextTrigger - sc_time_stamp(); } + +void RefreshManagerBankwise::updateState(Command, tlm_generic_payload *) +{ + +} diff --git a/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.h b/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.h index b4a9c6da..4e49dddf 100644 --- a/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.h +++ b/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.h @@ -45,19 +45,21 @@ class RefreshManagerBankwise final : public RefreshManagerIF { public: - RefreshManagerBankwise(std::vector &); + RefreshManagerBankwise(std::vector &, Rank, CheckerIF *); std::pair getNextCommand(); - sc_time getTriggerDelay(); + sc_time startRefreshManager(); + void updateState(Command, tlm_generic_payload *); private: const MemSpec *memSpec; - std::vector &bankMachines; + std::vector bankMachines; std::vector refreshPayloads; std::map triggerTimes; sc_time timeForNextTrigger; enum class RmState {IDLE, REFRESHING}; std::vector states; + CheckerIF *checker; }; #endif // REFRESHMANAGERBANKWISE_H diff --git a/DRAMSys/library/src/controller/refresh/RefreshManagerDummy.cpp b/DRAMSys/library/src/controller/refresh/RefreshManagerDummy.cpp index 5f77a543..c35e77af 100644 --- a/DRAMSys/library/src/controller/refresh/RefreshManagerDummy.cpp +++ b/DRAMSys/library/src/controller/refresh/RefreshManagerDummy.cpp @@ -39,7 +39,7 @@ std::pair RefreshManagerDummy::getNextCommand() return std::pair(Command::NOP, nullptr); } -sc_time RefreshManagerDummy::getTriggerDelay() +sc_time RefreshManagerDummy::startRefreshManager() { return sc_max_time() - sc_time_stamp(); } diff --git a/DRAMSys/library/src/controller/refresh/RefreshManagerDummy.h b/DRAMSys/library/src/controller/refresh/RefreshManagerDummy.h index 76ccb6fe..7dac7a23 100644 --- a/DRAMSys/library/src/controller/refresh/RefreshManagerDummy.h +++ b/DRAMSys/library/src/controller/refresh/RefreshManagerDummy.h @@ -47,7 +47,8 @@ class RefreshManagerDummy final : public RefreshManagerIF { public: std::pair getNextCommand(); - sc_time getTriggerDelay(); + sc_time startRefreshManager(); + void updateState(Command, tlm_generic_payload *) {} }; #endif // REFRESHMANAGERDUMMY_H diff --git a/DRAMSys/library/src/controller/refresh/RefreshManagerIF.h b/DRAMSys/library/src/controller/refresh/RefreshManagerIF.h index 31601f0a..0449e788 100644 --- a/DRAMSys/library/src/controller/refresh/RefreshManagerIF.h +++ b/DRAMSys/library/src/controller/refresh/RefreshManagerIF.h @@ -48,7 +48,8 @@ public: virtual ~RefreshManagerIF() {} virtual std::pair getNextCommand() = 0; - virtual sc_time getTriggerDelay() = 0; + virtual sc_time startRefreshManager() = 0; + virtual void updateState(Command, tlm_generic_payload *) = 0; }; #endif // REFRESHMANAGERIF_H diff --git a/DRAMSys/traceAnalyzer/scripts/tests.py b/DRAMSys/traceAnalyzer/scripts/tests.py index c82dbc81..dd5c022f 100755 --- a/DRAMSys/traceAnalyzer/scripts/tests.py +++ b/DRAMSys/traceAnalyzer/scripts/tests.py @@ -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