From c15434c4fa1e6784701d2775107099df428ff91d Mon Sep 17 00:00:00 2001 From: Lukas Steiner Date: Wed, 19 Aug 2020 09:46:24 +0200 Subject: [PATCH] Add initial version of DDR5 based on DDR4. --- DRAMSys/library/CMakeLists.txt | 3 + .../am_ddr5_2x4x8Gbx8_dimm_p1KB_rbc.json | 49 ++ .../memspecs/JEDEC_2x8Gb_DDR5-3200A_8bit.json | 54 ++ .../resources/configs/simulator/ddr5.json | 19 + .../resources/simulations/ddr5-example.json | 16 + .../src/configuration/Configuration.cpp | 3 + .../src/configuration/memspec/MemSpecDDR5.cpp | 32 +- .../src/configuration/memspec/MemSpecDDR5.h | 52 +- DRAMSys/library/src/controller/Controller.cpp | 3 + .../src/controller/checker/CheckerDDR5.cpp | 462 ++++++++++++++++++ .../src/controller/checker/CheckerDDR5.h | 77 +++ DRAMSys/library/src/simulation/DRAMSys.cpp | 3 + .../src/simulation/DRAMSysRecordable.cpp | 7 +- .../library/src/simulation/dram/DramDDR5.cpp | 52 ++ .../library/src/simulation/dram/DramDDR5.h | 50 ++ .../src/simulation/dram/DramRecordable.cpp | 2 + 16 files changed, 845 insertions(+), 39 deletions(-) create mode 100644 DRAMSys/library/resources/configs/amconfigs/am_ddr5_2x4x8Gbx8_dimm_p1KB_rbc.json create mode 100644 DRAMSys/library/resources/configs/memspecs/JEDEC_2x8Gb_DDR5-3200A_8bit.json create mode 100644 DRAMSys/library/resources/configs/simulator/ddr5.json create mode 100644 DRAMSys/library/resources/simulations/ddr5-example.json create mode 100644 DRAMSys/library/src/controller/checker/CheckerDDR5.cpp create mode 100644 DRAMSys/library/src/controller/checker/CheckerDDR5.h create mode 100644 DRAMSys/library/src/simulation/dram/DramDDR5.cpp create mode 100644 DRAMSys/library/src/simulation/dram/DramDDR5.h diff --git a/DRAMSys/library/CMakeLists.txt b/DRAMSys/library/CMakeLists.txt index 67bf3d92..7871f809 100644 --- a/DRAMSys/library/CMakeLists.txt +++ b/DRAMSys/library/CMakeLists.txt @@ -99,6 +99,7 @@ add_library(DRAMSysLibrary src/configuration/memspec/MemSpec.cpp src/configuration/memspec/MemSpecDDR3.cpp src/configuration/memspec/MemSpecDDR4.cpp + src/configuration/memspec/MemSpecDDR5.cpp src/configuration/memspec/MemSpecLPDDR4.cpp src/configuration/memspec/MemSpecWideIO.cpp src/configuration/memspec/MemSpecWideIO2.cpp @@ -115,6 +116,7 @@ add_library(DRAMSysLibrary src/controller/checker/CheckerIF.h src/controller/checker/CheckerDDR3.cpp src/controller/checker/CheckerDDR4.cpp + src/controller/checker/CheckerDDR5.cpp src/controller/checker/CheckerLPDDR4.cpp src/controller/checker/CheckerWideIO.cpp src/controller/checker/CheckerWideIO2.cpp @@ -161,6 +163,7 @@ add_library(DRAMSysLibrary src/simulation/dram/Dram.cpp src/simulation/dram/DramDDR3.cpp src/simulation/dram/DramDDR4.cpp + src/simulation/dram/DramDDR5.cpp src/simulation/dram/DramLPDDR4.cpp src/simulation/dram/DramWideIO.cpp src/simulation/dram/DramWideIO2.cpp diff --git a/DRAMSys/library/resources/configs/amconfigs/am_ddr5_2x4x8Gbx8_dimm_p1KB_rbc.json b/DRAMSys/library/resources/configs/amconfigs/am_ddr5_2x4x8Gbx8_dimm_p1KB_rbc.json new file mode 100644 index 00000000..7e02f877 --- /dev/null +++ b/DRAMSys/library/resources/configs/amconfigs/am_ddr5_2x4x8Gbx8_dimm_p1KB_rbc.json @@ -0,0 +1,49 @@ +{ + "CONGEN": { + "BYTE_BIT": [ + 0, + 1 + ], + "COLUMN_BIT": [ + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11 + ], + "BANKGROUP_BIT": [ + 12, + 13, + 14 + ], + "BANK_BIT": [ + 15 + ], + "ROW_BIT": [ + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31 + ], + "CHANNEL_BIT": [ + 32 + ] + } +} \ No newline at end of file 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 new file mode 100644 index 00000000..0b580d0d --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/JEDEC_2x8Gb_DDR5-3200A_8bit.json @@ -0,0 +1,54 @@ +{ + "memspec": { + "memarchitecturespec": { + "burstLength": 16, + "dataRate": 2, + "nbrOfBankGroups": 8, + "nbrOfBanks": 16, + "nbrOfColumns": 1024, + "nbrOfRanks": 1, + "nbrOfRows": 65536, + "width": 8, + "nbrOfDevicesOnDIMM": 4, + "nbrOfChannels": 2 + }, + "memoryId": "JEDEC_2x8Gb_DDR5-3200A_8bit", + "memoryType": "DDR5", + + "memtimingspec": { + "AL": 0, + "CCD_L": 16, + "CCD_S": 8, + "CKE": 6, + "CKESR": 7, + "DQSCK": 2, + "FAW": 32, + "RAS": 52, + "RC": 74, + "RCD": 22, + "REFM": 1, + "REFI": 6240, + "RFC": 312, + "RL": 22, + "RPRE": 1, + "RP": 22, + "RRD_L": 8, + "RRD_S": 8, + "RTP": 12, + "WL": 20, + "WPRE": 2, + "WR": 48, + "WTR_L": 16, + "WTR_S": 4, + "XP": 12, + "XPDLL": 0, + "XS": 312, + "XSDLL": 1024, + "ACTPDEN": 2, + "PRPDEN": 2, + "REFPDEN": 2, + "RTRS": 1, + "clkMhz": 1600 + } + } +} diff --git a/DRAMSys/library/resources/configs/simulator/ddr5.json b/DRAMSys/library/resources/configs/simulator/ddr5.json new file mode 100644 index 00000000..d3987d37 --- /dev/null +++ b/DRAMSys/library/resources/configs/simulator/ddr5.json @@ -0,0 +1,19 @@ +{ + "simconfig": { + "AddressOffset": 0, + "CheckTLM2Protocol": false, + "DatabaseRecording": true, + "Debug": false, + "ECCControllerMode": "Disabled", + "EnableWindowing": false, + "ErrorCSVFile": "", + "ErrorChipSeed": 42, + "PowerAnalysis": false, + "SimulationName": "ddr5", + "SimulationProgressBar": true, + "StoreMode": "NoStorage", + "ThermalSimulation": false, + "UseMalloc": false, + "WindowSize": 1000 + } +} diff --git a/DRAMSys/library/resources/simulations/ddr5-example.json b/DRAMSys/library/resources/simulations/ddr5-example.json new file mode 100644 index 00000000..b0052ec5 --- /dev/null +++ b/DRAMSys/library/resources/simulations/ddr5-example.json @@ -0,0 +1,16 @@ +{ + "simulation": { + "addressmapping": "am_ddr5_2x4x8Gbx8_dimm_p1KB_rbc.json", + "mcconfig": "fr_fcfs.json", + "memspec": "JEDEC_2x8Gb_DDR5-3200A_8bit.json", + "simconfig": "ddr5.json", + "simulationid": "ddr5-example", + "thermalconfig": "config.json", + "tracesetup": [ + { + "clkMhz": 200, + "name": "ddr3_example.stl" + } + ] + } +} diff --git a/DRAMSys/library/src/configuration/Configuration.cpp b/DRAMSys/library/src/configuration/Configuration.cpp index 4a0b9645..5d1e1aa0 100644 --- a/DRAMSys/library/src/configuration/Configuration.cpp +++ b/DRAMSys/library/src/configuration/Configuration.cpp @@ -43,6 +43,7 @@ #include "Configuration.h" #include "memspec/MemSpecDDR3.h" #include "memspec/MemSpecDDR4.h" +#include "memspec/MemSpecDDR5.h" #include "memspec/MemSpecWideIO.h" #include "memspec/MemSpecLPDDR4.h" #include "memspec/MemSpecWideIO2.h" @@ -291,6 +292,8 @@ void Configuration::loadMemSpec(Configuration &config, std::string memspecUri) memSpec = new MemSpecDDR3(jMemSpec); else if (memoryType == "DDR4") memSpec = new MemSpecDDR4(jMemSpec); + else if (memoryType == "DDR5") + memSpec = new MemSpecDDR5(jMemSpec); else if (memoryType == "LPDDR4") memSpec = new MemSpecLPDDR4(jMemSpec); else if (memoryType == "WIDEIO_SDR") diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.cpp index dca14f33..baf91d70 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.cpp @@ -55,19 +55,17 @@ MemSpecDDR5::MemSpecDDR5(json &memspec) tCKE (tCK * parseUint(memspec["memtimingspec"]["CKE"], "CKE")), tPD (tCKE), tCKESR (tCK * parseUint(memspec["memtimingspec"]["CKESR"], "CKESR")), - tDQSCK (tCK * parseUint(memspec["memtimingspec"]["DQSCK"], "DQSCK")), tRAS (tCK * parseUint(memspec["memtimingspec"]["RAS"], "RAS")), tRC (tCK * parseUint(memspec["memtimingspec"]["RC"], "RC")), tRCD (tCK * parseUint(memspec["memtimingspec"]["RCD"], "RCD")), tRL (tCK * parseUint(memspec["memtimingspec"]["RL"], "RL")), + tRPRE (tCK * parseUint(memspec["memtimingspec"]["RPRE"], "RPRE")), tRTP (tCK * parseUint(memspec["memtimingspec"]["RTP"], "RTP")), tWL (tCK * parseUint(memspec["memtimingspec"]["WL"], "WL")), + tWPRE (tCK * parseUint(memspec["memtimingspec"]["WPRE"], "WPRE")), tWR (tCK * parseUint(memspec["memtimingspec"]["WR"], "WR")), tXP (tCK * parseUint(memspec["memtimingspec"]["XP"], "XP")), tXS (tCK * parseUint(memspec["memtimingspec"]["XS"], "XS")), - tCCD_S (tCK * parseUint(memspec["memtimingspec"]["CCD_S"], "CCD_S")), - tCCD_L (tCK * parseUint(memspec["memtimingspec"]["CCD_L"], "CCD_L")), - tFAW (tCK * parseUint(memspec["memtimingspec"]["FAW"], "FAW")), tREFI ((parseUint(memspec["memtimingspec"]["REFM"], "REFM") == 4) ? (tCK * (parseUint(memspec["memtimingspec"]["REFI"], "REFI") / 4)) : ((parseUint(memspec["memtimingspec"]["REFM"], "REFM") == 2) ? @@ -79,6 +77,10 @@ MemSpecDDR5::MemSpecDDR5(json &memspec) (tCK * parseUint(memspec["memtimingspec"]["RFC2"], "RFC2")) : (tCK * parseUint(memspec["memtimingspec"]["RFC"], "RFC")))), tRP (tCK * parseUint(memspec["memtimingspec"]["RP"], "RP")), + tDQSCK (tCK * parseUint(memspec["memtimingspec"]["DQSCK"], "DQSCK")), + tCCD_S (tCK * parseUint(memspec["memtimingspec"]["CCD_S"], "CCD_S")), + tCCD_L (tCK * parseUint(memspec["memtimingspec"]["CCD_L"], "CCD_L")), + tFAW (tCK * parseUint(memspec["memtimingspec"]["FAW"], "FAW")), tRRD_S (tCK * parseUint(memspec["memtimingspec"]["RRD_S"], "RRD_S")), tRRD_L (tCK * parseUint(memspec["memtimingspec"]["RRD_L"], "RRD_L")), tWTR_S (tCK * parseUint(memspec["memtimingspec"]["WTR_S"], "WTR_S")), @@ -90,7 +92,13 @@ MemSpecDDR5::MemSpecDDR5(json &memspec) tPRPDEN (tCK * parseUint(memspec["memtimingspec"]["PRPDEN"], "PRPDEN")), tREFPDEN (tCK * parseUint(memspec["memtimingspec"]["REFPDEN"], "REFPDEN")), tRTRS (tCK * parseUint(memspec["memtimingspec"]["RTRS"], "RTRS")) -{} +{ + commandLengthInCycles[Command::ACT] = 2; + commandLengthInCycles[Command::RD] = 2; + commandLengthInCycles[Command::RDA] = 2; + commandLengthInCycles[Command::WR] = 2; + commandLengthInCycles[Command::WRA] = 2; +} sc_time MemSpecDDR5::getRefreshIntervalAB() const { @@ -109,15 +117,15 @@ sc_time MemSpecDDR5::getExecutionTime(Command command, const tlm_generic_payload if (command == Command::PRE || command == Command::PREA) return tRP; else if (command == Command::ACT) - return tRCD; + return tRCD + tCK; else if (command == Command::RD) - return tRL + burstDuration; + return tRL + burstDuration + tCK; else if (command == Command::RDA) - return tRTP + tRP; + return tRTP + tRP + tCK; else if (command == Command::WR) - return tWL + burstDuration; + return tWL + burstDuration + tCK; else if (command == Command::WRA) - return tWL + burstDuration + tWR + tRP; + return tWL + burstDuration + tWR + tRP + tCK; else if (command == Command::REFA) return tRFC; else @@ -131,9 +139,9 @@ sc_time MemSpecDDR5::getExecutionTime(Command command, const tlm_generic_payload TimeInterval MemSpecDDR5::getIntervalOnDataStrobe(Command command) const { if (command == Command::RD || command == Command::RDA) - return TimeInterval(sc_time_stamp() + tRL, sc_time_stamp() + tRL + burstDuration); + return TimeInterval(sc_time_stamp() + tRL + tCK, sc_time_stamp() + tRL + burstDuration + tCK); else if (command == Command::WR || command == Command::WRA) - return TimeInterval(sc_time_stamp() + tWL, sc_time_stamp() + tWL + burstDuration); + return TimeInterval(sc_time_stamp() + tWL + tCK, sc_time_stamp() + tWL + burstDuration + tCK); else { SC_REPORT_FATAL("MemSpec", "Method was called with invalid argument"); diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.h b/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.h index cc9dcda8..e1f02a62 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecDDR5.h @@ -45,36 +45,38 @@ public: MemSpecDDR5(nlohmann::json &memspec); // Memspec Variables: - const sc_time tRCD; - const sc_time tPPD; - const sc_time tRP; + const sc_time tCKE; + const sc_time tPD; + const sc_time tCKESR; const sc_time tRAS; + const sc_time tRC; + const sc_time tRCD; const sc_time tRL; - const sc_time tRTP; const sc_time tRPRE; - const sc_time tRPST; - const sc_time tRDQSOFF; + const sc_time tRTP; const sc_time tWL; - const sc_time tWR; - const sc_time tWTR_L; - const sc_time tWTR_S; const sc_time tWPRE; - const sc_time tWPST; - const sc_time tCCD_L_slr; - const sc_time tCCD_S_slr; - const sc_time tCCD_dlr; - const sc_time tCCD_L_WR_slr; - const sc_time tCCD_S_WR_slr; - const sc_time tCCD_WR_dlr; - const sc_time tCCD_WR_dpr; - const sc_time - const sc_time - const sc_time - const sc_time - const sc_time - const sc_time - const sc_time - const sc_time + const sc_time tWR; + const sc_time tXP; + const sc_time tXS; + const sc_time tREFI; + const sc_time tRFC; + const sc_time tRP; + const sc_time tDQSCK; + const sc_time tCCD_S; + const sc_time tCCD_L; + const sc_time tFAW; + const sc_time tRRD_S; + const sc_time tRRD_L; + const sc_time tWTR_S; + const sc_time tWTR_L; + const sc_time tAL; + const sc_time tXPDLL; + const sc_time tXSDLL; + const sc_time tACTPDEN; + const sc_time tPRPDEN; + const sc_time tREFPDEN; + const sc_time tRTRS; // Currents and Voltages: // TODO: to be completed diff --git a/DRAMSys/library/src/controller/Controller.cpp b/DRAMSys/library/src/controller/Controller.cpp index 169e90ae..5a81d6f1 100644 --- a/DRAMSys/library/src/controller/Controller.cpp +++ b/DRAMSys/library/src/controller/Controller.cpp @@ -39,6 +39,7 @@ #include "Command.h" #include "checker/CheckerDDR3.h" #include "checker/CheckerDDR4.h" +#include "checker/CheckerDDR5.h" #include "checker/CheckerWideIO.h" #include "checker/CheckerLPDDR4.h" #include "checker/CheckerWideIO2.h" @@ -76,6 +77,8 @@ Controller::Controller(sc_module_name name) : checker = new CheckerDDR3(); else if (memSpec->memoryType == "DDR4") checker = new CheckerDDR4(); + else if (memSpec->memoryType == "DDR5") + checker = new CheckerDDR5(); else if (memSpec->memoryType == "WIDEIO_SDR") checker = new CheckerWideIO(); else if (memSpec->memoryType == "LPDDR4") diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR5.cpp b/DRAMSys/library/src/controller/checker/CheckerDDR5.cpp new file mode 100644 index 00000000..ee9e44b6 --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerDDR5.cpp @@ -0,0 +1,462 @@ +/* + * 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 "CheckerDDR5.h" + +CheckerDDR5::CheckerDDR5() +{ + Configuration &config = Configuration::getInstance(); + memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("CheckerDDR5", "Wrong MemSpec chosen"); + + 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()); + + last4Activates = std::vector>(memSpec->numberOfRanks); + + tBURST = memSpec->burstLength / memSpec->dataRate * memSpec->tCK; + tRDWR = memSpec->tRL + tBURST + memSpec->tCK - memSpec->tWL + memSpec->tWPRE; + tRDWR_R = memSpec->tRL + tBURST + memSpec->tRTRS - memSpec->tWL + memSpec->tWPRE; + tWRRD_S = memSpec->tWL + tBURST + memSpec->tWTR_S; + tWRRD_L = memSpec->tWL + tBURST + memSpec->tWTR_L; + tWRRD_R = memSpec->tWL + tBURST + memSpec->tRTRS - memSpec->tRL + memSpec->tRPRE; + tWRPRE = memSpec->tWL + tBURST + memSpec->tWR; + tRDPDEN = memSpec->tRL + tBURST + memSpec->tCK; + tWRPDEN = memSpec->tWL + tBURST + memSpec->tWR; + tWRAPDEN = memSpec->tWL + tBURST + memSpec->tCK + memSpec->tWR; +} + +sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGroup bankgroup, Bank bank) const +{ + sc_time lastCommandStart; + sc_time earliestTimeToStart = sc_time_stamp(); + + if (command == Command::RD || command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD - memSpec->tAL); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_S); + + lastCommandStart = lastScheduledByCommand[Command::RD] != lastScheduledByCommandAndRank[Command::RD][rank.ID()] ? lastScheduledByCommand[Command::RD] : SC_ZERO_TIME; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST + memSpec->tRTRS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_S); + + lastCommandStart = lastScheduledByCommand[Command::RDA] != lastScheduledByCommandAndRank[Command::RDA][rank.ID()] ? lastScheduledByCommand[Command::RDA] : SC_ZERO_TIME; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST + memSpec->tRTRS); + + if (command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE - memSpec->tRTP); + } + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_L); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_S); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_R); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_L); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_S); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_R); + + 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) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD - memSpec->tAL); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR); + + lastCommandStart = lastScheduledByCommand[Command::RD] != lastScheduledByCommandAndRank[Command::RD][rank.ID()] ? lastScheduledByCommand[Command::RD] : SC_ZERO_TIME; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR_R); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR); + + lastCommandStart = lastScheduledByCommand[Command::RDA] != lastScheduledByCommandAndRank[Command::RDA][rank.ID()] ? lastScheduledByCommand[Command::RDA] : SC_ZERO_TIME; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR_R); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_S); + + lastCommandStart = lastScheduledByCommand[Command::WR] != lastScheduledByCommandAndRank[Command::WR][rank.ID()] ? lastScheduledByCommand[Command::WR] : SC_ZERO_TIME; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST + memSpec->tRTRS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_S); + + lastCommandStart = lastScheduledByCommand[Command::WRA] != lastScheduledByCommandAndRank[Command::WRA][rank.ID()] ? lastScheduledByCommand[Command::WRA] : SC_ZERO_TIME; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST + memSpec->tRTRS); + + 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::ACT) + { + 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 = lastScheduledByCommandAndBank[Command::RDA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tAL + memSpec->tRTP + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = 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::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); + + if (last4Activates[rank.ID()].size() >= 4) + earliestTimeToStart = std::max(earliestTimeToStart, last4Activates[rank.ID()].front() + memSpec->tFAW); + } + else if (command == Command::PRE) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RD][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tAL + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + } + else if (command == Command::PREA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tAL + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tAL + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + } + else if (command == Command::REFA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tAL + memSpec->tRTP + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + 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::PDEA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tACTPDEN); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDPDEN); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDPDEN); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPDEN); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRAPDEN); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPRPDEN); + + 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->tPD); + } + else if (command == Command::PDEP) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDPDEN); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDPDEN); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRAPDEN); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPRPDEN); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPRPDEN); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXP][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCKE); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tREFPDEN); + + 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->tPD); + } + else if (command == Command::SREFEN) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + std::max(tRDPDEN, memSpec->tAL + memSpec->tRTP + memSpec->tRP)); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + std::max(tWRAPDEN, tWRPRE + 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 + SC_REPORT_FATAL("CheckerDDR5", "Unknown command!"); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->tCK); + + return earliestTimeToStart; +} + +void CheckerDDR5::insert(Command command, Rank rank, BankGroup bankgroup, Bank bank) +{ + PRINTDEBUGMESSAGE("CheckerDDR5", "Changing state on bank " + std::to_string(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(); + lastCommandOnBus = sc_time_stamp(); + + if (command == Command::ACT) + { + if (last4Activates[rank.ID()].size() == 4) + last4Activates[rank.ID()].pop(); + last4Activates[rank.ID()].push(sc_time_stamp()); + } +} diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR5.h b/DRAMSys/library/src/controller/checker/CheckerDDR5.h new file mode 100644 index 00000000..c2338fa6 --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerDDR5.h @@ -0,0 +1,77 @@ +/* + * 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 CHECKERDDR5_H +#define CHECKERDDR5_H + +#include "CheckerIF.h" +#include +#include +#include "../../configuration/memspec/MemSpecDDR5.h" +#include "../../configuration/Configuration.h" + +class CheckerDDR5 final : public CheckerIF +{ +public: + CheckerDDR5(); + virtual sc_time timeToSatisfyConstraints(Command, Rank, BankGroup, Bank) const override; + virtual void insert(Command, Rank, BankGroup, Bank) override; + +private: + const MemSpecDDR5 *memSpec; + + std::vector> lastScheduledByCommandAndBank; + std::vector> lastScheduledByCommandAndBankGroup; + std::vector> lastScheduledByCommandAndRank; + std::vector lastScheduledByCommand; + sc_time lastCommandOnBus; + + // Four activate window + std::vector> last4Activates; + + sc_time tBURST; + sc_time tRDWR; + sc_time tRDWR_R; + sc_time tWRRD_S; + sc_time tWRRD_L; + sc_time tWRRD_R; + sc_time tRDAACT; + sc_time tWRPRE; + sc_time tWRAACT; + sc_time tRDPDEN; + sc_time tWRPDEN; + sc_time tWRAPDEN; +}; + +#endif // CHECKERDDR5_H diff --git a/DRAMSys/library/src/simulation/DRAMSys.cpp b/DRAMSys/library/src/simulation/DRAMSys.cpp index fca962a1..9140dd6f 100644 --- a/DRAMSys/library/src/simulation/DRAMSys.cpp +++ b/DRAMSys/library/src/simulation/DRAMSys.cpp @@ -51,6 +51,7 @@ #include "../error/ecchamming.h" #include "dram/DramDDR3.h" #include "dram/DramDDR4.h" +#include "dram/DramDDR5.h" #include "dram/DramWideIO.h" #include "dram/DramLPDDR4.h" #include "dram/DramWideIO2.h" @@ -216,6 +217,8 @@ void DRAMSys::instantiateModules(const std::string &pathToResources, dram = new DramWideIO(str.c_str()); else if (memoryType == "DDR4") dram = new DramDDR4(str.c_str()); + else if (memoryType == "DDR5") + dram = new DramDDR5(str.c_str()); else if (memoryType == "LPDDR4") dram = new DramLPDDR4(str.c_str()); else if (memoryType == "WIDEIO2") diff --git a/DRAMSys/library/src/simulation/DRAMSysRecordable.cpp b/DRAMSys/library/src/simulation/DRAMSysRecordable.cpp index 93b92a33..70631100 100644 --- a/DRAMSys/library/src/simulation/DRAMSysRecordable.cpp +++ b/DRAMSys/library/src/simulation/DRAMSysRecordable.cpp @@ -38,6 +38,7 @@ #include "dram/DramRecordable.h" #include "dram/DramDDR3.h" #include "dram/DramDDR4.h" +#include "dram/DramDDR5.h" #include "dram/DramWideIO.h" #include "dram/DramLPDDR4.h" #include "dram/DramWideIO2.h" @@ -152,12 +153,14 @@ void DRAMSysRecordable::instantiateModules(const std::string &traceName, if (memoryType == "DDR3") dram = new DramRecordable(str.c_str(), tlmRecorders[i]); - else if (memoryType == "WIDEIO_SDR") - dram = new DramRecordable(str.c_str(), tlmRecorders[i]); else if (memoryType == "DDR4") dram = new DramRecordable(str.c_str(), tlmRecorders[i]); + else if (memoryType == "DDR5") + dram = new DramRecordable(str.c_str(), tlmRecorders[i]); else if (memoryType == "LPDDR4") dram = new DramRecordable(str.c_str(), tlmRecorders[i]); + else if (memoryType == "WIDEIO_SDR") + dram = new DramRecordable(str.c_str(), tlmRecorders[i]); else if (memoryType == "WIDEIO2") dram = new DramRecordable(str.c_str(), tlmRecorders[i]); else if (memoryType == "HBM2") diff --git a/DRAMSys/library/src/simulation/dram/DramDDR5.cpp b/DRAMSys/library/src/simulation/dram/DramDDR5.cpp new file mode 100644 index 00000000..c794e9c0 --- /dev/null +++ b/DRAMSys/library/src/simulation/dram/DramDDR5.cpp @@ -0,0 +1,52 @@ +/* + * 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. + * + * Authors: + * Lukas Steiner + */ + +#include "DramDDR5.h" + +#include "Dram.h" +#include "../../configuration/Configuration.h" +#include "../../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h" +#include "../../configuration/memspec/MemSpecDDR5.h" + +using namespace DRAMPower; + +DramDDR5::DramDDR5(sc_module_name name) : Dram(name) +{ + if (storeMode == StorageMode::ErrorModel) + SC_REPORT_FATAL("DramDDR5", "Error Model not supported for DDR5"); + + if (Configuration::getInstance().powerAnalysis) + SC_REPORT_FATAL("DramDDR5", "DRAMPower does not support DDR5"); +} diff --git a/DRAMSys/library/src/simulation/dram/DramDDR5.h b/DRAMSys/library/src/simulation/dram/DramDDR5.h new file mode 100644 index 00000000..14898af1 --- /dev/null +++ b/DRAMSys/library/src/simulation/dram/DramDDR5.h @@ -0,0 +1,50 @@ +/* + * 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. + * + * Authors: + * Lukas Steiner + */ + +#ifndef DRAMDDR5_H +#define DRAMDDR5_H + +#include +#include "Dram.h" + +class DramDDR5 : public Dram +{ +public: + DramDDR5(sc_module_name); + SC_HAS_PROCESS(DramDDR5); + virtual ~DramDDR5() {} +}; + +#endif // DRAMDDR5_H diff --git a/DRAMSys/library/src/simulation/dram/DramRecordable.cpp b/DRAMSys/library/src/simulation/dram/DramRecordable.cpp index 3b9215ef..2532bf91 100644 --- a/DRAMSys/library/src/simulation/dram/DramRecordable.cpp +++ b/DRAMSys/library/src/simulation/dram/DramRecordable.cpp @@ -41,6 +41,7 @@ #include "../../common/utils.h" #include "DramDDR3.h" #include "DramDDR4.h" +#include "DramDDR5.h" #include "DramWideIO.h" #include "DramLPDDR4.h" #include "DramWideIO2.h" @@ -147,6 +148,7 @@ void DramRecordable::powerWindow() template class DramRecordable; template class DramRecordable; +template class DramRecordable; template class DramRecordable; template class DramRecordable; template class DramRecordable;