diff --git a/DRAMSys/library/library.pro b/DRAMSys/library/library.pro index 6ab96b7c..02051018 100644 --- a/DRAMSys/library/library.pro +++ b/DRAMSys/library/library.pro @@ -90,17 +90,12 @@ SOURCES += \ src/common/TlmRecorder.cpp \ src/common/DebugManager.cpp \ src/configuration/Configuration.cpp \ - src/controller/core/powerdown/PowerDownManagerTimeout.cpp \ - src/controller/core/powerdown/PowerDownManagerBankwise.cpp \ - src/controller/core/powerdown/PowerDownManager.cpp \ src/simulation/MemoryManager.cpp \ src/simulation/TemperatureController.cpp \ src/configuration/ConfigurationLoader.cpp \ - src/controller/core/powerdown/NoPowerDown.cpp \ src/controller/Command.cpp \ src/error/errormodel.cpp \ src/simulation/TracePlayer.cpp \ - src/controller/core/powerdown/PowerDownManagerTimeoutBankwise.cpp \ src/simulation/TraceSetup.cpp \ src/simulation/DRAMSys.cpp \ src/simulation/Setup.cpp \ @@ -155,7 +150,8 @@ SOURCES += \ src/controller/checker/CheckerGDDR6.cpp \ src/simulation/dram/DramGDDR5.cpp \ src/simulation/dram/DramGDDR5X.cpp \ - src/simulation/dram/DramGDDR6.cpp + src/simulation/dram/DramGDDR6.cpp \ + src/controller/powerdown/PowerDownManager.cpp HEADERS += \ src/common/third_party/tinyxml2/tinyxml2.h \ @@ -164,9 +160,6 @@ HEADERS += \ src/common/protocol.h \ src/common/DebugManager.h \ src/configuration/Configuration.h \ - src/controller/core/powerdown/PowerDownManagerTimeout.h \ - src/controller/core/powerdown/PowerDownManagerBankwise.h \ - src/controller/core/powerdown/PowerDownManager.h \ src/simulation/TracePlayer.h \ src/simulation/MemoryManager.h \ src/simulation/dram/Dram.h \ @@ -178,13 +171,10 @@ HEADERS += \ src/simulation/TracePlayerListener.h \ src/simulation/TraceGenerator.h \ src/simulation/TemperatureController.h \ - src/controller/core/powerdown/NoPowerDown.h \ src/controller/Command.h \ - src/controller/core/powerdown/IPowerDownManager.h \ src/configuration/ConfigurationLoader.h \ src/error/errormodel.h \ src/simulation/ExampleInitiator.h \ - src/controller/core/powerdown/PowerDownManagerTimeoutBankwise.h \ src/simulation/TraceSetup.h \ src/simulation/DRAMSys.h \ src/simulation/Setup.h \ @@ -244,7 +234,8 @@ HEADERS += \ src/controller/checker/CheckerGDDR6.h \ src/simulation/dram/DramGDDR5.h \ src/simulation/dram/DramGDDR5X.h \ - src/simulation/dram/DramGDDR6.h + src/simulation/dram/DramGDDR6.h \ + src/controller/powerdown/PowerDownManager.h #src/common/third_party/json/include/nlohmann/json.hpp \ thermalsim = $$(THERMALSIM) diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.cpp index 02f83638..51b21916 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.cpp @@ -61,6 +61,8 @@ sc_time MemSpecDDR3::getExecutionTime(Command command, const tlm_generic_payload return tRFC; else if (command == Command::REFB) return tRFC; + else if (command == Command::PDXA || command == Command::PDXP || command == Command::SREFEX) + return clk; else { SC_REPORT_FATAL("getExecutionTime", diff --git a/DRAMSys/library/src/controller/BankMachine.cpp b/DRAMSys/library/src/controller/BankMachine.cpp index 7240f0f5..57ac74f1 100644 --- a/DRAMSys/library/src/controller/BankMachine.cpp +++ b/DRAMSys/library/src/controller/BankMachine.cpp @@ -66,6 +66,8 @@ void BankMachine::updateState(Command command) currentState = BmState::Precharged; currentPayload = nullptr; } + else if (command == Command::PDEA || command == Command::PDEP) + blocked = true; else if (command == Command::REFA || command == Command::REFB || command == Command::PDXA || command == Command::PDXP) blocked = false; diff --git a/DRAMSys/library/src/controller/Command.cpp b/DRAMSys/library/src/controller/Command.cpp index c9f98bf4..290f7c44 100644 --- a/DRAMSys/library/src/controller/Command.cpp +++ b/DRAMSys/library/src/controller/Command.cpp @@ -103,15 +103,15 @@ std::string commandToString(Command command) const std::vector &getAllCommands() { static std::vector allCommands( { Command::NOP, - Command::PRE, - Command::PREA, - Command::ACT, Command::RD, Command::WR, Command::RDA, Command::WRA, - Command::REFA, + Command::PRE, + Command::ACT, Command::REFB, + Command::PREA, + Command::REFA, Command::PDEA, Command::PDXA, Command::PDEP, @@ -137,18 +137,38 @@ bool commandIsIn(Command command, std::vector commands) } std::array phaseOfCommand = {UNINITIALIZED_PHASE, - BEGIN_PRE, - BEGIN_PREA, - BEGIN_ACT, BEGIN_RD, BEGIN_WR, BEGIN_RDA, BEGIN_WRA, - BEGIN_REFA, + BEGIN_PRE, + BEGIN_ACT, BEGIN_REFB, + BEGIN_PREA, + BEGIN_REFA, BEGIN_PDNA, END_PDNA, BEGIN_PDNP, END_PDNP, BEGIN_SREF, END_SREF}; + +bool isBankCommand(Command command) +{ + return (command <= 7); +} + +bool isRankCommand(Command command) +{ + return (command >= 8); +} + +bool isCasCommand(Command command) +{ + return (command <= 4); +} + +bool isRasCommand(Command command) +{ + return (command >= 5); +} diff --git a/DRAMSys/library/src/controller/Command.h b/DRAMSys/library/src/controller/Command.h index 176233fc..8365ef4d 100644 --- a/DRAMSys/library/src/controller/Command.h +++ b/DRAMSys/library/src/controller/Command.h @@ -47,15 +47,15 @@ using namespace tlm; enum Command { NOP, - PRE, - PREA, - ACT, RD, WR, RDA, WRA, - REFA, + PRE, + ACT, REFB, + PREA, + REFA, PDEA, PDXA, PDEP, @@ -68,6 +68,10 @@ std::string commandToString(Command command); const std::vector &getAllCommands(); unsigned numberOfCommands(); bool commandIsIn(Command command, std::vector commands); +bool isBankCommand(Command command); +bool isRankCommand(Command command); +bool isCasCommand(Command command); +bool isRasCommand(Command command); extern std::array phaseOfCommand; diff --git a/DRAMSys/library/src/controller/Controller.cpp b/DRAMSys/library/src/controller/Controller.cpp index 08ed05c5..7f935710 100644 --- a/DRAMSys/library/src/controller/Controller.cpp +++ b/DRAMSys/library/src/controller/Controller.cpp @@ -133,6 +133,14 @@ Controller::Controller(sc_module_name name) : bankMachines.begin() + (rankID + 1) * memSpec->BanksPerRank)); } + for (unsigned rankID = 0; rankID < memSpec->NumberOfRanks; rankID++) + { + PowerDownManager *manager = new PowerDownManager(bankMachinesOnRank[rankID], Rank(rankID), checker); + powerDownManagers.push_back(manager); + manager->triggerEntry(); + controllerEvent.notify(manager->start()); + } + if (config.ControllerCoreRefDisable) { for (unsigned rankID = 0; rankID < memSpec->NumberOfRanks; rankID++) @@ -143,7 +151,7 @@ Controller::Controller(sc_module_name name) : for (unsigned rankID = 0; rankID < memSpec->NumberOfRanks; rankID++) { RefreshManagerIF *manager = new RefreshManagerBankwise - (bankMachinesOnRank[rankID], Rank(rankID), checker); + (bankMachinesOnRank[rankID], powerDownManagers[rankID], Rank(rankID), checker); refreshManagers.push_back(manager); controllerEvent.notify(manager->start()); } @@ -153,7 +161,7 @@ Controller::Controller(sc_module_name name) : for (unsigned rankID = 0; rankID < memSpec->NumberOfRanks; rankID++) { RefreshManagerIF *manager = new RefreshManager - (bankMachinesOnRank[rankID], Rank(rankID), checker); + (bankMachinesOnRank[rankID], powerDownManagers[rankID], Rank(rankID), checker); refreshManagers.push_back(manager); controllerEvent.notify(manager->start()); } @@ -211,11 +219,14 @@ void Controller::controllerMethod() // (4) Start refresh managers to issue requests for the current time for (auto it : refreshManagers) it->start(); + for (auto it : powerDownManagers) + it->start(); // (5) Choose one request and send it to DRAM std::pair commandPair; std::vector> readyCommands; bool readyCmdBlocked = false; + // TODO: check if all parts have to be called // (5.1) Check for bank commands (PRE, ACT, RD/RDA or WR/WRA) for (auto it : bankMachines) { @@ -230,13 +241,21 @@ void Controller::controllerMethod() if (commandPair.second != nullptr) readyCommands.push_back(commandPair); } + // (5.3) Check for power-down commands (...TODO) + for (auto it : powerDownManagers) + { + commandPair = it->getNextCommand(); + if (commandPair.second != nullptr) + readyCommands.push_back(commandPair); + } + if (!readyCommands.empty()) { commandPair = commandMux->selectCommand(readyCommands); if (commandPair.second != nullptr) // can happen with FIFO strict { Rank rank = DramExtension::getRank(commandPair.second); - if (commandPair.first == Command::PREA || commandPair.first == Command::REFA) + if (isRankCommand(commandPair.first)) { for (auto it : bankMachinesOnRank[rank.ID()]) it->updateState(commandPair.first); @@ -247,6 +266,7 @@ void Controller::controllerMethod() bankMachines[bank.ID()]->updateState(commandPair.first); } refreshManagers[rank.ID()]->updateState(commandPair.first, commandPair.second); + powerDownManagers[rank.ID()]->updateState(commandPair.first); sendToDram(commandPair.first, commandPair.second); } else @@ -254,6 +274,7 @@ void Controller::controllerMethod() } // (6) Restart bank machines and refresh managers to issue new requests for the future + // TODO: check if all calls are necessary for (auto it : bankMachines) { sc_time delay = it->start(); @@ -262,6 +283,8 @@ void Controller::controllerMethod() } for (auto it : refreshManagers) controllerEvent.notify(it->start()); + for (auto it : powerDownManagers) + controllerEvent.notify(it->start()); } tlm_sync_enum Controller::nb_transport_fw(tlm_generic_payload &trans, @@ -317,15 +340,21 @@ void Controller::releasePayload() uint64_t id __attribute__((unused)) = DramExtension::getPayloadID(payloadToRelease); PRINTDEBUGMESSAGE(name(), "Payload " + std::to_string(id) + " left system."); - totalNumberOfPayloads--; - ranksNumberOfPayloads[DramExtension::getRank(payloadToRelease).ID()]--; + Rank rank = DramExtension::getRank(payloadToRelease); + payloadToRelease->release(); payloadToRelease = nullptr; timeToRelease = sc_max_time(); numberOfTransactionsServed++; + totalNumberOfPayloads--; + ranksNumberOfPayloads[rank.ID()]--; + if (totalNumberOfPayloads == 0) startBandwidthIdleCollector(); + + if (ranksNumberOfPayloads[rank.ID()] == 0) + powerDownManagers[rank.ID()]->triggerEntry(); } void Controller::acquirePayload() @@ -333,13 +362,19 @@ void Controller::acquirePayload() uint64_t id __attribute__((unused)) = DramExtension::getPayloadID(payloadToAcquire); PRINTDEBUGMESSAGE(name(), "Payload " + std::to_string(id) + " entered system."); + Rank rank = DramExtension::getRank(payloadToAcquire); + if (totalNumberOfPayloads == 0) endBandwithIdleCollector(); + if(ranksNumberOfPayloads[rank.ID()] == 0) + powerDownManagers[rank.ID()]->triggerExit(); + + totalNumberOfPayloads++; + ranksNumberOfPayloads[rank.ID()]++; + scheduler->storeRequest(payloadToAcquire); payloadToAcquire->acquire(); - totalNumberOfPayloads++; - ranksNumberOfPayloads[DramExtension::getRank(payloadToAcquire).ID()]++; payloadToAcquire->set_response_status(TLM_OK_RESPONSE); sendToFrontend(payloadToAcquire, END_REQ); payloadToAcquire = nullptr; diff --git a/DRAMSys/library/src/controller/Controller.h b/DRAMSys/library/src/controller/Controller.h index 14758071..94c36392 100644 --- a/DRAMSys/library/src/controller/Controller.h +++ b/DRAMSys/library/src/controller/Controller.h @@ -50,11 +50,13 @@ #include "../common/DebugManager.h" #include "checker/CheckerIF.h" #include "refresh/RefreshManagerIF.h" +#include "powerdown/PowerDownManager.h" using namespace tlm; class BankMachine; class SchedulerIF; +class PowerDownManager; class Controller : public GenericController { @@ -87,6 +89,7 @@ private: SchedulerIF *scheduler; CheckerIF *checker; std::vector refreshManagers; + std::vector powerDownManagers; void releasePayload(); void acquirePayload(); diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR3.cpp b/DRAMSys/library/src/controller/checker/CheckerDDR3.cpp index 74f80b04..d1a72fbe 100644 --- a/DRAMSys/library/src/controller/checker/CheckerDDR3.cpp +++ b/DRAMSys/library/src/controller/checker/CheckerDDR3.cpp @@ -92,6 +92,18 @@ sc_time CheckerDDR3::delayToSatisfyConstraints(Command command, Rank rank, BankG // if (lastCommandStart != SC_ZERO_TIME) // earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXP][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXS); + if (lastActivates[rank.ID()].size() >= 4) earliestTimeToStart = std::max(earliestTimeToStart, lastActivates[rank.ID()].front() + memSpec->tFAW); } @@ -125,6 +137,14 @@ sc_time CheckerDDR3::delayToSatisfyConstraints(Command command, Rank rank, BankG if (lastCommandStart != SC_ZERO_TIME) earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + burstClocks + memSpec->tWTR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXSDLL); } else if (command == Command::WR || command == Command::WRA) { @@ -148,6 +168,14 @@ 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); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXSDLL); } else if (command == Command::PRE) { @@ -162,6 +190,10 @@ sc_time CheckerDDR3::delayToSatisfyConstraints(Command command, Rank rank, BankG if (lastCommandStart != SC_ZERO_TIME) earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + burstClocks + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); } else if (command == Command::PREA) { @@ -185,6 +217,10 @@ sc_time CheckerDDR3::delayToSatisfyConstraints(Command command, Rank rank, BankG if (lastCommandStart != SC_ZERO_TIME) earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + burstClocks + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); } else if (command == Command::REFA) { @@ -212,6 +248,115 @@ sc_time CheckerDDR3::delayToSatisfyConstraints(Command command, Rank rank, BankG lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; if (lastCommandStart != SC_ZERO_TIME) earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXP][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXS); + } + else if (command == Command::PDEA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tRL + 5 * memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tRL + 5 * memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + 4 * memSpec->clk + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + 5 * memSpec->clk + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCKE); + } + else if (command == Command::PDXA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::PDEA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCKE); + } + else if (command == Command::PDEP) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tRL + 5 * memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tRL + 5 * memSpec->clk); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + 5 * memSpec->clk + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXP][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCKE); + + lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXS); + } + else if (command == Command::PDXP) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::PDEP][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCKE); + } + else if (command == Command::SREFEN) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + std::max(memSpec->tRL + 5 * memSpec->clk, memSpec->tAL + memSpec->tRTP + memSpec->tRP)); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + std::max(memSpec->tWL + 5 * memSpec->clk + memSpec->tWR, memSpec->tWL + burstClocks + 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::PDXP][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + + lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXS); + } + else if (command == Command::SREFEX) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEN][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCKESR); } else reportFatal("CheckerDDR3", "Unknown command!"); diff --git a/DRAMSys/library/src/controller/cmdmux/CmdMuxStrict.cpp b/DRAMSys/library/src/controller/cmdmux/CmdMuxStrict.cpp index ff558678..6e2d623e 100644 --- a/DRAMSys/library/src/controller/cmdmux/CmdMuxStrict.cpp +++ b/DRAMSys/library/src/controller/cmdmux/CmdMuxStrict.cpp @@ -41,7 +41,7 @@ CmdMuxStrict::selectCommand(std::vector(Command::NOP, nullptr); diff --git a/DRAMSys/library/src/controller/powerdown/PowerDownManager.cpp b/DRAMSys/library/src/controller/powerdown/PowerDownManager.cpp new file mode 100644 index 00000000..b0fadef6 --- /dev/null +++ b/DRAMSys/library/src/controller/powerdown/PowerDownManager.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#include "PowerDownManager.h" +#include "../../common/utils.h" + +PowerDownManager::PowerDownManager(std::vector &bankMachines, Rank rank, CheckerIF *checker) + : bankMachines(bankMachines), rank(rank), checker(checker) +{ + setUpDummy(powerDownPayload, rank); +} + +void PowerDownManager::triggerEntry() +{ + if (state == PdmState::Idle) + triggered = true; +} + +void PowerDownManager::triggerExit() +{ + if (state == PdmState::Idle) + triggered = false; + else + triggered = true; +} + +std::pair PowerDownManager::getNextCommand() +{ + if (sc_time_stamp() == timeToSchedule) + return std::pair(nextCommand, &powerDownPayload); + else + return std::pair(Command::NOP, nullptr); +} + +sc_time PowerDownManager::start() +{ + timeToSchedule = sc_max_time(); + sc_time delay = sc_max_time() - sc_time_stamp(); + + if (triggered) + { + if (state == PdmState::Idle) + { + nextCommand = Command::PDEP; + for (auto it : bankMachines) + { + if(it->getState() == BmState::Activated) + { + nextCommand = Command::PDEA; + break; + } + } + } + else if (state == PdmState::ActivePd) + nextCommand = Command::PDXA; + else if (state == PdmState::PrechargePd) + nextCommand = Command::PDXP; + // TODO: add self refresh + delay = checker->delayToSatisfyConstraints(nextCommand, rank, BankGroup(0), Bank(0)); + timeToSchedule = sc_time_stamp() + delay; + } + + return delay; +} + +void PowerDownManager::updateState(Command command) +{ + if (command == Command::PDEA) + { + state = PdmState::ActivePd; + triggered = false; + } + else if (command == Command::PDEP) + { + state = PdmState::PrechargePd; + triggered = false; + } + else if (command == Command::PDXA || command == Command::PDXP) + { + state = PdmState::Idle; + triggered = false; + } +} diff --git a/DRAMSys/library/src/controller/powerdown/PowerDownManager.h b/DRAMSys/library/src/controller/powerdown/PowerDownManager.h new file mode 100644 index 00000000..50692f3a --- /dev/null +++ b/DRAMSys/library/src/controller/powerdown/PowerDownManager.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#ifndef POWERDOWNMANAGER_H +#define POWERDOWNMANAGER_H + +#include "../BankMachine.h" +#include "../checker/CheckerIF.h" + +using namespace tlm; + +class BankMachine; + +class PowerDownManager +{ +public: + PowerDownManager(std::vector &, Rank, CheckerIF *); + + void triggerEntry(); + void triggerExit(); + + std::pair getNextCommand(); + void updateState(Command); + sc_time start(); + +private: + enum class PdmState {Idle, ActivePd, PrechargePd, SelfRefresh} state = PdmState::Idle; + bool triggered = false; + std::vector &bankMachines; + tlm_generic_payload powerDownPayload; + Rank rank; + CheckerIF *checker; + + sc_time timeToSchedule; + Command nextCommand; +}; + +#endif // POWERDOWNMANAGER_H diff --git a/DRAMSys/library/src/controller/refresh/RefreshManager.cpp b/DRAMSys/library/src/controller/refresh/RefreshManager.cpp index 906db024..8f32a3b9 100644 --- a/DRAMSys/library/src/controller/refresh/RefreshManager.cpp +++ b/DRAMSys/library/src/controller/refresh/RefreshManager.cpp @@ -37,8 +37,9 @@ #include "../../configuration/Configuration.h" #include "../../common/utils.h" -RefreshManager::RefreshManager(std::vector &bankMachines, Rank rank, CheckerIF *checker) - : bankMachines(bankMachines), rank(rank), checker(checker) +RefreshManager::RefreshManager(std::vector &bankMachines, + PowerDownManager *powerDownManager, Rank rank, CheckerIF *checker) + : bankMachines(bankMachines), powerDownManager(powerDownManager), rank(rank), checker(checker) { Configuration &config = Configuration::getInstance(); memSpec = config.memSpec; @@ -53,23 +54,22 @@ RefreshManager::RefreshManager(std::vector &bankMachines, Rank ra std::pair RefreshManager::getNextCommand() { - if (sc_time_stamp() == timeToSchedule) + if (sc_time_stamp() == timeToSchedule && !blocked) return std::pair(nextCommand, &refreshPayload); else return std::pair(Command::NOP, nullptr); } -void RefreshManager::block() -{ - blocked = true; -} - sc_time RefreshManager::start() { timeToSchedule = sc_max_time(); if (sc_time_stamp() >= timeForNextTrigger) { + powerDownManager->triggerExit(); + if (blocked) + return sc_max_time() - sc_time_stamp(); + if (sc_time_stamp() >= timeForNextTrigger + memSpec->getRefreshIntervalAB()) { timeForNextTrigger += memSpec->getRefreshIntervalAB(); @@ -121,7 +121,7 @@ sc_time RefreshManager::start() { for (auto it : bankMachines) { - if (!it->isIdle()) // at least one bank is active -> abort pulling in + if (!it->isIdle()) // at least one bank has a payload -> abort pulling in { state = RmState::Regular; timeForNextTrigger += memSpec->getRefreshIntervalAB(); @@ -158,6 +158,8 @@ void RefreshManager::updateState(Command command, tlm_generic_payload *) { state = RmState::Regular; timeForNextTrigger += memSpec->getRefreshIntervalAB(); + // TODO: is only allowed if all banks are still idle + //powerDownManager->triggerEntry(); } } else if (command == Command::PREA) @@ -165,6 +167,11 @@ void RefreshManager::updateState(Command command, tlm_generic_payload *) // if PREA was successful we will do the refresh in any case for (auto it : bankMachines) it->block(); + // TODO: remove for and insert blocking directly into BM state = RmState::Precharged; } + else if (command == Command::PDEA || command == Command::PDEP) + blocked = true; + else if (command == Command::PDXA || command == Command::PDXP) + blocked = false; } diff --git a/DRAMSys/library/src/controller/refresh/RefreshManager.h b/DRAMSys/library/src/controller/refresh/RefreshManager.h index a16981d4..36dca117 100644 --- a/DRAMSys/library/src/controller/refresh/RefreshManager.h +++ b/DRAMSys/library/src/controller/refresh/RefreshManager.h @@ -38,6 +38,7 @@ #include "RefreshManagerIF.h" #include "../../configuration/memspec/MemSpec.h" #include "../BankMachine.h" +#include "../powerdown/PowerDownManager.h" #include "../checker/CheckerIF.h" using namespace tlm; @@ -45,17 +46,17 @@ using namespace tlm; class RefreshManager final : public RefreshManagerIF { public: - RefreshManager(std::vector &, Rank, CheckerIF *); + RefreshManager(std::vector &, PowerDownManager *, Rank, CheckerIF *); std::pair getNextCommand(); sc_time start(); void updateState(Command, tlm_generic_payload *); - void block(); private: enum class RmState {Regular, Precharged, Pulledin} state = RmState::Regular; const MemSpec *memSpec; - std::vector bankMachines; + std::vector &bankMachines; + PowerDownManager *powerDownManager; tlm_generic_payload refreshPayload; sc_time timeForNextTrigger = sc_max_time(); sc_time timeToSchedule = sc_max_time(); diff --git a/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.cpp b/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.cpp index 7cdc42b7..874d877e 100644 --- a/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.cpp +++ b/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.cpp @@ -37,8 +37,9 @@ #include "../../common/utils.h" #include "../../common/dramExtensions.h" -RefreshManagerBankwise::RefreshManagerBankwise(std::vector &bankMachines, Rank rank, CheckerIF *checker) - : bankMachines(bankMachines), rank(rank), checker(checker) +RefreshManagerBankwise::RefreshManagerBankwise(std::vector &bankMachines, + PowerDownManager *powerDownManager, Rank rank, CheckerIF *checker) + : bankMachines(bankMachines), powerDownManager(powerDownManager), rank(rank), checker(checker) { Configuration &config = Configuration::getInstance(); memSpec = config.memSpec; @@ -66,11 +67,6 @@ std::pair RefreshManagerBankwise::getNextCommand return std::pair(Command::NOP, nullptr); } -void RefreshManagerBankwise::block() -{ - blocked = true; -} - sc_time RefreshManagerBankwise::start() { timeToSchedule = sc_max_time(); @@ -213,4 +209,8 @@ void RefreshManagerBankwise::updateState(Command command, tlm_generic_payload *p state = RmState::Precharged; } } + else if (command == Command::PDEA || command == Command::PDEP) + blocked = true; + else if (command == Command::PDXA || command == Command::PDXP) + blocked = false; } diff --git a/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.h b/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.h index d986ac74..169f4719 100644 --- a/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.h +++ b/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.h @@ -38,6 +38,7 @@ #include "RefreshManagerIF.h" #include "../../configuration/memspec/MemSpec.h" #include "../BankMachine.h" +#include "../powerdown/PowerDownManager.h" #include #include #include @@ -47,17 +48,17 @@ using namespace tlm; class RefreshManagerBankwise final : public RefreshManagerIF { public: - RefreshManagerBankwise(std::vector &, Rank, CheckerIF *); + RefreshManagerBankwise(std::vector &, PowerDownManager *, Rank, CheckerIF *); std::pair getNextCommand(); sc_time start(); void updateState(Command, tlm_generic_payload *); - void block(); private: enum class RmState {Regular, Precharged, Pulledin} state = RmState::Regular; const MemSpec *memSpec; - std::vector bankMachines; + std::vector &bankMachines; + PowerDownManager *powerDownManager; std::vector refreshPayloads; sc_time timeForNextTrigger = sc_max_time(); sc_time timeToSchedule = sc_max_time(); diff --git a/DRAMSys/library/src/controller/refresh/RefreshManagerDummy.h b/DRAMSys/library/src/controller/refresh/RefreshManagerDummy.h index 301d724e..2d895cf3 100644 --- a/DRAMSys/library/src/controller/refresh/RefreshManagerDummy.h +++ b/DRAMSys/library/src/controller/refresh/RefreshManagerDummy.h @@ -49,7 +49,6 @@ public: std::pair getNextCommand(); sc_time start(); void updateState(Command, tlm_generic_payload *) {} - void block() {} }; #endif // REFRESHMANAGERDUMMY_H diff --git a/DRAMSys/library/src/controller/refresh/RefreshManagerIF.h b/DRAMSys/library/src/controller/refresh/RefreshManagerIF.h index d2b78266..d1e589ca 100644 --- a/DRAMSys/library/src/controller/refresh/RefreshManagerIF.h +++ b/DRAMSys/library/src/controller/refresh/RefreshManagerIF.h @@ -50,7 +50,6 @@ public: virtual std::pair getNextCommand() = 0; virtual sc_time start() = 0; virtual void updateState(Command, tlm_generic_payload *) = 0; - virtual void block() = 0; }; #endif // REFRESHMANAGERIF_H