diff --git a/DRAMSys/library/CMakeLists.txt b/DRAMSys/library/CMakeLists.txt index 7871f809..de833506 100644 --- a/DRAMSys/library/CMakeLists.txt +++ b/DRAMSys/library/CMakeLists.txt @@ -137,6 +137,7 @@ add_library(DRAMSysLibrary src/controller/refresh/RefreshManagerDummy.cpp src/controller/refresh/RefreshManagerRankwise.cpp src/controller/refresh/RefreshManagerBankwise.cpp + src/controller/refresh/RefreshManagerGroupwise.cpp src/controller/respqueue/RespQueueIF.h src/controller/respqueue/RespQueueFifo.cpp diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8Gb_DDR5-3200A_8bit.json b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8Gb_DDR5-3200A_8bit.json index 0b580d0d..492eea26 100644 --- a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8Gb_DDR5-3200A_8bit.json +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8Gb_DDR5-3200A_8bit.json @@ -28,6 +28,7 @@ "RCD": 22, "REFM": 1, "REFI": 6240, + "REFISB": 1560, "RFC": 312, "RL": 22, "RPRE": 1, diff --git a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x8x8Gb_DDR5-3200A_4bit.json b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x8x8Gb_DDR5-3200A_4bit.json index 95e2e703..d8984701 100644 --- a/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x8x8Gb_DDR5-3200A_4bit.json +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8x8x8Gb_DDR5-3200A_4bit.json @@ -50,7 +50,8 @@ "RFC_dpr": 104, "RFCsb_slr": 184, "RFCsb_dlr": 62, - "REFI": 6240, + "REFI": 6240, + "REFISB": 1560, "REFSBRD_slr": 48, "REFSBRD_dlr": 24, "RTRS": 2, diff --git a/DRAMSys/library/src/configuration/memspec/MemSpec.cpp b/DRAMSys/library/src/configuration/memspec/MemSpec.cpp index 39fd1211..ac893709 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpec.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpec.cpp @@ -74,3 +74,21 @@ sc_time MemSpec::getCommandLength(Command command) const { return tCK * commandLengthInCycles[command]; } + +sc_time MemSpec::getRefreshIntervalAB() const +{ + SC_REPORT_FATAL("MemSpec", "All bank refresh not supported"); + return SC_ZERO_TIME; +} + +sc_time MemSpec::getRefreshIntervalPB() const +{ + SC_REPORT_FATAL("MemSpec", "Per bank refresh not supported"); + return SC_ZERO_TIME; +} + +sc_time MemSpec::getRefreshIntervalSB() const +{ + SC_REPORT_FATAL("MemSpec", "Same bank refresh not supported"); + return SC_ZERO_TIME; +} diff --git a/DRAMSys/library/src/configuration/memspec/MemSpec.h b/DRAMSys/library/src/configuration/memspec/MemSpec.h index 3f97dcff..1f9687ab 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpec.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpec.h @@ -71,8 +71,9 @@ public: virtual ~MemSpec() {} - virtual sc_time getRefreshIntervalAB() const = 0; - virtual sc_time getRefreshIntervalPB() const = 0; + virtual sc_time getRefreshIntervalAB() const; + virtual sc_time getRefreshIntervalPB() const; + virtual sc_time getRefreshIntervalSB() const; virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const = 0; virtual TimeInterval getIntervalOnDataStrobe(Command) const = 0; diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.cpp index 427c3f85..21a1434a 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.cpp @@ -95,12 +95,6 @@ sc_time MemSpecDDR3::getRefreshIntervalAB() const return tREFI; } -sc_time MemSpecDDR3::getRefreshIntervalPB() const -{ - SC_REPORT_FATAL("MemSpecDDR3", "Per bank refresh not supported"); - return SC_ZERO_TIME; -} - // Returns the execution time for commands that have a fixed execution time sc_time MemSpecDDR3::getExecutionTime(Command command, const tlm_generic_payload &) const { diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.h b/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.h index f8a1d6de..f71cde71 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecDDR3.h @@ -88,7 +88,6 @@ public: const double iDD3P1; virtual sc_time getRefreshIntervalAB() const override; - virtual sc_time getRefreshIntervalPB() const override; virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override; virtual TimeInterval getIntervalOnDataStrobe(Command) const override; diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.cpp index fdb2f843..cd9c2624 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.cpp @@ -114,12 +114,6 @@ sc_time MemSpecDDR4::getRefreshIntervalAB() const return tREFI; } -sc_time MemSpecDDR4::getRefreshIntervalPB() const -{ - SC_REPORT_FATAL("MemSpecDDR4", "Per bank refresh not supported"); - return SC_ZERO_TIME; -} - // Returns the execution time for commands that have a fixed execution time sc_time MemSpecDDR4::getExecutionTime(Command command, const tlm_generic_payload &) const { diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.h b/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.h index c702f871..d6da746e 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecDDR4.h @@ -95,7 +95,6 @@ public: const double iDD62; const double vDD2; - virtual sc_time getRefreshIntervalPB() const override; virtual sc_time getRefreshIntervalAB() const override; virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override; diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.cpp index 88f998ff..14a3a334 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.cpp @@ -91,6 +91,7 @@ MemSpecDDR5::MemSpecDDR5(json &memspec) tRFCsb_slr (tCK * parseUint(memspec["memtimingspec"]["RFCsb_slr"], "RFCsb_slr")), tRFCsb_dlr (tCK * parseUint(memspec["memtimingspec"]["RFCsb_dlr"], "RFCsb_dlr")), tREFI (tCK * parseUint(memspec["memtimingspec"]["REFI"], "REFI")), + tREFIsb (tCK * parseUint(memspec["memtimingspec"]["REFISB"], "REFISB")), tREFSBRD_slr (tCK * parseUint(memspec["memtimingspec"]["REFSBRD_slr"], "REFSBRD_slr")), tREFSBRD_dlr (tCK * parseUint(memspec["memtimingspec"]["REFSBRD_dlr"], "REFSBRD_dlr")), tRTRS (tCK * parseUint(memspec["memtimingspec"]["RTRS"], "RTRS")), @@ -113,10 +114,9 @@ sc_time MemSpecDDR5::getRefreshIntervalAB() const return tREFI; } -sc_time MemSpecDDR5::getRefreshIntervalPB() const +sc_time MemSpecDDR5::getRefreshIntervalSB() const { - SC_REPORT_FATAL("MemSpecDDR5", "Per bank refresh not supported"); - return SC_ZERO_TIME; + return tREFIsb; } // Returns the execution time for commands that have a fixed execution time diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.h b/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.h index f243b1a0..3103c3cd 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.h @@ -85,6 +85,7 @@ public: const sc_time tRFCsb_slr; const sc_time tRFCsb_dlr; const sc_time tREFI; + const sc_time tREFIsb; const sc_time tREFSBRD_slr; const sc_time tREFSBRD_dlr; const sc_time tRTRS; @@ -99,8 +100,8 @@ public: // Currents and Voltages: // TODO: to be completed - virtual sc_time getRefreshIntervalPB() const override; virtual sc_time getRefreshIntervalAB() const override; + virtual sc_time getRefreshIntervalSB() const override; virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override; virtual TimeInterval getIntervalOnDataStrobe(Command) const override; diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.h b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.h index 84e7113e..690f29b5 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.h @@ -85,8 +85,8 @@ public: // Currents and Voltages: // TODO: to be completed - virtual sc_time getRefreshIntervalPB() const override; virtual sc_time getRefreshIntervalAB() const override; + virtual sc_time getRefreshIntervalPB() const override; virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override; virtual TimeInterval getIntervalOnDataStrobe(Command) const override; diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.h b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.h index f5d22239..130606f7 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.h @@ -85,8 +85,8 @@ public: // Currents and Voltages: // TODO: to be completed - virtual sc_time getRefreshIntervalPB() const override; virtual sc_time getRefreshIntervalAB() const override; + virtual sc_time getRefreshIntervalPB() const override; virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override; virtual TimeInterval getIntervalOnDataStrobe(Command) const override; diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.h b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.h index a4d2318d..7e2f91c8 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.h @@ -87,8 +87,8 @@ public: // Currents and Voltages: // TODO: to be completed - virtual sc_time getRefreshIntervalPB() const override; virtual sc_time getRefreshIntervalAB() const override; + virtual sc_time getRefreshIntervalPB() const override; virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override; virtual TimeInterval getIntervalOnDataStrobe(Command) const override; diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.h b/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.h index a6885b49..148be20a 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.h @@ -80,8 +80,8 @@ public: // Currents and Voltages: // TODO: to be completed - virtual sc_time getRefreshIntervalPB() const override; virtual sc_time getRefreshIntervalAB() const override; + virtual sc_time getRefreshIntervalPB() const override; virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override; virtual TimeInterval getIntervalOnDataStrobe(Command) const override; diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecLPDDR4.h b/DRAMSys/library/src/configuration/memspec/MemSpecLPDDR4.h index 26da297c..d85998a9 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecLPDDR4.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecLPDDR4.h @@ -80,8 +80,8 @@ public: // Currents and Voltages: // TODO: to be completed - virtual sc_time getRefreshIntervalPB() const override; virtual sc_time getRefreshIntervalAB() const override; + virtual sc_time getRefreshIntervalPB() const override; virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override; virtual TimeInterval getIntervalOnDataStrobe(Command) const override; diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.cpp index 0d8b9be6..577c1ca3 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.cpp @@ -101,12 +101,6 @@ sc_time MemSpecWideIO::getRefreshIntervalAB() const return tREFI; } -sc_time MemSpecWideIO::getRefreshIntervalPB() const -{ - SC_REPORT_FATAL("MemSpecWideIO", "Per bank refresh not supported"); - return SC_ZERO_TIME; -} - // Returns the execution time for commands that have a fixed execution time sc_time MemSpecWideIO::getExecutionTime(Command command, const tlm_generic_payload &) const { diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.h b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.h index 2ce092ff..49d351f7 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO.h @@ -93,7 +93,6 @@ public: const double iDD62; const double vDD2; - virtual sc_time getRefreshIntervalPB() const override; virtual sc_time getRefreshIntervalAB() const override; virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override; diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecWideIO2.h b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO2.h index d56f9d30..877f15bd 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecWideIO2.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecWideIO2.h @@ -74,8 +74,8 @@ public: // Currents and Voltages: // TODO: to be completed - virtual sc_time getRefreshIntervalPB() const override; virtual sc_time getRefreshIntervalAB() const override; + virtual sc_time getRefreshIntervalPB() const override; virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override; virtual TimeInterval getIntervalOnDataStrobe(Command) const override; diff --git a/DRAMSys/library/src/controller/BankMachine.cpp b/DRAMSys/library/src/controller/BankMachine.cpp index 82259337..115dbf8f 100644 --- a/DRAMSys/library/src/controller/BankMachine.cpp +++ b/DRAMSys/library/src/controller/BankMachine.cpp @@ -57,7 +57,7 @@ void BankMachine::updateState(Command command) currentState = BmState::Activated; currentRow = DramExtension::getRow(currentPayload); break; - case Command::PRE: case Command::PREA: + case Command::PRE: case Command::PREA: case Command::PRESB: currentState = BmState::Precharged; break; case Command::RD: case Command::WR: @@ -70,7 +70,7 @@ void BankMachine::updateState(Command command) case Command::PDEA: case Command::PDEP: case Command::SREFEN: sleeping = true; break; - case Command::REFA: case Command::REFB: + case Command::REFA: case Command::REFB: case Command::REFSB: sleeping = false; blocked = false; break; diff --git a/DRAMSys/library/src/controller/Controller.cpp b/DRAMSys/library/src/controller/Controller.cpp index 5a81d6f1..912f990d 100644 --- a/DRAMSys/library/src/controller/Controller.cpp +++ b/DRAMSys/library/src/controller/Controller.cpp @@ -54,9 +54,10 @@ #include "cmdmux/CmdMuxOldest.h" #include "respqueue/RespQueueFifo.h" #include "respqueue/RespQueueReorder.h" -#include "refresh/RefreshManagerRankwise.h" #include "refresh/RefreshManagerDummy.h" +#include "refresh/RefreshManagerRankwise.h" #include "refresh/RefreshManagerBankwise.h" +#include "refresh/RefreshManagerGroupwise.h" #include "powerdown/PowerDownManagerStaggered.h" #include "powerdown/PowerDownManagerDummy.h" @@ -185,6 +186,15 @@ Controller::Controller(sc_module_name name) : refreshManagers.push_back(manager); } } + else if (config.refreshPolicy == "Groupwise") + { + for (unsigned rankID = 0; rankID < memSpec->numberOfRanks; rankID++) + { + RefreshManagerIF *manager = new RefreshManagerGroupwise + (bankMachinesOnRank[rankID], powerDownManagers[rankID], Rank(rankID), checker); + refreshManagers.push_back(manager); + } + } else if (config.refreshPolicy == "Bankwise") { for (unsigned rankID = 0; rankID < memSpec->numberOfRanks; rankID++) @@ -271,28 +281,36 @@ void Controller::controllerMethod() if (!readyCommands.empty()) { commandTuple = cmdMux->selectCommand(readyCommands); - if (std::get<0>(commandTuple) != Command::NOP) // can happen with FIFO strict + Command selectedCommand = std::get<0>(commandTuple); + if (selectedCommand != Command::NOP) // can happen with FIFO strict { - Rank rank = DramExtension::getRank(std::get<1>(commandTuple)); - BankGroup bankgroup = DramExtension::getBankGroup(std::get<1>(commandTuple)); - Bank bank = DramExtension::getBank(std::get<1>(commandTuple)); + tlm_generic_payload *selectedPayload = std::get<1>(commandTuple); + Rank rank = DramExtension::getRank(selectedPayload); + BankGroup bankgroup = DramExtension::getBankGroup(selectedPayload); + Bank bank = DramExtension::getBank(selectedPayload); - if (isRankCommand(std::get<0>(commandTuple))) + if (isRankCommand(selectedCommand)) { for (auto it : bankMachinesOnRank[rank.ID()]) - it->updateState(std::get<0>(commandTuple)); + it->updateState(selectedCommand); + } + else if (isGroupCommand(selectedCommand)) + { + for (unsigned bankID = (bank.ID() % memSpec->banksPerGroup); + bankID < memSpec->banksPerRank; bankID += memSpec->banksPerGroup) + bankMachinesOnRank[rank.ID()][bankID]->updateState(selectedCommand); } else - bankMachines[bank.ID()]->updateState(std::get<0>(commandTuple)); + bankMachines[bank.ID()]->updateState(selectedCommand); - refreshManagers[rank.ID()]->updateState(std::get<0>(commandTuple)); - powerDownManagers[rank.ID()]->updateState(std::get<0>(commandTuple)); - checker->insert(std::get<0>(commandTuple), rank, bankgroup, bank); + refreshManagers[rank.ID()]->updateState(selectedCommand); + powerDownManagers[rank.ID()]->updateState(selectedCommand); + checker->insert(selectedCommand, rank, bankgroup, bank); - if (isCasCommand(std::get<0>(commandTuple))) + if (isCasCommand(selectedCommand)) { - scheduler->removeRequest(std::get<1>(commandTuple)); - respQueue->insertPayload(std::get<1>(commandTuple), memSpec->getIntervalOnDataStrobe(std::get<0>(commandTuple)).end); + scheduler->removeRequest(selectedPayload); + respQueue->insertPayload(selectedPayload, memSpec->getIntervalOnDataStrobe(selectedCommand).end); sc_time triggerTime = respQueue->getTriggerTime(); if (triggerTime != sc_max_time()) @@ -303,7 +321,7 @@ void Controller::controllerMethod() if (ranksNumberOfPayloads[rank.ID()] == 0) powerDownManagers[rank.ID()]->triggerEntry(); - sendToDram(std::get<0>(commandTuple), std::get<1>(commandTuple)); + sendToDram(selectedCommand, selectedPayload); } else readyCmdBlocked = true; diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR5.cpp b/DRAMSys/library/src/controller/checker/CheckerDDR5.cpp index 68de6a49..24679491 100644 --- a/DRAMSys/library/src/controller/checker/CheckerDDR5.cpp +++ b/DRAMSys/library/src/controller/checker/CheckerDDR5.cpp @@ -53,6 +53,9 @@ CheckerDDR5::CheckerDDR5() (numberOfCommands(), std::vector(memSpec->numberOfBanks)); lastScheduledByCommand = std::vector(numberOfCommands()); + lastScheduledByCommandAndBankInGroup = std::vector> + (numberOfCommands(), std::vector(memSpec->numberOfRanks * memSpec->banksPerGroup)); + last4ActivatesLogical = std::vector>(memSpec->numberOfLogicalRanks); last4ActivatesPhysical = std::vector>(memSpec->numberOfPhysicalRanks); @@ -80,6 +83,8 @@ CheckerDDR5::CheckerDDR5() tRDPDEN = memSpec->tRL + tRD_BURST + memSpec->tCK; tWRPDEN = memSpec->tWL + tWR_BURST + memSpec->tWR + memSpec->tCK; tWRAPDEN = memSpec->tWL + tWR_BURST + memSpec->tWR + memSpec->tCK; + + // TODO: tRTP BL 32!!! (check LPDDR4) } sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGroup bankgroup, Bank bank) const @@ -91,6 +96,8 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGr Rank physicalrank = Rank(logicalrank.ID() / memSpec->logicalRanksPerPhysicalRank); Rank dimmrank = Rank(physicalrank.ID() / memSpec->physicalRanksPerDIMMRank); + unsigned bankInGroupID = rank.ID() * memSpec->banksPerGroup + bank.ID() % memSpec->banksPerGroup; + if (command == Command::RD || command == Command::RDA) { lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; @@ -304,9 +311,37 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGr if (lastCommandStart != SC_ZERO_TIME) earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP - memSpec->tCK); + lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::PRESB][bankInGroupID]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP - memSpec->tCK); + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::REFA][logicalrank.ID()]; if (lastCommandStart != SC_ZERO_TIME) - earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC_slr); + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC_slr - memSpec->tCK); + + // TODO: No tRFC_dlr and tRFC_dpr between REFA and ACT? + + lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::REFSB][bankInGroupID]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCsb_slr - memSpec->tCK); + + // TODO: No tRFCsb_dlr between REFSB and ACT? + + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::REFSB][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tREFSBRD_slr - memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::REFSB][physicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tREFSBRD_dlr - memSpec->tCK); + + if (last4ActivatesLogical[logicalrank.ID()].size() >= 4) + earliestTimeToStart = std::max(earliestTimeToStart, last4ActivatesLogical[logicalrank.ID()].front() + + memSpec->tFAW_slr - memSpec->tCK); + + if (last4ActivatesPhysical[physicalrank.ID()].size() >= 4) + earliestTimeToStart = std::max(earliestTimeToStart, last4ActivatesPhysical[physicalrank.ID()].front() + + memSpec->tFAW_dlr - memSpec->tCK); } else if (command == Command::PRE) { @@ -329,6 +364,10 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGr lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::PREA][physicalrank.ID()]; if (lastCommandStart != SC_ZERO_TIME) earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + + lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::PRESB][physicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); } else if (command == Command::PREA) { @@ -359,6 +398,40 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGr lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::PREA][physicalrank.ID()]; if (lastCommandStart != SC_ZERO_TIME) earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + + // PRESB tPPD + } + else if (command == Command::PRESB) + { + lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::ACT][bankInGroupID]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::RD][bankInGroupID]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::RDA][bankInGroupID]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::WR][bankInGroupID]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::WRA][bankInGroupID]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::PRE][physicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + + // PREA tRP + + lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::PRESB][physicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); } else if (command == Command::REFA) { @@ -393,6 +466,67 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGr lastCommandStart = lastScheduledByCommandAndDIMMRank[Command::REFA][dimmrank.ID()]; if (lastCommandStart != SC_ZERO_TIME) earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC_dpr); + + // REFSB tRFCsb + // PRESB tRP + } + else if (command == Command::REFSB) + { + lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::ACT][bankInGroupID]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::ACT][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRD_L_slr + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::RDA][bankInGroupID]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDAACT + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRAACT + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::PRE][bankInGroupID]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + // PREA tRP + + lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::PRESB][bankInGroupID]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::REFA][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC_slr); + + // TODO: check this + lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::REFA][physicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC_dlr); + + // TODO: check this + lastCommandStart = lastScheduledByCommandAndDIMMRank[Command::REFA][dimmrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC_dpr); + + lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::REFSB][logicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCsb_slr); + + lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::REFSB][physicalrank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCsb_dlr); + + if (last4ActivatesLogical[logicalrank.ID()].size() >= 4) + earliestTimeToStart = std::max(earliestTimeToStart, + last4ActivatesLogical[logicalrank.ID()].front() + memSpec->tFAW_slr); + + if (last4ActivatesPhysical[physicalrank.ID()].size() >= 4) + earliestTimeToStart = std::max(earliestTimeToStart, + last4ActivatesPhysical[physicalrank.ID()].front() + memSpec->tFAW_dlr); } else SC_REPORT_FATAL("CheckerDDR5", "Unknown command!"); @@ -420,7 +554,10 @@ void CheckerDDR5::insert(Command command, Rank rank, BankGroup bankgroup, Bank b lastCommandOnBus = sc_time_stamp() + memSpec->getCommandLength(command) - memSpec->tCK; - if (command == Command::ACT) + lastScheduledByCommandAndBankInGroup[command][rank.ID() * memSpec->banksPerGroup + + bank.ID() % memSpec->banksPerGroup] = sc_time_stamp(); + + if (command == Command::ACT || command == Command::REFSB) { if (last4ActivatesLogical[logicalrank.ID()].size() == 4) last4ActivatesLogical[logicalrank.ID()].pop(); diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR5.h b/DRAMSys/library/src/controller/checker/CheckerDDR5.h index af5cf61f..54d5c080 100644 --- a/DRAMSys/library/src/controller/checker/CheckerDDR5.h +++ b/DRAMSys/library/src/controller/checker/CheckerDDR5.h @@ -59,6 +59,8 @@ private: std::vector lastScheduledByCommand; sc_time lastCommandOnBus; + std::vector> lastScheduledByCommandAndBankInGroup; + std::vector> last4ActivatesPhysical; std::vector> last4ActivatesLogical; diff --git a/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.cpp b/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.cpp index 6acb4e6c..48685335 100644 --- a/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.cpp +++ b/DRAMSys/library/src/controller/refresh/RefreshManagerBankwise.cpp @@ -39,9 +39,9 @@ using namespace tlm; -RefreshManagerBankwise::RefreshManagerBankwise(std::vector &bankMachines, +RefreshManagerBankwise::RefreshManagerBankwise(std::vector &bankMachinesOnRank, PowerDownManagerIF *powerDownManager, Rank rank, CheckerIF *checker) - : bankMachinesOnRank(bankMachines), powerDownManager(powerDownManager), rank(rank), checker(checker) + : bankMachinesOnRank(bankMachinesOnRank), powerDownManager(powerDownManager), rank(rank), checker(checker) { Configuration &config = Configuration::getInstance(); memSpec = config.memSpec; @@ -50,8 +50,9 @@ RefreshManagerBankwise::RefreshManagerBankwise(std::vector &bankM refreshPayloads = std::vector(memSpec->banksPerRank); for (unsigned bankID = 0; bankID < memSpec->banksPerRank; bankID++) { - setUpDummy(refreshPayloads[bankID], 0, rank, bankMachines[bankID]->getBankGroup(), bankMachines[bankID]->getBank()); - allBankMachines.push_back(bankMachines[bankID]); + setUpDummy(refreshPayloads[bankID], 0, rank, bankMachinesOnRank[bankID]->getBankGroup(), + bankMachinesOnRank[bankID]->getBank()); + allBankMachines.push_back(bankMachinesOnRank[bankID]); } remainingBankMachines = allBankMachines; currentBankMachine = *remainingBankMachines.begin(); diff --git a/DRAMSys/library/src/controller/refresh/RefreshManagerGroupwise.cpp b/DRAMSys/library/src/controller/refresh/RefreshManagerGroupwise.cpp new file mode 100644 index 00000000..07bf1d7b --- /dev/null +++ b/DRAMSys/library/src/controller/refresh/RefreshManagerGroupwise.cpp @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2020, Technische Universität 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 "RefreshManagerGroupwise.h" +#include "../../configuration/Configuration.h" +#include "../../common/utils.h" +#include "../../common/dramExtensions.h" + +using namespace tlm; + +RefreshManagerGroupwise::RefreshManagerGroupwise(std::vector &bankMachines, + PowerDownManagerIF *powerDownManager, Rank rank, CheckerIF *checker) + : bankMachinesOnRank(bankMachines), powerDownManager(powerDownManager), rank(rank), checker(checker) +{ + Configuration &config = Configuration::getInstance(); + memSpec = config.memSpec; + timeForNextTrigger = memSpec->getRefreshIntervalPB(); + + refreshPayloads = std::vector(memSpec->banksPerRank); + for (unsigned bankID = 0; bankID < memSpec->banksPerRank; bankID++) + { + setUpDummy(refreshPayloads[bankID], 0, rank, bankMachines[bankID]->getBankGroup(), bankMachines[bankID]->getBank()); + allBankMachines.push_back(bankMachines[bankID]); + } + remainingBankMachines = allBankMachines; + currentBankMachine = *remainingBankMachines.begin(); + + maxPostponed = config.refreshMaxPostponed * memSpec->banksPerRank; + maxPulledin = -(config.refreshMaxPulledin * memSpec->banksPerRank); +} + +std::tuple RefreshManagerGroupwise::getNextCommand() +{ + return std::tuple + (nextCommand, &refreshPayloads[currentBankMachine->getBank().ID() % memSpec->banksPerRank], timeToSchedule); +} + +sc_time RefreshManagerGroupwise::start() +{ + timeToSchedule = sc_max_time(); + nextCommand = Command::NOP; + + if (sc_time_stamp() >= timeForNextTrigger) + { + powerDownManager->triggerInterruption(); + if (sleeping) + return timeToSchedule; + + if (sc_time_stamp() >= timeForNextTrigger + memSpec->getRefreshIntervalPB()) + { + timeForNextTrigger += memSpec->getRefreshIntervalPB(); + state = RmState::Regular; + } + + if (state == RmState::Regular) + { + bool forcedRefresh = (flexibilityCounter == maxPostponed); + bool allBanksBusy = true; + + if (!skipSelection) + { + currentIterator = remainingBankMachines.begin(); + currentBankMachine = *remainingBankMachines.begin(); + + for (auto it = remainingBankMachines.begin(); it != remainingBankMachines.end(); it++) + { + if ((*it)->isIdle()) + { + currentIterator = it; + currentBankMachine = *it; + allBanksBusy = false; + break; + } + } + } + + if (allBanksBusy && !forcedRefresh) + { + flexibilityCounter++; + timeForNextTrigger += memSpec->getRefreshIntervalPB(); + return timeForNextTrigger; + } + else + { + if (currentBankMachine->getState() == BmState::Activated) + nextCommand = Command::PRE; + else + { + nextCommand = Command::REFB; + + if (forcedRefresh) + { + currentBankMachine->block(); + skipSelection = true; + } + } + + timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, + currentBankMachine->getBankGroup(), currentBankMachine->getBank()); + return timeToSchedule; + } + } + else // if (state == RmState::Pulledin) + { + bool allBanksBusy = true; + + for (auto it = remainingBankMachines.begin(); it != remainingBankMachines.end(); it++) + { + if ((*it)->isIdle()) + { + currentIterator = it; + currentBankMachine = *it; + allBanksBusy = false; + break; + } + } + + if (allBanksBusy) + { + state = RmState::Regular; + timeForNextTrigger += memSpec->getRefreshIntervalPB(); + return timeForNextTrigger; + } + else + { + if (currentBankMachine->getState() == BmState::Activated) + nextCommand = Command::PRE; + else + nextCommand = Command::REFB; + timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank, + currentBankMachine->getBankGroup(), currentBankMachine->getBank()); + return timeToSchedule; + } + } + } + else + return timeForNextTrigger; +} + +void RefreshManagerGroupwise::updateState(Command command) +{ + switch (command) + { + case Command::REFB: + skipSelection = false; + remainingBankMachines.erase(currentIterator); + if (remainingBankMachines.empty()) + remainingBankMachines = allBankMachines; + + if (state == RmState::Pulledin) + flexibilityCounter--; + else + state = RmState::Pulledin; + + if (flexibilityCounter == maxPulledin) + { + state = RmState::Regular; + timeForNextTrigger += memSpec->getRefreshIntervalPB(); + } + break; + case Command::REFA: + // Refresh command after SREFEX + state = RmState::Regular; // TODO: check if this assignment is necessary + timeForNextTrigger = sc_time_stamp() + memSpec->getRefreshIntervalPB(); + sleeping = false; + break; + case Command::PDEA: case Command::PDEP: + sleeping = true; + break; + case Command::SREFEN: + sleeping = true; + timeForNextTrigger = sc_max_time(); + break; + case Command::PDXA: case Command::PDXP: + sleeping = false; + break; + } +} diff --git a/DRAMSys/library/src/controller/refresh/RefreshManagerGroupwise.h b/DRAMSys/library/src/controller/refresh/RefreshManagerGroupwise.h new file mode 100644 index 00000000..ba7e4dd8 --- /dev/null +++ b/DRAMSys/library/src/controller/refresh/RefreshManagerGroupwise.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2020, Technische Universität 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 REFRESHMANAGERGROUPWISE_H +#define REFRESHMANAGERGROUPWISE_H + +#include "RefreshManagerIF.h" +#include "../../configuration/memspec/MemSpec.h" +#include "../BankMachine.h" +#include "../powerdown/PowerDownManagerIF.h" +#include +#include +#include + +class RefreshManagerGroupwise final : public RefreshManagerIF +{ +public: + RefreshManagerGroupwise(std::vector &, PowerDownManagerIF *, Rank, CheckerIF *); + + virtual std::tuple getNextCommand() override; + virtual sc_time start() override; + virtual void updateState(Command) override; + +private: + enum class RmState {Regular, Pulledin} state = RmState::Regular; + const MemSpec *memSpec; + std::vector &bankMachinesOnRank; + PowerDownManagerIF *powerDownManager; + std::vector refreshPayloads; + sc_time timeForNextTrigger = sc_max_time(); + sc_time timeToSchedule = sc_max_time(); + Rank rank; + CheckerIF *checker; + Command nextCommand = Command::NOP; + + std::list remainingBankMachines; + std::list allBankMachines; + std::list::iterator currentIterator; + BankMachine *currentBankMachine; + + int flexibilityCounter = 0; + int maxPostponed = 0; + int maxPulledin = 0; + + bool sleeping = false; + bool skipSelection = false; +}; + +#endif // REFRESHMANAGERGROUPWISE_H diff --git a/DRAMSys/library/src/controller/refresh/RefreshManagerRankwise.cpp b/DRAMSys/library/src/controller/refresh/RefreshManagerRankwise.cpp index 40df47e3..af163a2f 100644 --- a/DRAMSys/library/src/controller/refresh/RefreshManagerRankwise.cpp +++ b/DRAMSys/library/src/controller/refresh/RefreshManagerRankwise.cpp @@ -39,9 +39,9 @@ using namespace tlm; -RefreshManagerRankwise::RefreshManagerRankwise(std::vector &bankMachines, +RefreshManagerRankwise::RefreshManagerRankwise(std::vector &bankMachinesOnRank, PowerDownManagerIF *powerDownManager, Rank rank, CheckerIF *checker) - : bankMachinesOnRank(bankMachines), powerDownManager(powerDownManager), rank(rank), checker(checker) + : bankMachinesOnRank(bankMachinesOnRank), powerDownManager(powerDownManager), rank(rank), checker(checker) { Configuration &config = Configuration::getInstance(); memSpec = config.memSpec;