diff --git a/DRAMSys/library/library.pro b/DRAMSys/library/library.pro index 3bc74e25..5c0df5d3 100644 --- a/DRAMSys/library/library.pro +++ b/DRAMSys/library/library.pro @@ -135,7 +135,8 @@ SOURCES += \ src/controller/refresh/RefreshManagerDummy.cpp \ src/controller/refresh/RefreshManagerBankwise.cpp \ src/controller/checker/CheckerWideIO.cpp \ - src/configuration/memspec/MemSpecLPDDR4.cpp + src/configuration/memspec/MemSpecLPDDR4.cpp \ + src/controller/checker/CheckerDDR4.cpp HEADERS += \ src/common/third_party/tinyxml2/tinyxml2.h \ @@ -207,7 +208,8 @@ HEADERS += \ src/configuration/memspec/MemSpecDDR3.h \ src/configuration/memspec/MemSpecWideIO.h \ src/configuration/memspec/MemSpecDDR4.h \ - src/configuration/memspec/MemSpecLPDDR4.h + src/configuration/memspec/MemSpecLPDDR4.h \ + src/controller/checker/CheckerDDR4.h #src/common/third_party/json/include/nlohmann/json.hpp \ thermalsim = $$(THERMALSIM) diff --git a/DRAMSys/library/src/controller/Controller.cpp b/DRAMSys/library/src/controller/Controller.cpp index 335fa01b..cc50efd3 100644 --- a/DRAMSys/library/src/controller/Controller.cpp +++ b/DRAMSys/library/src/controller/Controller.cpp @@ -42,6 +42,7 @@ #include "../common/dramExtensions.h" #include "../common/protocol.h" #include "checker/CheckerDDR3.h" +#include "checker/CheckerDDR4.h" #include "checker/CheckerWideIO.h" #include "refresh/RefreshManager.h" #include "refresh/RefreshManagerDummy.h" @@ -59,6 +60,8 @@ Controller::Controller(sc_module_name name) : if (config.memSpec->MemoryType == "DDR3") checker = new CheckerDDR3(); + else if (config.memSpec->MemoryType == "DDR4") + checker = new CheckerDDR4(); else if (config.memSpec->MemoryType == "WIDEIO_SDR") checker = new CheckerWideIO(); else @@ -288,7 +291,7 @@ void Controller::sendToFrontend(tlm_generic_payload *payload, tlm_phase phase) void Controller::sendToDram(Command command, tlm_generic_payload *payload) { DramExtension extension = DramExtension::getExtension(payload); - checker->insert(command, extension.getRank(), extension.getBank()); + checker->insert(command, extension.getRank(), extension.getBankGroup(), extension.getBank()); sc_time delay = SC_ZERO_TIME; tlm_phase phase; diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR3.cpp b/DRAMSys/library/src/controller/checker/CheckerDDR3.cpp index 38da02a6..e1c85404 100644 --- a/DRAMSys/library/src/controller/checker/CheckerDDR3.cpp +++ b/DRAMSys/library/src/controller/checker/CheckerDDR3.cpp @@ -168,13 +168,12 @@ sc_time CheckerDDR3::delayToSatisfyConstraints(Command command, Rank rank, BankG reportFatal("CheckerDDR3", "Unknown command!"); } // Check if command bus is free - //if (lastScheduled.isValidCommand()) - earliestTimeToStart = std::max(earliestTimeToStart, lastScheduled + memSpec->clk); + earliestTimeToStart = std::max(earliestTimeToStart, lastScheduled + memSpec->clk); return (earliestTimeToStart - sc_time_stamp()); } -void CheckerDDR3::insert(Command command, Rank rank, Bank bank) +void CheckerDDR3::insert(Command command, Rank rank, BankGroup, Bank bank) { PRINTDEBUGMESSAGE("CheckerDDR3", "Changing state on bank " + bank.ID() + " command is " + commandToString(command)); diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR3.h b/DRAMSys/library/src/controller/checker/CheckerDDR3.h index 45043c94..169f5878 100644 --- a/DRAMSys/library/src/controller/checker/CheckerDDR3.h +++ b/DRAMSys/library/src/controller/checker/CheckerDDR3.h @@ -49,11 +49,16 @@ public: CheckerDDR3(); ~CheckerDDR3(); sc_time delayToSatisfyConstraints(Command, Rank, BankGroup, Bank) const; - void insert(Command, Rank, Bank); + void insert(Command, Rank, BankGroup, Bank); private: const MemSpecDDR3 *memSpec; + std::vector> lastScheduledByCommandAndBank; + std::vector> lastScheduledByCommandAndRank; + std::vector lastScheduledByCommand; + sc_time lastScheduled; + // Four activate window std::vector> lastActivates; diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR4.cpp b/DRAMSys/library/src/controller/checker/CheckerDDR4.cpp new file mode 100644 index 00000000..f35bd770 --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerDDR4.cpp @@ -0,0 +1,304 @@ +/* + * 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 "CheckerDDR4.h" + +CheckerDDR4::CheckerDDR4() +{ + Configuration config = Configuration::getInstance(); + memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("CheckerDDR4", "Wrong MemSpec chosen"); + + if (config.ControllerCoreRefDisable) + refreshChecker = new RefreshCheckerDDR4Dummy(memSpec); + else if (config.BankwiseLogic) + refreshChecker = new RefreshCheckerDDR4Bankwise(memSpec); + else + refreshChecker = new RefreshCheckerDDR4(memSpec); + + lastScheduledByCommandAndBank = std::vector> + (numberOfCommands(), std::vector(memSpec->NumberOfBanks)); + lastScheduledByCommandAndBankGroup = std::vector> + (numberOfCommands(), std::vector(memSpec->NumberOfBankGroups)); + lastScheduledByCommandAndRank = std::vector> + (numberOfCommands(), std::vector(memSpec->NumberOfRanks)); + lastScheduledByCommand = std::vector(numberOfCommands()); + + lastActivates = std::vector>(memSpec->NumberOfRanks); + + burstClocks = (memSpec->BurstLength / 2) * memSpec->clk; +} + +CheckerDDR4::~CheckerDDR4() +{ + delete refreshChecker; +} + +sc_time CheckerDDR4::delayToSatisfyConstraints(Command command, Rank rank, BankGroup bankgroup, Bank bank) const +{ + sc_time lastCommandStart; + sc_time earliestTimeToStart = sc_time_stamp(); + + if (command == Command::ACT) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + + burstClocks + memSpec->tWR + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.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); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::ACT][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRD_L); + + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRD_S); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.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) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_S); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_S); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + + burstClocks + memSpec->tWTR_L); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + + burstClocks + memSpec->tWTR_S); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + + burstClocks + memSpec->tWTR_L); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + + burstClocks + memSpec->tWTR_S); + + refreshChecker->delayToSatisfyRD(bank, earliestTimeToStart); + } + else if (command == Command::WR || command == Command::WRA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRL + + burstClocks + 2 * memSpec->clk - memSpec->tWL); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRL + + burstClocks + 2 * memSpec->clk - memSpec->tWL); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_S); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_S); + + refreshChecker->delayToSatisfyWR(bank, earliestTimeToStart); + } + else if (command == Command::PRE) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RD][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + + burstClocks + memSpec->tWR); + + refreshChecker->delayToSatisfyPRE(bank, earliestTimeToStart); + } + else + { + reportFatal("CheckerDDR4", "Unknown command!"); + } + // Check if command bus is free + earliestTimeToStart = std::max(earliestTimeToStart, lastScheduled + memSpec->clk); + + return (earliestTimeToStart - sc_time_stamp()); +} + +void CheckerDDR4::insert(Command command, Rank rank, BankGroup bankgroup, Bank bank) +{ + PRINTDEBUGMESSAGE("CheckerDDR4", "Changing state on bank " + bank.ID() + + " command is " + commandToString(command)); + + lastScheduledByCommandAndBank[command][bank.ID()] = sc_time_stamp(); + lastScheduledByCommandAndBankGroup[command][bankgroup.ID()] = sc_time_stamp(); + lastScheduledByCommandAndRank[command][rank.ID()] = sc_time_stamp(); + lastScheduledByCommand[command] = sc_time_stamp(); + lastScheduled = sc_time_stamp(); + + if (command == Command::ACT) + { + if (lastActivates[rank.ID()].size() == 4) + 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 RefreshCheckerDDR4::delayToSatisfyACT(Bank, sc_time &earliestTimeToStart) +{ + if (earliestTimeToStart >= (timeForNextPREA - memSpec->tRAS)) + earliestTimeToStart = timeForNextREFA + memSpec->tRFC; +} + +void RefreshCheckerDDR4::delayToSatisfyRD(Bank, sc_time &earliestTimeToStart) +{ + if (earliestTimeToStart >= (timeForNextPREA - memSpec->tRTP)) + earliestTimeToStart = timeForNextREFA + memSpec->tRFC; +} + +void RefreshCheckerDDR4::delayToSatisfyWR(Bank, sc_time &earliestTimeToStart) +{ + if (earliestTimeToStart >= (timeForNextPREA - memSpec->tWL - burstClocks - memSpec->tWR)) + earliestTimeToStart = timeForNextREFA + memSpec->tRFC; +} + +void RefreshCheckerDDR4::delayToSatisfyPRE(Bank, sc_time &earliestTimeToStart) +{ + if (earliestTimeToStart >= timeForNextPREA) + earliestTimeToStart = timeForNextREFA + memSpec->tRFC; +} + +void RefreshCheckerDDR4::insert(Bank) +{ + timeForNextREFA += memSpec->tREFI; + timeForNextPREA += memSpec->tREFI; +} + +RefreshCheckerDDR4Bankwise::RefreshCheckerDDR4Bankwise(const MemSpecDDR4 *memSpec) + : RefreshCheckerDDR4Dummy(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 RefreshCheckerDDR4Bankwise::delayToSatisfyACT(Bank bank, sc_time &earliestTimeToStart) +{ + if (earliestTimeToStart >= (timesForNextPRE[bank.ID()] - memSpec->tRAS)) + earliestTimeToStart = timesForNextREFB[bank.ID()] + memSpec->tRFC; +} + +void RefreshCheckerDDR4Bankwise::delayToSatisfyRD(Bank bank, sc_time &earliestTimeToStart) +{ + if (earliestTimeToStart >= (timesForNextPRE[bank.ID()] - memSpec->tRTP)) + earliestTimeToStart = timesForNextREFB[bank.ID()] + memSpec->tRFC; +} + +void RefreshCheckerDDR4Bankwise::delayToSatisfyWR(Bank bank, sc_time &earliestTimeToStart) +{ + if (earliestTimeToStart >= (timesForNextPRE[bank.ID()] - memSpec->tWL - burstClocks - memSpec->tWR)) + earliestTimeToStart = timesForNextREFB[bank.ID()] + memSpec->tRFC; +} + +void RefreshCheckerDDR4Bankwise::insert(Bank bank) +{ + timesForNextREFB[bank.ID()] += memSpec->tREFI; + timesForNextPRE[bank.ID()] += memSpec->tREFI; +} diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR4.h b/DRAMSys/library/src/controller/checker/CheckerDDR4.h new file mode 100644 index 00000000..581c4821 --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerDDR4.h @@ -0,0 +1,127 @@ +/* + * 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 CHECKERDDR4_H +#define CHECKERDDR4_H + +#include "CheckerIF.h" +#include +#include +#include "../../configuration/memspec/MemSpecDDR4.h" +#include "../../configuration/Configuration.h" + +class RefreshCheckerDDR4Dummy; + +class CheckerDDR4 final : public CheckerIF +{ +public: + CheckerDDR4(); + ~CheckerDDR4(); + sc_time delayToSatisfyConstraints(Command, Rank, BankGroup, Bank) const; + void insert(Command, Rank, BankGroup, Bank); + +private: + const MemSpecDDR4 *memSpec; + + std::vector> lastScheduledByCommandAndBank; + std::vector> lastScheduledByCommandAndBankGroup; + std::vector> lastScheduledByCommandAndRank; + std::vector lastScheduledByCommand; + sc_time lastScheduled; + + // Four activate window + std::vector> lastActivates; + + RefreshCheckerDDR4Dummy *refreshChecker; + + sc_time burstClocks; + + // PowerDown TODO: Implement this method? + //sc_time getTimeConstraintToEnterPowerDown(Command lastCmd, Command pdnCmd) const; +}; + +class RefreshCheckerDDR4Dummy +{ +protected: + friend class CheckerDDR4; + RefreshCheckerDDR4Dummy(const MemSpecDDR4 *memSpec) : memSpec(memSpec) + { + burstClocks = (memSpec->BurstLength / 2) * memSpec->clk; + } + virtual ~RefreshCheckerDDR4Dummy() {} + + 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 MemSpecDDR4 *memSpec; + + sc_time burstClocks; +}; + +class RefreshCheckerDDR4 final : public RefreshCheckerDDR4Dummy +{ +private: + friend class CheckerDDR4; + RefreshCheckerDDR4(const MemSpecDDR4 *memSpec) + : RefreshCheckerDDR4Dummy(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 RefreshCheckerDDR4Bankwise final : public RefreshCheckerDDR4Dummy +{ +private: + friend class CheckerDDR4; + RefreshCheckerDDR4Bankwise(const MemSpecDDR4 *); + + 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 // CHECKERDDR4_H diff --git a/DRAMSys/library/src/controller/checker/CheckerIF.h b/DRAMSys/library/src/controller/checker/CheckerIF.h index f01350fa..2fe47f2a 100644 --- a/DRAMSys/library/src/controller/checker/CheckerIF.h +++ b/DRAMSys/library/src/controller/checker/CheckerIF.h @@ -47,13 +47,7 @@ public: virtual ~CheckerIF() {} virtual sc_time delayToSatisfyConstraints(Command, Rank, BankGroup, Bank) const = 0; - virtual void insert(Command, Rank, Bank) = 0; - -protected: - std::vector> lastScheduledByCommandAndBank; - std::vector> lastScheduledByCommandAndRank; - std::vector lastScheduledByCommand; - sc_time lastScheduled; + virtual void insert(Command, Rank, BankGroup, Bank) = 0; // PowerDown TODO: Implement this method? //sc_time getTimeConstraintToEnterPowerDown(Command lastCmd, Command pdnCmd) const; diff --git a/DRAMSys/library/src/controller/checker/CheckerWideIO.cpp b/DRAMSys/library/src/controller/checker/CheckerWideIO.cpp index 60901022..895bbcb2 100644 --- a/DRAMSys/library/src/controller/checker/CheckerWideIO.cpp +++ b/DRAMSys/library/src/controller/checker/CheckerWideIO.cpp @@ -152,13 +152,12 @@ sc_time CheckerWideIO::delayToSatisfyConstraints(Command command, Rank rank, Ban reportFatal("CheckerWideIO", "Unknown command!"); } // Check if command bus is free - //if (lastScheduled.isValidCommand()) - earliestTimeToStart = std::max(earliestTimeToStart, lastScheduled + memSpec->clk); + earliestTimeToStart = std::max(earliestTimeToStart, lastScheduled + memSpec->clk); return (earliestTimeToStart - sc_time_stamp()); } -void CheckerWideIO::insert(Command command, Rank rank, Bank bank) +void CheckerWideIO::insert(Command command, Rank rank, BankGroup, Bank bank) { PRINTDEBUGMESSAGE("CheckerWideIO", "Changing state on bank " + bank.ID() + " command is " + commandToString(command)); diff --git a/DRAMSys/library/src/controller/checker/CheckerWideIO.h b/DRAMSys/library/src/controller/checker/CheckerWideIO.h index db22f8f7..58fb4560 100644 --- a/DRAMSys/library/src/controller/checker/CheckerWideIO.h +++ b/DRAMSys/library/src/controller/checker/CheckerWideIO.h @@ -49,11 +49,16 @@ public: CheckerWideIO(); ~CheckerWideIO(); sc_time delayToSatisfyConstraints(Command, Rank, BankGroup, Bank) const; - void insert(Command, Rank, Bank); + void insert(Command, Rank, BankGroup, Bank); private: const MemSpecWideIO *memSpec; + std::vector> lastScheduledByCommandAndBank; + std::vector> lastScheduledByCommandAndRank; + std::vector lastScheduledByCommand; + sc_time lastScheduled; + // Four activate window std::vector> lastActivates;