From 5f7cb7a32667986d813f18d1c40bb51a703a14ac Mon Sep 17 00:00:00 2001 From: "Lukas Steiner (2)" Date: Thu, 17 Oct 2019 15:00:28 +0200 Subject: [PATCH] Included memspec, dram and checker for GDDR5, GDDR5X and GDDR6. --- DRAMSys/library/library.pro | 22 +- .../src/configuration/ConfigurationLoader.cpp | 216 +++++++++- .../src/configuration/ConfigurationLoader.h | 3 + .../configuration/memspec/MemSpecGDDR5.cpp | 88 ++++ .../src/configuration/memspec/MemSpecGDDR5.h | 90 ++++ .../configuration/memspec/MemSpecGDDR5X.cpp | 88 ++++ .../src/configuration/memspec/MemSpecGDDR5X.h | 90 ++++ .../configuration/memspec/MemSpecGDDR6.cpp | 88 ++++ .../src/configuration/memspec/MemSpecGDDR6.h | 93 +++++ .../src/configuration/memspec/MemSpecHBM2.h | 12 +- DRAMSys/library/src/controller/Controller.cpp | 9 + .../src/controller/checker/CheckerDDR3.h | 3 - .../src/controller/checker/CheckerDDR4.h | 3 - .../src/controller/checker/CheckerGDDR5.cpp | 394 ++++++++++++++++++ .../src/controller/checker/CheckerGDDR5.h | 69 +++ .../src/controller/checker/CheckerGDDR5X.cpp | 394 ++++++++++++++++++ .../src/controller/checker/CheckerGDDR5X.h | 69 +++ .../src/controller/checker/CheckerGDDR6.cpp | 383 +++++++++++++++++ .../src/controller/checker/CheckerGDDR6.h | 68 +++ .../src/controller/checker/CheckerHBM2.h | 3 - .../src/controller/checker/CheckerIF.h | 3 - .../src/controller/checker/CheckerLPDDR4.h | 3 - .../src/controller/checker/CheckerWideIO.h | 3 - .../src/controller/checker/CheckerWideIO2.h | 3 - DRAMSys/library/src/simulation/DRAMSys.cpp | 24 ++ .../library/src/simulation/dram/DramDDR3.h | 1 - .../library/src/simulation/dram/DramDDR4.h | 1 - .../library/src/simulation/dram/DramGDDR5.cpp | 57 +++ .../library/src/simulation/dram/DramGDDR5.h | 50 +++ .../src/simulation/dram/DramGDDR5X.cpp | 57 +++ .../library/src/simulation/dram/DramGDDR5X.h | 50 +++ .../library/src/simulation/dram/DramGDDR6.cpp | 57 +++ .../library/src/simulation/dram/DramGDDR6.h | 51 +++ .../library/src/simulation/dram/DramHBM2.cpp | 2 - .../library/src/simulation/dram/DramHBM2.h | 3 - .../src/simulation/dram/DramLPDDR4.cpp | 5 +- .../library/src/simulation/dram/DramLPDDR4.h | 1 - .../src/simulation/dram/DramRecordable.cpp | 6 + .../src/simulation/dram/DramWideIO2.cpp | 2 - .../library/src/simulation/dram/DramWideIO2.h | 3 - 40 files changed, 2521 insertions(+), 46 deletions(-) create mode 100644 DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.cpp create mode 100644 DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.h create mode 100644 DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.cpp create mode 100644 DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.h create mode 100644 DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.cpp create mode 100644 DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.h create mode 100644 DRAMSys/library/src/controller/checker/CheckerGDDR5.cpp create mode 100644 DRAMSys/library/src/controller/checker/CheckerGDDR5.h create mode 100644 DRAMSys/library/src/controller/checker/CheckerGDDR5X.cpp create mode 100644 DRAMSys/library/src/controller/checker/CheckerGDDR5X.h create mode 100644 DRAMSys/library/src/controller/checker/CheckerGDDR6.cpp create mode 100644 DRAMSys/library/src/controller/checker/CheckerGDDR6.h create mode 100644 DRAMSys/library/src/simulation/dram/DramGDDR5.cpp create mode 100644 DRAMSys/library/src/simulation/dram/DramGDDR5.h create mode 100644 DRAMSys/library/src/simulation/dram/DramGDDR5X.cpp create mode 100644 DRAMSys/library/src/simulation/dram/DramGDDR5X.h create mode 100644 DRAMSys/library/src/simulation/dram/DramGDDR6.cpp create mode 100644 DRAMSys/library/src/simulation/dram/DramGDDR6.h diff --git a/DRAMSys/library/library.pro b/DRAMSys/library/library.pro index 1e09b7ea..6ab96b7c 100644 --- a/DRAMSys/library/library.pro +++ b/DRAMSys/library/library.pro @@ -146,7 +146,16 @@ SOURCES += \ src/controller/checker/CheckerWideIO2.cpp \ src/configuration/memspec/MemSpecHBM2.cpp \ src/simulation/dram/DramHBM2.cpp \ - src/controller/checker/CheckerHBM2.cpp + src/controller/checker/CheckerHBM2.cpp \ + src/configuration/memspec/MemSpecGDDR5.cpp \ + src/configuration/memspec/MemSpecGDDR5X.cpp \ + src/configuration/memspec/MemSpecGDDR6.cpp \ + src/controller/checker/CheckerGDDR5.cpp \ + src/controller/checker/CheckerGDDR5X.cpp \ + src/controller/checker/CheckerGDDR6.cpp \ + src/simulation/dram/DramGDDR5.cpp \ + src/simulation/dram/DramGDDR5X.cpp \ + src/simulation/dram/DramGDDR6.cpp HEADERS += \ src/common/third_party/tinyxml2/tinyxml2.h \ @@ -226,7 +235,16 @@ HEADERS += \ src/controller/checker/CheckerWideIO2.h \ src/configuration/memspec/MemSpecHBM2.h \ src/simulation/dram/DramHBM2.h \ - src/controller/checker/CheckerHBM2.h + src/controller/checker/CheckerHBM2.h \ + src/configuration/memspec/MemSpecGDDR5.h \ + src/configuration/memspec/MemSpecGDDR5X.h \ + src/configuration/memspec/MemSpecGDDR6.h \ + src/controller/checker/CheckerGDDR5.h \ + src/controller/checker/CheckerGDDR5X.h \ + src/controller/checker/CheckerGDDR6.h \ + src/simulation/dram/DramGDDR5.h \ + src/simulation/dram/DramGDDR5X.h \ + src/simulation/dram/DramGDDR6.h #src/common/third_party/json/include/nlohmann/json.hpp \ thermalsim = $$(THERMALSIM) diff --git a/DRAMSys/library/src/configuration/ConfigurationLoader.cpp b/DRAMSys/library/src/configuration/ConfigurationLoader.cpp index f67af551..29a46b3e 100644 --- a/DRAMSys/library/src/configuration/ConfigurationLoader.cpp +++ b/DRAMSys/library/src/configuration/ConfigurationLoader.cpp @@ -43,6 +43,9 @@ #include "memspec/MemSpecLPDDR4.h" #include "memspec/MemSpecWideIO2.h" #include "memspec/MemSpecHBM2.h" +#include "memspec/MemSpecGDDR5.h" +#include "memspec/MemSpecGDDR5X.h" +#include "memspec/MemSpecGDDR6.h" #include "../common/timingCalculations.h" using namespace tinyxml2; @@ -182,6 +185,24 @@ void ConfigurationLoader::loadMemSpec(Configuration &config, loadCommons(config, memspec); loadHBM2(config, memspec); } + else if (memoryType == "GDDR5") + { + Configuration::getInstance().memSpec = new MemSpecGDDR5(); + loadCommons(config, memspec); + loadGDDR5(config, memspec); + } + else if (memoryType == "GDDR5X") + { + Configuration::getInstance().memSpec = new MemSpecGDDR5X(); + loadCommons(config, memspec); + loadGDDR5X(config, memspec); + } + else if (memoryType == "GDDR6") + { + Configuration::getInstance().memSpec = new MemSpecGDDR6(); + loadCommons(config, memspec); + loadGDDR6(config, memspec); + } else reportFatal("ConfigurationLoader", "Unsupported DRAM type"); } @@ -549,8 +570,16 @@ void ConfigurationLoader::loadHBM2(Configuration &config, XMLElement *xmlSpec) memSpec->tRTW = clk * queryUIntParameter(timings, "RTW"); memSpec->tXP = clk * queryUIntParameter(timings, "XP"); memSpec->tCKE = clk * queryUIntParameter(timings, "CKE"); -// memSpec->tPD = clk * queryUIntParameter(timings, "PD"); -// memSpec->tCKESR = clk * queryUIntParameter(timings, "CKESR"); + memSpec->tPD = memSpec->tCKE; + memSpec->tRDPDE = memSpec->tRL + memSpec->tPL + + (memSpec->BurstLength / memSpec->DataRate + 1) * memSpec->clk; + memSpec->tWRPDE = memSpec->tWL + memSpec->tPL + + (memSpec->BurstLength / memSpec->DataRate + 1) * memSpec->clk + memSpec->tWR; + memSpec->tWRAPDE = memSpec->tWL + memSpec->tPL + + (memSpec->BurstLength / memSpec->DataRate + 1) * memSpec->clk + memSpec->tWR; + memSpec->tCKESR = memSpec->tCKE + memSpec->clk; + memSpec->tRDSRE = memSpec->tRL + memSpec->tPL + + (memSpec->BurstLength / memSpec->DataRate + 1) * memSpec->clk; memSpec->tXS = clk * queryUIntParameter(timings, "XS"); memSpec->tRFC = clk * queryUIntParameter(timings, "RFC"); memSpec->tRFCSB = clk * queryUIntParameter(timings, "RFCSB"); @@ -561,3 +590,186 @@ void ConfigurationLoader::loadHBM2(Configuration &config, XMLElement *xmlSpec) // Currents and voltages // TODO: to be completed } + +void ConfigurationLoader::loadGDDR5(Configuration &config, XMLElement *xmlSpec) +{ + MemSpecGDDR5 *memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("ConfigurationLoader", "Wrong MemSpec chosen"); + + // MemArchitecture + XMLElement *architecture = xmlSpec->FirstChildElement("memarchitecturespec"); + memSpec->NumberOfRanks = queryUIntParameter(architecture, "nbrOfRanks"); + memSpec->BanksPerRank = queryUIntParameter(architecture, "nbrOfBanks"); + memSpec->GroupsPerRank = queryUIntParameter(architecture, "nbrOfBankGroups"); + memSpec->BanksPerGroup = memSpec->BanksPerRank / memSpec->GroupsPerRank; + memSpec->NumberOfBanks = memSpec->BanksPerRank * memSpec->NumberOfRanks; + memSpec->NumberOfBankGroups = memSpec->GroupsPerRank * memSpec->NumberOfRanks; + + // MemTimings specific for GDDR5 + XMLElement *timings = xmlSpec->FirstChildElement("memtimingspec"); + sc_time clk = memSpec->clk; + memSpec->tRP = clk * queryUIntParameter(timings, "RP"); + memSpec->tRAS = clk * queryUIntParameter(timings, "RAS"); + memSpec->tRC = clk * queryUIntParameter(timings, "RC"); + memSpec->tRCDRD = clk * queryUIntParameter(timings, "RCDRD"); + memSpec->tRCDWR = clk * queryUIntParameter(timings, "RCDWR"); + memSpec->tRTP = clk * queryUIntParameter(timings, "RTP"); + memSpec->tRRDS = clk * queryUIntParameter(timings, "RRDS"); + memSpec->tRRDL = clk * queryUIntParameter(timings, "RRDL"); + memSpec->tCCDS = clk * queryUIntParameter(timings, "CCDS"); + memSpec->tCCDL = clk * queryUIntParameter(timings, "CCDL"); + memSpec->tCL = clk * queryUIntParameter(timings, "CL"); + memSpec->tWCK2CKPIN = clk * queryUIntParameter(timings, "WCK2CKPIN"); + memSpec->tWCK2CK = clk * queryUIntParameter(timings, "WCK2CK"); + memSpec->tWCK2DQO = clk * queryUIntParameter(timings, "WCK2DQO"); + memSpec->tRTW = clk * queryUIntParameter(timings, "RTW"); + memSpec->tWL = clk * queryUIntParameter(timings, "WL"); + memSpec->tWCK2DQI = clk * queryUIntParameter(timings, "WCK2DQI"); + memSpec->tWR = clk * queryUIntParameter(timings, "WR"); + memSpec->tWTRS = clk * queryUIntParameter(timings, "WTRS"); + memSpec->tWTRL = clk * queryUIntParameter(timings, "WTRL"); + memSpec->tCKE = clk * queryUIntParameter(timings, "CKE"); + memSpec->tPD = memSpec->tCKE; + memSpec->tXPN = clk * queryUIntParameter(timings, "XPN"); + memSpec->tREFI = clk * queryUIntParameter(timings, "REFI"); + memSpec->tREFIPB = clk * queryUIntParameter(timings, "REFIPB"); + memSpec->tRFC = clk * queryUIntParameter(timings, "RFC"); + memSpec->tRFCPB = clk * queryUIntParameter(timings, "RFCPB"); + memSpec->tRREFD = clk * queryUIntParameter(timings, "RREFD"); + memSpec->tXS = clk * queryUIntParameter(timings, "XS"); + memSpec->tFAW = clk * queryUIntParameter(timings, "FAW"); + memSpec->t32AW = clk * queryUIntParameter(timings, "32AW"); + memSpec->tRDSRE = memSpec->tCL + memSpec->tWCK2CKPIN + memSpec->tWCK2CK + + memSpec->tWCK2DQO + memSpec->BurstLength / memSpec->DataRate * clk; + memSpec->tWRSRE = memSpec->tWL + memSpec->tWCK2CKPIN + memSpec->tWCK2CK + + memSpec->tWCK2DQI + memSpec->BurstLength / memSpec->DataRate * clk; + memSpec->tPPD = clk * queryUIntParameter(timings, "PPD"); + memSpec->tLK = clk * queryUIntParameter(timings, "LK"); + + // Currents and voltages + // TODO: to be completed +} + +void ConfigurationLoader::loadGDDR5X(Configuration &config, XMLElement *xmlSpec) +{ + MemSpecGDDR5X *memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("ConfigurationLoader", "Wrong MemSpec chosen"); + + // MemArchitecture + XMLElement *architecture = xmlSpec->FirstChildElement("memarchitecturespec"); + memSpec->NumberOfRanks = queryUIntParameter(architecture, "nbrOfRanks"); + memSpec->BanksPerRank = queryUIntParameter(architecture, "nbrOfBanks"); + memSpec->GroupsPerRank = queryUIntParameter(architecture, "nbrOfBankGroups"); + memSpec->BanksPerGroup = memSpec->BanksPerRank / memSpec->GroupsPerRank; + memSpec->NumberOfBanks = memSpec->BanksPerRank * memSpec->NumberOfRanks; + memSpec->NumberOfBankGroups = memSpec->GroupsPerRank * memSpec->NumberOfRanks; + + // MemTimings specific for GDDR5X + XMLElement *timings = xmlSpec->FirstChildElement("memtimingspec"); + sc_time clk = memSpec->clk; + memSpec->tRP = clk * queryUIntParameter(timings, "RP"); + memSpec->tRAS = clk * queryUIntParameter(timings, "RAS"); + memSpec->tRC = clk * queryUIntParameter(timings, "RC"); + memSpec->tRCDRD = clk * queryUIntParameter(timings, "RCDRD"); + memSpec->tRCDWR = clk * queryUIntParameter(timings, "RCDWR"); + memSpec->tRTP = clk * queryUIntParameter(timings, "RTP"); + memSpec->tRRDS = clk * queryUIntParameter(timings, "RRDS"); + memSpec->tRRDL = clk * queryUIntParameter(timings, "RRDL"); + memSpec->tCCDS = clk * queryUIntParameter(timings, "CCDS"); + memSpec->tCCDL = clk * queryUIntParameter(timings, "CCDL"); + memSpec->tRL = clk * queryUIntParameter(timings, "RL"); + memSpec->tWCK2CKPIN = clk * queryUIntParameter(timings, "WCK2CKPIN"); + memSpec->tWCK2CK = clk * queryUIntParameter(timings, "WCK2CK"); + memSpec->tWCK2DQO = clk * queryUIntParameter(timings, "WCK2DQO"); + memSpec->tRTW = clk * queryUIntParameter(timings, "RTW"); + memSpec->tWL = clk * queryUIntParameter(timings, "WL"); + memSpec->tWCK2DQI = clk * queryUIntParameter(timings, "WCK2DQI"); + memSpec->tWR = clk * queryUIntParameter(timings, "WR"); + memSpec->tWTRS = clk * queryUIntParameter(timings, "WTRS"); + memSpec->tWTRL = clk * queryUIntParameter(timings, "WTRL"); + memSpec->tCKE = clk * queryUIntParameter(timings, "CKE"); + memSpec->tPD = memSpec->tCKE; + memSpec->tXP = clk * queryUIntParameter(timings, "XP"); + memSpec->tREFI = clk * queryUIntParameter(timings, "REFI"); + memSpec->tREFIPB = clk * queryUIntParameter(timings, "REFIPB"); + memSpec->tRFC = clk * queryUIntParameter(timings, "RFC"); + memSpec->tRFCPB = clk * queryUIntParameter(timings, "RFCPB"); + memSpec->tRREFD = clk * queryUIntParameter(timings, "RREFD"); + memSpec->tXS = clk * queryUIntParameter(timings, "XS"); + memSpec->tFAW = clk * queryUIntParameter(timings, "FAW"); + memSpec->t32AW = clk * queryUIntParameter(timings, "32AW"); + memSpec->tRDSRE = memSpec->tRL + memSpec->tWCK2CKPIN + memSpec->tWCK2CK + + memSpec->tWCK2DQO + memSpec->BurstLength / memSpec->DataRate * clk; + memSpec->tWRSRE = memSpec->tWL + memSpec->tWCK2CKPIN + memSpec->tWCK2CK + + memSpec->tWCK2DQI + memSpec->BurstLength / memSpec->DataRate * clk; + memSpec->tPPD = clk * queryUIntParameter(timings, "PPD"); + memSpec->tLK = clk * queryUIntParameter(timings, "LK"); + + // Currents and voltages + // TODO: to be completed +} + +void ConfigurationLoader::loadGDDR6(Configuration &config, XMLElement *xmlSpec) +{ + MemSpecGDDR6 *memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("ConfigurationLoader", "Wrong MemSpec chosen"); + + // MemArchitecture + XMLElement *architecture = xmlSpec->FirstChildElement("memarchitecturespec"); + memSpec->NumberOfRanks = queryUIntParameter(architecture, "nbrOfRanks"); + memSpec->BanksPerRank = queryUIntParameter(architecture, "nbrOfBanks"); + memSpec->GroupsPerRank = queryUIntParameter(architecture, "nbrOfBankGroups"); + memSpec->BanksPerGroup = memSpec->BanksPerRank / memSpec->GroupsPerRank; + memSpec->NumberOfBanks = memSpec->BanksPerRank * memSpec->NumberOfRanks; + memSpec->NumberOfBankGroups = memSpec->GroupsPerRank * memSpec->NumberOfRanks; + + // MemTimings specific for GDDR6 + XMLElement *timings = xmlSpec->FirstChildElement("memtimingspec"); + sc_time clk = memSpec->clk; + memSpec->tRP = clk * queryUIntParameter(timings, "RP"); + memSpec->tRAS = clk * queryUIntParameter(timings, "RAS"); + memSpec->tRC = clk * queryUIntParameter(timings, "RC"); + memSpec->tRCDRD = clk * queryUIntParameter(timings, "RCDRD"); + memSpec->tRCDWR = clk * queryUIntParameter(timings, "RCDWR"); + memSpec->tRTP = clk * queryUIntParameter(timings, "RTP"); + memSpec->tRRDS = clk * queryUIntParameter(timings, "RRDS"); + memSpec->tRRDL = clk * queryUIntParameter(timings, "RRDL"); + memSpec->tCCDS = clk * queryUIntParameter(timings, "CCDS"); + memSpec->tCCDL = clk * queryUIntParameter(timings, "CCDL"); + memSpec->tRL = clk * queryUIntParameter(timings, "RL"); + memSpec->tWCK2CKPIN = clk * queryUIntParameter(timings, "WCK2CKPIN"); + memSpec->tWCK2CK = clk * queryUIntParameter(timings, "WCK2CK"); + memSpec->tWCK2DQO = clk * queryUIntParameter(timings, "WCK2DQO"); + memSpec->tRTW = clk * queryUIntParameter(timings, "RTW"); + memSpec->tWL = clk * queryUIntParameter(timings, "WL"); + memSpec->tWCK2DQI = clk * queryUIntParameter(timings, "WCK2DQI"); + memSpec->tWR = clk * queryUIntParameter(timings, "WR"); + memSpec->tWTRS = clk * queryUIntParameter(timings, "WTRS"); + memSpec->tWTRL = clk * queryUIntParameter(timings, "WTRL"); + memSpec->tCKE = clk * queryUIntParameter(timings, "CKE"); + memSpec->tPD = memSpec->tCKE; + memSpec->tCKESR = clk * queryUIntParameter(timings, "CKESR"); + memSpec->tXP = clk * queryUIntParameter(timings, "XP"); + memSpec->tREFI = clk * queryUIntParameter(timings, "REFI"); + memSpec->tREFIPB = clk * queryUIntParameter(timings, "REFIPB"); + memSpec->tRFC = clk * queryUIntParameter(timings, "RFC"); + memSpec->tRFCPB = clk * queryUIntParameter(timings, "RFCPB"); + memSpec->tRREFD = clk * queryUIntParameter(timings, "RREFD"); + memSpec->tXS = clk * queryUIntParameter(timings, "XS"); + memSpec->tFAW = clk * queryUIntParameter(timings, "FAW"); + memSpec->tRDSRE = memSpec->tRL + memSpec->tWCK2CKPIN + memSpec->tWCK2CK + + memSpec->tWCK2DQO + memSpec->BurstLength / memSpec->DataRate * clk; + memSpec->tWRSRE = memSpec->tWL + memSpec->tWCK2CKPIN + memSpec->tWCK2CK + + memSpec->tWCK2DQI + memSpec->BurstLength / memSpec->DataRate * clk; + memSpec->tPPD = clk * queryUIntParameter(timings, "PPD"); + memSpec->tLK = clk * queryUIntParameter(timings, "LK"); + memSpec->tACTPDE = clk * queryUIntParameter(timings, "ACTPDE"); + memSpec->tPREPDE = clk * queryUIntParameter(timings, "PREPDE"); + memSpec->tREFPDE = clk * queryUIntParameter(timings, "REFPDE"); + + // Currents and voltages + // TODO: to be completed +} diff --git a/DRAMSys/library/src/configuration/ConfigurationLoader.h b/DRAMSys/library/src/configuration/ConfigurationLoader.h index add7fc88..b5ea9290 100644 --- a/DRAMSys/library/src/configuration/ConfigurationLoader.h +++ b/DRAMSys/library/src/configuration/ConfigurationLoader.h @@ -75,6 +75,9 @@ private: static void loadWideIO(Configuration &config, tinyxml2::XMLElement *memspec); static void loadWideIO2(Configuration &config, tinyxml2::XMLElement *memspec); static void loadHBM2(Configuration &config, tinyxml2::XMLElement *memspec); + static void loadGDDR5(Configuration &config, tinyxml2::XMLElement *memspec); + static void loadGDDR5X(Configuration &config, tinyxml2::XMLElement *memspec); + static void loadGDDR6(Configuration &config, tinyxml2::XMLElement *memspec); }; diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.cpp new file mode 100644 index 00000000..5bcbcbc6 --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.cpp @@ -0,0 +1,88 @@ +/* + * 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. + * + * Authors: + * Lukas Steiner + */ + +#include "MemSpecGDDR5.h" + +sc_time MemSpecGDDR5::getRefreshIntervalAB() const +{ + return tREFI; +} + +sc_time MemSpecGDDR5::getRefreshIntervalPB() const +{ + return tREFIPB; +} + +sc_time MemSpecGDDR5::getExecutionTime(Command command, const tlm_generic_payload &payload) const +{ + if (command == Command::PRE || command == Command::PREA) + return tRP; + else if (command == Command::ACT) + { + if (payload.get_command() == TLM_READ_COMMAND) + return tRCDRD + clk; + else + return tRCDWR + clk; + } + else if (command == Command::RD || command == Command::RDA) + return tCL + tWCK2CKPIN + tWCK2CK + tWCK2DQO + getReadAccessTime(); + else if (command == Command::WR || command == Command::WRA) + return tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI + getWriteAccessTime(); + else if (command == Command::REFA) + return tRFC; + else if (command == Command::REFB) + return tRFCPB; + else + { + SC_REPORT_FATAL("getExecutionTime", + "command not known or command doesn't have a fixed execution time"); + return SC_ZERO_TIME; + } +} + +TimeInterval MemSpecGDDR5::getIntervalOnDataStrobe(Command command) const +{ + if (command == Command::RD || command == Command::RDA) + return TimeInterval(sc_time_stamp() + tCL + tWCK2CKPIN + tWCK2CK + tWCK2DQO, + sc_time_stamp() + tCL + tWCK2CKPIN + tWCK2CK + tWCK2DQO + getReadAccessTime()); + else if (command == Command::WR || command == Command::WRA) + return TimeInterval(sc_time_stamp() + tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI, + sc_time_stamp() + tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI + getWriteAccessTime()); + else + { + SC_REPORT_FATAL("MemSpecGDDR5", "Method was called with invalid argument"); + return TimeInterval(); + } +} diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.h b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.h new file mode 100644 index 00000000..c04bbfd2 --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5.h @@ -0,0 +1,90 @@ +/* + * 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. + * + * Authors: + * Lukas Steiner + */ + +#ifndef MEMSPECGDDR5_H +#define MEMSPECGDDR5_H + +#include "MemSpec.h" + +struct MemSpecGDDR5 final : public MemSpec +{ + // Memspec Variables: + sc_time tRP; + sc_time tRAS; + sc_time tRC; + sc_time tRCDRD; + sc_time tRCDWR; + sc_time tRTP; + sc_time tRRDS; + sc_time tRRDL; + sc_time tCCDS; + sc_time tCCDL; + sc_time tCL; + sc_time tWCK2CKPIN; + sc_time tWCK2CK; + sc_time tWCK2DQO; + sc_time tRTW; + sc_time tWL; + sc_time tWCK2DQI; + sc_time tWR; + sc_time tWTRS; + sc_time tWTRL; + sc_time tCKE; + sc_time tPD; // = tCKE; + sc_time tXPN; + sc_time tREFI; + sc_time tREFIPB; + sc_time tRFC; + sc_time tRFCPB; + sc_time tRREFD; + sc_time tXS; + sc_time tFAW; + sc_time t32AW; + sc_time tRDSRE; // = tCL + tWCK2CKPIN + tWCK2CK + tWCK2DQO + BurstLength / DataRate * tCK; + sc_time tWRSRE; // = tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI + BurstLength / DataRate * tCK; + sc_time tPPD; + sc_time tLK; + + // Currents and Voltages: + // TODO: to be completed + + virtual sc_time getRefreshIntervalPB() const override; + virtual sc_time getRefreshIntervalAB() const override; + + virtual sc_time getExecutionTime(Command, const tlm_generic_payload &) const override; + virtual TimeInterval getIntervalOnDataStrobe(Command) const override; +}; + +#endif // MEMSPECGDDR5_H diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.cpp new file mode 100644 index 00000000..d7e148f6 --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.cpp @@ -0,0 +1,88 @@ +/* + * 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. + * + * Authors: + * Lukas Steiner + */ + +#include "MemSpecGDDR5X.h" + +sc_time MemSpecGDDR5X::getRefreshIntervalAB() const +{ + return tREFI; +} + +sc_time MemSpecGDDR5X::getRefreshIntervalPB() const +{ + return tREFIPB; +} + +sc_time MemSpecGDDR5X::getExecutionTime(Command command, const tlm_generic_payload &payload) const +{ + if (command == Command::PRE || command == Command::PREA) + return tRP; + else if (command == Command::ACT) + { + if (payload.get_command() == TLM_READ_COMMAND) + return tRCDRD + clk; + else + return tRCDWR + clk; + } + else if (command == Command::RD || command == Command::RDA) + return tRL + tWCK2CKPIN + tWCK2CK + tWCK2DQO + getReadAccessTime(); + else if (command == Command::WR || command == Command::WRA) + return tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI + getWriteAccessTime(); + else if (command == Command::REFA) + return tRFC; + else if (command == Command::REFB) + return tRFCPB; + else + { + SC_REPORT_FATAL("getExecutionTime", + "command not known or command doesn't have a fixed execution time"); + return SC_ZERO_TIME; + } +} + +TimeInterval MemSpecGDDR5X::getIntervalOnDataStrobe(Command command) const +{ + if (command == Command::RD || command == Command::RDA) + return TimeInterval(sc_time_stamp() + tRL + tWCK2CKPIN + tWCK2CK + tWCK2DQO, + sc_time_stamp() + tRL + tWCK2CKPIN + tWCK2CK + tWCK2DQO + getReadAccessTime()); + else if (command == Command::WR || command == Command::WRA) + return TimeInterval(sc_time_stamp() + tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI, + sc_time_stamp() + tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI + getWriteAccessTime()); + else + { + SC_REPORT_FATAL("MemSpecGDDR5X", "Method was called with invalid argument"); + return TimeInterval(); + } +} diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.h b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.h new file mode 100644 index 00000000..a69d76ce --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR5X.h @@ -0,0 +1,90 @@ +/* + * 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. + * + * Authors: + * Lukas Steiner + */ + +#ifndef MEMSPECGDDR5X_H +#define MEMSPECGDDR5X_H + +#include "MemSpec.h" + +struct MemSpecGDDR5X final : public MemSpec +{ + // Memspec Variables: + sc_time tRP; + sc_time tRAS; + sc_time tRC; + sc_time tRCDRD; + sc_time tRCDWR; + sc_time tRTP; + sc_time tRRDS; + sc_time tRRDL; + sc_time tCCDS; + sc_time tCCDL; + sc_time tRL; + sc_time tWCK2CKPIN; + sc_time tWCK2CK; + sc_time tWCK2DQO; + sc_time tRTW; + sc_time tWL; + sc_time tWCK2DQI; + sc_time tWR; + sc_time tWTRS; + sc_time tWTRL; + sc_time tCKE; + sc_time tPD; // = tCKE; + sc_time tXP; + sc_time tREFI; + sc_time tREFIPB; + sc_time tRFC; + sc_time tRFCPB; + sc_time tRREFD; + sc_time tXS; + sc_time tFAW; + sc_time t32AW; + sc_time tRDSRE; // = tCL + tWCK2CKPIN + tWCK2CK + tWCK2DQO + BurstLength / DataRate * tCK; + sc_time tWRSRE; // = tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI + BurstLength / DataRate * tCK; + sc_time tPPD; + sc_time tLK; + + // Currents and Voltages: + // TODO: to be completed + + virtual sc_time getRefreshIntervalPB() const override; + virtual sc_time getRefreshIntervalAB() const override; + + virtual sc_time getExecutionTime(Command, const tlm_generic_payload &) const override; + virtual TimeInterval getIntervalOnDataStrobe(Command) const override; +}; + +#endif // MEMSPECGDDR5X_H diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.cpp new file mode 100644 index 00000000..9be62f01 --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.cpp @@ -0,0 +1,88 @@ +/* + * 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. + * + * Authors: + * Lukas Steiner + */ + +#include "MemSpecGDDR6.h" + +sc_time MemSpecGDDR6::getRefreshIntervalAB() const +{ + return tREFI; +} + +sc_time MemSpecGDDR6::getRefreshIntervalPB() const +{ + return tREFIPB; +} + +sc_time MemSpecGDDR6::getExecutionTime(Command command, const tlm_generic_payload &payload) const +{ + if (command == Command::PRE || command == Command::PREA) + return tRP; + else if (command == Command::ACT) + { + if (payload.get_command() == TLM_READ_COMMAND) + return tRCDRD + clk; + else + return tRCDWR + clk; + } + else if (command == Command::RD || command == Command::RDA) + return tRL + tWCK2CKPIN + tWCK2CK + tWCK2DQO + getReadAccessTime(); + else if (command == Command::WR || command == Command::WRA) + return tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI + getWriteAccessTime(); + else if (command == Command::REFA) + return tRFC; + else if (command == Command::REFB) + return tRFCPB; + else + { + SC_REPORT_FATAL("getExecutionTime", + "command not known or command doesn't have a fixed execution time"); + return SC_ZERO_TIME; + } +} + +TimeInterval MemSpecGDDR6::getIntervalOnDataStrobe(Command command) const +{ + if (command == Command::RD || command == Command::RDA) + return TimeInterval(sc_time_stamp() + tRL + tWCK2CKPIN + tWCK2CK + tWCK2DQO, + sc_time_stamp() + tRL + tWCK2CKPIN + tWCK2CK + tWCK2DQO + getReadAccessTime()); + else if (command == Command::WR || command == Command::WRA) + return TimeInterval(sc_time_stamp() + tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI, + sc_time_stamp() + tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI + getWriteAccessTime()); + else + { + SC_REPORT_FATAL("MemSpecGDDR6", "Method was called with invalid argument"); + return TimeInterval(); + } +} diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.h b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.h new file mode 100644 index 00000000..43924408 --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecGDDR6.h @@ -0,0 +1,93 @@ +/* + * 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. + * + * Authors: + * Lukas Steiner + */ + +#ifndef MEMSPECGDDR6_H +#define MEMSPECGDDR6_H + +#include "MemSpec.h" + +struct MemSpecGDDR6 final : public MemSpec +{ + // Memspec Variables: + sc_time tRP; + sc_time tRAS; + sc_time tRC; + sc_time tRCDRD; + sc_time tRCDWR; + sc_time tRTP; + sc_time tRRDS; + sc_time tRRDL; + sc_time tCCDS; + sc_time tCCDL; + sc_time tRL; + sc_time tWCK2CKPIN; + sc_time tWCK2CK; + sc_time tWCK2DQO; + sc_time tRTW; + sc_time tWL; + sc_time tWCK2DQI; + sc_time tWR; + sc_time tWTRS; + sc_time tWTRL; + sc_time tCKE; + sc_time tPD; // = tCKE; + sc_time tCKESR; + sc_time tXP; + sc_time tREFI; + sc_time tREFIPB; + sc_time tRFC; + sc_time tRFCPB; + sc_time tRREFD; + sc_time tXS; + sc_time tFAW; + sc_time tRDSRE; // = tCL + tWCK2CKPIN + tWCK2CK + tWCK2DQO + BurstLength / DataRate * tCK; + sc_time tWRSRE; // = tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI + BurstLength / DataRate * tCK; + sc_time tPPD; + sc_time tLK; + sc_time tACTPDE; + sc_time tPREPDE; + sc_time tREFPDE; + + // Currents and Voltages: + // TODO: to be completed + + virtual sc_time getRefreshIntervalPB() const override; + virtual sc_time getRefreshIntervalAB() const override; + + virtual sc_time getExecutionTime(Command, const tlm_generic_payload &) const override; + virtual TimeInterval getIntervalOnDataStrobe(Command) const override; +}; + +#endif // MEMSPECGDDR6_H diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.h b/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.h index d09c31c9..72b96781 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpecHBM2.h @@ -66,12 +66,12 @@ struct MemSpecHBM2 final : public MemSpec sc_time tRTW; sc_time tXP; sc_time tCKE; - sc_time tPD = tCKE; - sc_time tRDPDE = tRL + tPL + (BurstLength / 2) * clk + clk; - sc_time tWRPDE = tWL + tPL + (BurstLength / 2) * clk + clk + tWR; - sc_time tWRAPDE = tWL + tPL + (BurstLength / 2) * clk + clk + tWR; - sc_time tCKESR = tCKE + clk; - sc_time tRDSRE = tRL + tPL + (BurstLength / 2) * clk + clk; + sc_time tPD; // = tCKE; + sc_time tRDPDE; // = tRL + tPL + (BurstLength / DataRate) * clk + clk; + sc_time tWRPDE; // = tWL + tPL + (BurstLength / DataRate) * clk + clk + tWR; + sc_time tWRAPDE; // = tWL + tPL + (BurstLength / DataRate) * clk + clk + tWR; + sc_time tCKESR; // = tCKE + clk; + sc_time tRDSRE; // = tRL + tPL + (BurstLength / DataRate) * clk + clk; sc_time tXS; sc_time tRFC; sc_time tRFCSB; diff --git a/DRAMSys/library/src/controller/Controller.cpp b/DRAMSys/library/src/controller/Controller.cpp index f3359a0f..11209180 100644 --- a/DRAMSys/library/src/controller/Controller.cpp +++ b/DRAMSys/library/src/controller/Controller.cpp @@ -47,6 +47,9 @@ #include "checker/CheckerLPDDR4.h" #include "checker/CheckerWideIO2.h" #include "checker/CheckerHBM2.h" +#include "checker/CheckerGDDR5.h" +#include "checker/CheckerGDDR5X.h" +#include "checker/CheckerGDDR6.h" #include "refresh/RefreshManager.h" #include "refresh/RefreshManagerDummy.h" #include "refresh/RefreshManagerBankwise.h" @@ -74,6 +77,12 @@ Controller::Controller(sc_module_name name) : checker = new CheckerWideIO2(); else if (memSpec->MemoryType == "HBM2") checker = new CheckerHBM2(); + else if (memSpec->MemoryType == "GDDR5") + checker = new CheckerGDDR5(); + else if (memSpec->MemoryType == "GDDR5X") + checker = new CheckerGDDR5X(); + else if (memSpec->MemoryType == "GDDR6") + checker = new CheckerGDDR6(); else SC_REPORT_FATAL("Controller", "Unsupported DRAM type"); diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR3.h b/DRAMSys/library/src/controller/checker/CheckerDDR3.h index 55f36c9c..12697b3d 100644 --- a/DRAMSys/library/src/controller/checker/CheckerDDR3.h +++ b/DRAMSys/library/src/controller/checker/CheckerDDR3.h @@ -58,9 +58,6 @@ private: // Four activate window std::vector> lastActivates; - - // PowerDown TODO: Implement this method? - //sc_time getTimeConstraintToEnterPowerDown(Command lastCmd, Command pdnCmd) const; }; #endif // CHECKERDDR3_H diff --git a/DRAMSys/library/src/controller/checker/CheckerDDR4.h b/DRAMSys/library/src/controller/checker/CheckerDDR4.h index ca85a4c3..2ff961a9 100644 --- a/DRAMSys/library/src/controller/checker/CheckerDDR4.h +++ b/DRAMSys/library/src/controller/checker/CheckerDDR4.h @@ -61,9 +61,6 @@ private: std::vector> lastActivates; sc_time burstClocks; - - // PowerDown TODO: Implement this method? - //sc_time getTimeConstraintToEnterPowerDown(Command lastCmd, Command pdnCmd) const; }; #endif // CHECKERDDR4_H diff --git a/DRAMSys/library/src/controller/checker/CheckerGDDR5.cpp b/DRAMSys/library/src/controller/checker/CheckerGDDR5.cpp new file mode 100644 index 00000000..5f8089fe --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerGDDR5.cpp @@ -0,0 +1,394 @@ +/* + * 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 "CheckerGDDR5.h" + +CheckerGDDR5::CheckerGDDR5() +{ + Configuration &config = Configuration::getInstance(); + memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("CheckerGDDR5", "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); + last32Activates = std::vector>(memSpec->NumberOfRanks); + + burstClocks = (memSpec->BurstLength / memSpec->DataRate) * memSpec->clk; +} + +sc_time CheckerGDDR5::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::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->tRRDL); + + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDS); + + 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 = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + + lastCommandStart = lastScheduledByCommandAndBank[Command::REFB][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCPB); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD); + + if (last4Activates[rank.ID()].size() == 4) + earliestTimeToStart = std::max(earliestTimeToStart, last4Activates[rank.ID()].front() + memSpec->tFAW); + + if (last32Activates[rank.ID()].size() == 32) + earliestTimeToStart = std::max(earliestTimeToStart, last32Activates[rank.ID()].front() + memSpec->t32AW); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::RD) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDRD); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRL); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRL); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRS); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDRD); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + std::max(memSpec->tWR - memSpec->tRTP, memSpec->tWTRL)); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRL); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRL); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRS); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::WR || command == Command::WRA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDWR); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + 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); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::PREA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::REFA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::REFB) + { + 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->tRRDL); + + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDS); + + 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::REFB][bank.ID()]; +// if (lastCommandStart != SC_ZERO_TIME) +// earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCSB); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + { + if (bankwiseRefreshCounter == 0) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCPB); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD); + } + + if (last4Activates[rank.ID()].size() == 4) + earliestTimeToStart = std::max(earliestTimeToStart, last4Activates[rank.ID()].front() + memSpec->tFAW); + + if (last32Activates[rank.ID()].size() == 32) + earliestTimeToStart = std::max(earliestTimeToStart, last32Activates[rank.ID()].front() + memSpec->t32AW); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else + { + reportFatal("CheckerGDDR5", "Unknown command!"); + } + + return (earliestTimeToStart - sc_time_stamp()); +} + +void CheckerGDDR5::insert(Command command, Rank rank, BankGroup bankgroup, Bank bank) +{ + PRINTDEBUGMESSAGE("CheckerGDDR5", "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(); + lastCommandOnBus = sc_time_stamp(); + + if (command == Command::ACT || command == Command::REFB) + { + if (last4Activates[rank.ID()].size() == 4) + last4Activates[rank.ID()].pop(); + last4Activates[rank.ID()].push(lastCommandOnBus); + + if (last32Activates[rank.ID()].size() == 32) + last32Activates[rank.ID()].pop(); + last32Activates[rank.ID()].push(lastCommandOnBus); + } + + if (command == Command::REFB) + bankwiseRefreshCounter = (bankwiseRefreshCounter + 1) % memSpec->BanksPerRank; +} diff --git a/DRAMSys/library/src/controller/checker/CheckerGDDR5.h b/DRAMSys/library/src/controller/checker/CheckerGDDR5.h new file mode 100644 index 00000000..a17b7c28 --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerGDDR5.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#ifndef CHECKERGDDR5_H +#define CHECKERGDDR5_H + +#include "CheckerIF.h" +#include +#include +#include "../../configuration/memspec/MemSpecGDDR5.h" +#include "../../configuration/Configuration.h" + +class CheckerGDDR5 final : public CheckerIF +{ +public: + CheckerGDDR5(); + virtual sc_time delayToSatisfyConstraints(Command, Rank, BankGroup, Bank) const override; + virtual void insert(Command, Rank, BankGroup, Bank) override; + +private: + const MemSpecGDDR5 *memSpec; + + std::vector> lastScheduledByCommandAndBank; + std::vector> lastScheduledByCommandAndBankGroup; + std::vector> lastScheduledByCommandAndRank; + std::vector lastScheduledByCommand; + sc_time lastCommandOnBus; + + // 4 and 32 activate window + std::vector> last4Activates; + std::vector> last32Activates; + + sc_time burstClocks; + + unsigned bankwiseRefreshCounter = 0; +}; + +#endif // CHECKERGDDR5_H diff --git a/DRAMSys/library/src/controller/checker/CheckerGDDR5X.cpp b/DRAMSys/library/src/controller/checker/CheckerGDDR5X.cpp new file mode 100644 index 00000000..fbc3cbaa --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerGDDR5X.cpp @@ -0,0 +1,394 @@ +/* + * 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 "CheckerGDDR5X.h" + +CheckerGDDR5X::CheckerGDDR5X() +{ + Configuration &config = Configuration::getInstance(); + memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("CheckerGDDR5X", "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); + last32Activates = std::vector>(memSpec->NumberOfRanks); + + burstClocks = (memSpec->BurstLength / memSpec->DataRate) * memSpec->clk; +} + +sc_time CheckerGDDR5X::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::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->tRRDL); + + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDS); + + 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 = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + + lastCommandStart = lastScheduledByCommandAndBank[Command::REFB][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCPB); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD); + + if (last4Activates[rank.ID()].size() == 4) + earliestTimeToStart = std::max(earliestTimeToStart, last4Activates[rank.ID()].front() + memSpec->tFAW); + + if (last32Activates[rank.ID()].size() == 32) + earliestTimeToStart = std::max(earliestTimeToStart, last32Activates[rank.ID()].front() + memSpec->t32AW); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::RD) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDRD); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRL); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRL); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRS); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDRD); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + std::max(memSpec->tWR - memSpec->tRTP, memSpec->tWTRL)); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRL); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRL); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRS); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::WR || command == Command::WRA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDWR); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + 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); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::PREA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::REFA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::REFB) + { + 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->tRRDL); + + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDS); + + 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::REFB][bank.ID()]; +// if (lastCommandStart != SC_ZERO_TIME) +// earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCSB); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + { + if (bankwiseRefreshCounter == 0) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCPB); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD); + } + + if (last4Activates[rank.ID()].size() == 4) + earliestTimeToStart = std::max(earliestTimeToStart, last4Activates[rank.ID()].front() + memSpec->tFAW); + + if (last32Activates[rank.ID()].size() == 32) + earliestTimeToStart = std::max(earliestTimeToStart, last32Activates[rank.ID()].front() + memSpec->t32AW); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else + { + reportFatal("CheckerGDDR5X", "Unknown command!"); + } + + return (earliestTimeToStart - sc_time_stamp()); +} + +void CheckerGDDR5X::insert(Command command, Rank rank, BankGroup bankgroup, Bank bank) +{ + PRINTDEBUGMESSAGE("CheckerGDDR5X", "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(); + lastCommandOnBus = sc_time_stamp(); + + if (command == Command::ACT || command == Command::REFB) + { + if (last4Activates[rank.ID()].size() == 4) + last4Activates[rank.ID()].pop(); + last4Activates[rank.ID()].push(lastCommandOnBus); + + if (last32Activates[rank.ID()].size() == 32) + last32Activates[rank.ID()].pop(); + last32Activates[rank.ID()].push(lastCommandOnBus); + } + + if (command == Command::REFB) + bankwiseRefreshCounter = (bankwiseRefreshCounter + 1) % memSpec->BanksPerRank; +} diff --git a/DRAMSys/library/src/controller/checker/CheckerGDDR5X.h b/DRAMSys/library/src/controller/checker/CheckerGDDR5X.h new file mode 100644 index 00000000..355ca555 --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerGDDR5X.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2019, University of Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#ifndef CHECKERGDDR5X_H +#define CHECKERGDDR5X_H + +#include "CheckerIF.h" +#include +#include +#include "../../configuration/memspec/MemSpecGDDR5X.h" +#include "../../configuration/Configuration.h" + +class CheckerGDDR5X final : public CheckerIF +{ +public: + CheckerGDDR5X(); + virtual sc_time delayToSatisfyConstraints(Command, Rank, BankGroup, Bank) const override; + virtual void insert(Command, Rank, BankGroup, Bank) override; + +private: + const MemSpecGDDR5X *memSpec; + + std::vector> lastScheduledByCommandAndBank; + std::vector> lastScheduledByCommandAndBankGroup; + std::vector> lastScheduledByCommandAndRank; + std::vector lastScheduledByCommand; + sc_time lastCommandOnBus; + + // 4 and 32 activate window + std::vector> last4Activates; + std::vector> last32Activates; + + sc_time burstClocks; + + unsigned bankwiseRefreshCounter = 0; +}; + +#endif // CHECKERGDDR5X_H diff --git a/DRAMSys/library/src/controller/checker/CheckerGDDR6.cpp b/DRAMSys/library/src/controller/checker/CheckerGDDR6.cpp new file mode 100644 index 00000000..f5aebd85 --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerGDDR6.cpp @@ -0,0 +1,383 @@ +/* + * 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 "CheckerGDDR6.h" + +CheckerGDDR6::CheckerGDDR6() +{ + Configuration &config = Configuration::getInstance(); + memSpec = dynamic_cast(config.memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("CheckerGDDR6", "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()); + + lastActivates = std::vector>(memSpec->NumberOfRanks); + + burstClocks = (memSpec->BurstLength / memSpec->DataRate) * memSpec->clk; +} + +sc_time CheckerGDDR6::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::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->tRRDL); + + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDS); + + 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 = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + + lastCommandStart = lastScheduledByCommandAndBank[Command::REFB][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCPB); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD); + + if (lastActivates[rank.ID()].size() == 4) + earliestTimeToStart = std::max(earliestTimeToStart, lastActivates[rank.ID()].front() + memSpec->tFAW); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::RD) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDRD); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRL); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRL); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRS); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDRD); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + std::max(memSpec->tWR - memSpec->tRTP, memSpec->tWTRL)); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRL); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRL); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWTRS); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::WR || command == Command::WRA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDWR); + + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + 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); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::PREA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::REFA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + + memSpec->tWL + burstClocks + memSpec->tWR + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else if (command == Command::REFB) + { + 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->tRRDL); + + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDS); + + 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::REFB][bank.ID()]; +// if (lastCommandStart != SC_ZERO_TIME) +// earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCSB); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()]; + if (lastCommandStart != SC_ZERO_TIME) + { + if (bankwiseRefreshCounter == 0) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCPB); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD); + } + + if (lastActivates[rank.ID()].size() == 4) + earliestTimeToStart = std::max(earliestTimeToStart, lastActivates[rank.ID()].front() + memSpec->tFAW); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk); + } + else + { + reportFatal("CheckerGDDR6", "Unknown command!"); + } + + return (earliestTimeToStart - sc_time_stamp()); +} + +void CheckerGDDR6::insert(Command command, Rank rank, BankGroup bankgroup, Bank bank) +{ + PRINTDEBUGMESSAGE("CheckerGDDR6", "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(); + lastCommandOnBus = sc_time_stamp(); + + if (command == Command::ACT || command == Command::REFB) + { + if (lastActivates[rank.ID()].size() == 4) + lastActivates[rank.ID()].pop(); + lastActivates[rank.ID()].push(lastCommandOnBus); + } + + if (command == Command::REFB) + bankwiseRefreshCounter = (bankwiseRefreshCounter + 1) % memSpec->BanksPerRank; +} diff --git a/DRAMSys/library/src/controller/checker/CheckerGDDR6.h b/DRAMSys/library/src/controller/checker/CheckerGDDR6.h new file mode 100644 index 00000000..f61007e6 --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerGDDR6.h @@ -0,0 +1,68 @@ +/* + * 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 CHECKERGDDR6_H +#define CHECKERGDDR6_H + +#include "CheckerIF.h" +#include +#include +#include "../../configuration/memspec/MemSpecGDDR6.h" +#include "../../configuration/Configuration.h" + +class CheckerGDDR6 final : public CheckerIF +{ +public: + CheckerGDDR6(); + virtual sc_time delayToSatisfyConstraints(Command, Rank, BankGroup, Bank) const override; + virtual void insert(Command, Rank, BankGroup, Bank) override; + +private: + const MemSpecGDDR6 *memSpec; + + std::vector> lastScheduledByCommandAndBank; + std::vector> lastScheduledByCommandAndBankGroup; + std::vector> lastScheduledByCommandAndRank; + std::vector lastScheduledByCommand; + sc_time lastCommandOnBus; + + // four activate window + std::vector> lastActivates; + + sc_time burstClocks; + + unsigned bankwiseRefreshCounter = 0; +}; + +#endif // CHECKERGDDR6_H diff --git a/DRAMSys/library/src/controller/checker/CheckerHBM2.h b/DRAMSys/library/src/controller/checker/CheckerHBM2.h index d4e2d0ef..31769bb9 100644 --- a/DRAMSys/library/src/controller/checker/CheckerHBM2.h +++ b/DRAMSys/library/src/controller/checker/CheckerHBM2.h @@ -64,9 +64,6 @@ private: sc_time burstClocks; unsigned bankwiseRefreshCounter = 0; - - // PowerDown TODO: Implement this method? - //sc_time getTimeConstraintToEnterPowerDown(Command lastCmd, Command pdnCmd) const; }; #endif // CHECKERHBM2_H diff --git a/DRAMSys/library/src/controller/checker/CheckerIF.h b/DRAMSys/library/src/controller/checker/CheckerIF.h index 2fe47f2a..64e43f5a 100644 --- a/DRAMSys/library/src/controller/checker/CheckerIF.h +++ b/DRAMSys/library/src/controller/checker/CheckerIF.h @@ -48,9 +48,6 @@ public: virtual sc_time delayToSatisfyConstraints(Command, Rank, BankGroup, Bank) const = 0; virtual void insert(Command, Rank, BankGroup, Bank) = 0; - - // PowerDown TODO: Implement this method? - //sc_time getTimeConstraintToEnterPowerDown(Command lastCmd, Command pdnCmd) const; }; #endif // CHECKERIF_H diff --git a/DRAMSys/library/src/controller/checker/CheckerLPDDR4.h b/DRAMSys/library/src/controller/checker/CheckerLPDDR4.h index b925b9e4..fbadc16e 100644 --- a/DRAMSys/library/src/controller/checker/CheckerLPDDR4.h +++ b/DRAMSys/library/src/controller/checker/CheckerLPDDR4.h @@ -58,9 +58,6 @@ private: // Four activate window std::vector> lastActivates; - - // PowerDown TODO: Implement this method? - //sc_time getTimeConstraintToEnterPowerDown(Command lastCmd, Command pdnCmd) const; }; #endif // CHECKERLPDDR4_H diff --git a/DRAMSys/library/src/controller/checker/CheckerWideIO.h b/DRAMSys/library/src/controller/checker/CheckerWideIO.h index 9c0aa038..6bcc0796 100644 --- a/DRAMSys/library/src/controller/checker/CheckerWideIO.h +++ b/DRAMSys/library/src/controller/checker/CheckerWideIO.h @@ -60,9 +60,6 @@ private: std::vector> lastActivates; sc_time burstClocks; - - // PowerDown TODO: Implement this method? - //sc_time getTimeConstraintToEnterPowerDown(Command lastCmd, Command pdnCmd) const; }; #endif // CHECKERWIDEIO_H diff --git a/DRAMSys/library/src/controller/checker/CheckerWideIO2.h b/DRAMSys/library/src/controller/checker/CheckerWideIO2.h index a909fb59..7c27933d 100644 --- a/DRAMSys/library/src/controller/checker/CheckerWideIO2.h +++ b/DRAMSys/library/src/controller/checker/CheckerWideIO2.h @@ -58,9 +58,6 @@ private: // Four activate window std::vector> lastActivates; - - // PowerDown TODO: Implement this method? - //sc_time getTimeConstraintToEnterPowerDown(Command lastCmd, Command pdnCmd) const; }; #endif // CHECKERWIDEIO2_H diff --git a/DRAMSys/library/src/simulation/DRAMSys.cpp b/DRAMSys/library/src/simulation/DRAMSys.cpp index b67309e4..f348eaa4 100644 --- a/DRAMSys/library/src/simulation/DRAMSys.cpp +++ b/DRAMSys/library/src/simulation/DRAMSys.cpp @@ -59,6 +59,9 @@ #include "dram/DramLPDDR4.h" #include "dram/DramWideIO2.h" #include "dram/DramHBM2.h" +#include "dram/DramGDDR5.h" +#include "dram/DramGDDR5X.h" +#include "dram/DramGDDR6.h" #include "../controller/Controller.h" #include "../controller/ControllerRecordable.h" @@ -306,6 +309,27 @@ void DRAMSys::instantiateModules(const string &traceName, else dram = new DramHBM2(str.c_str()); } + else if (memoryType == "GDDR5") + { + if (recordingEnabled) + dram = new DramRecordable(str.c_str(), tlmRecorders[i]); + else + dram = new DramGDDR5(str.c_str()); + } + else if (memoryType == "GDDR5X") + { + if (recordingEnabled) + dram = new DramRecordable(str.c_str(), tlmRecorders[i]); + else + dram = new DramGDDR5X(str.c_str()); + } + else if (memoryType == "GDDR6") + { + if (recordingEnabled) + dram = new DramRecordable(str.c_str(), tlmRecorders[i]); + else + dram = new DramGDDR6(str.c_str()); + } else { SC_REPORT_FATAL("DRAMSys", "Unsupported DRAM type"); diff --git a/DRAMSys/library/src/simulation/dram/DramDDR3.h b/DRAMSys/library/src/simulation/dram/DramDDR3.h index 1a51c471..1c1a9ffe 100644 --- a/DRAMSys/library/src/simulation/dram/DramDDR3.h +++ b/DRAMSys/library/src/simulation/dram/DramDDR3.h @@ -37,7 +37,6 @@ #define DRAMDDR3_H #include -#include #include "Dram.h" class DramDDR3 : public Dram diff --git a/DRAMSys/library/src/simulation/dram/DramDDR4.h b/DRAMSys/library/src/simulation/dram/DramDDR4.h index 9bf17bd7..bb901591 100644 --- a/DRAMSys/library/src/simulation/dram/DramDDR4.h +++ b/DRAMSys/library/src/simulation/dram/DramDDR4.h @@ -37,7 +37,6 @@ #define DRAMDDR4_H #include -#include #include "Dram.h" class DramDDR4 : public Dram diff --git a/DRAMSys/library/src/simulation/dram/DramGDDR5.cpp b/DRAMSys/library/src/simulation/dram/DramGDDR5.cpp new file mode 100644 index 00000000..3e580346 --- /dev/null +++ b/DRAMSys/library/src/simulation/dram/DramGDDR5.cpp @@ -0,0 +1,57 @@ +/* + * 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. + * + * Authors: + * Lukas Steiner + */ + +#include "DramGDDR5.h" + +#include "Dram.h" +#include "../../configuration/Configuration.h" +#include "../../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h" +#include "../../configuration/memspec/MemSpecGDDR5.h" + +DramGDDR5::DramGDDR5(sc_module_name name) : Dram(name) +{ + if (StoreMode == StorageMode::ErrorModel) + SC_REPORT_FATAL("DramGDDR5", "Error Model not supported for GDDR5"); + + // Parameters for DRAMPower + MemSpecGDDR5 *memSpec = dynamic_cast(this->memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("DramGDDR5", "Wrong MemSpec chosen"); + + if (Configuration::getInstance().PowerAnalysis) + SC_REPORT_FATAL("DramGDDR5", "DRAMPower not supported for GDDR5"); + else + DRAMPower = new libDRAMPowerDummy(); +} diff --git a/DRAMSys/library/src/simulation/dram/DramGDDR5.h b/DRAMSys/library/src/simulation/dram/DramGDDR5.h new file mode 100644 index 00000000..e35bc380 --- /dev/null +++ b/DRAMSys/library/src/simulation/dram/DramGDDR5.h @@ -0,0 +1,50 @@ +/* + * 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. + * + * Authors: + * Lukas Steiner + */ + +#ifndef DRAMGDDR5_H +#define DRAMGDDR5_H + +#include +#include "Dram.h" + +class DramGDDR5 : public Dram +{ +public: + DramGDDR5(sc_module_name); + SC_HAS_PROCESS(DramGDDR5); + virtual ~DramGDDR5() {} +}; + +#endif // DRAMGDDR5_H diff --git a/DRAMSys/library/src/simulation/dram/DramGDDR5X.cpp b/DRAMSys/library/src/simulation/dram/DramGDDR5X.cpp new file mode 100644 index 00000000..a3f492e7 --- /dev/null +++ b/DRAMSys/library/src/simulation/dram/DramGDDR5X.cpp @@ -0,0 +1,57 @@ +/* + * 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. + * + * Authors: + * Lukas Steiner + */ + +#include "DramGDDR5X.h" + +#include "Dram.h" +#include "../../configuration/Configuration.h" +#include "../../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h" +#include "../../configuration/memspec/MemSpecGDDR5X.h" + +DramGDDR5X::DramGDDR5X(sc_module_name name) : Dram(name) +{ + if (StoreMode == StorageMode::ErrorModel) + SC_REPORT_FATAL("DramGDDR5X", "Error Model not supported for GDDR5X"); + + // Parameters for DRAMPower + MemSpecGDDR5X *memSpec = dynamic_cast(this->memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("DramGDDR5X", "Wrong MemSpec chosen"); + + if (Configuration::getInstance().PowerAnalysis) + SC_REPORT_FATAL("DramGDDR5X", "DRAMPower not supported for GDDR5X"); + else + DRAMPower = new libDRAMPowerDummy(); +} diff --git a/DRAMSys/library/src/simulation/dram/DramGDDR5X.h b/DRAMSys/library/src/simulation/dram/DramGDDR5X.h new file mode 100644 index 00000000..dedf1f8d --- /dev/null +++ b/DRAMSys/library/src/simulation/dram/DramGDDR5X.h @@ -0,0 +1,50 @@ +/* + * 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. + * + * Authors: + * Lukas Steiner + */ + +#ifndef DRAMGDDR5X_H +#define DRAMGDDR5X_H + +#include +#include "Dram.h" + +class DramGDDR5X : public Dram +{ +public: + DramGDDR5X(sc_module_name); + SC_HAS_PROCESS(DramGDDR5X); + virtual ~DramGDDR5X() {} +}; + +#endif // DRAMGDDR5X_H diff --git a/DRAMSys/library/src/simulation/dram/DramGDDR6.cpp b/DRAMSys/library/src/simulation/dram/DramGDDR6.cpp new file mode 100644 index 00000000..8260db52 --- /dev/null +++ b/DRAMSys/library/src/simulation/dram/DramGDDR6.cpp @@ -0,0 +1,57 @@ +/* + * 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. + * + * Authors: + * Lukas Steiner + */ + +#include "DramGDDR6.h" + +#include "Dram.h" +#include "../../configuration/Configuration.h" +#include "../../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h" +#include "../../configuration/memspec/MemSpecGDDR6.h" + +DramGDDR6::DramGDDR6(sc_module_name name) : Dram(name) +{ + if (StoreMode == StorageMode::ErrorModel) + SC_REPORT_FATAL("DramGDDR6", "Error Model not supported for GDDR6"); + + // Parameters for DRAMPower + MemSpecGDDR6 *memSpec = dynamic_cast(this->memSpec); + if (memSpec == nullptr) + SC_REPORT_FATAL("DramGDDR6", "Wrong MemSpec chosen"); + + if (Configuration::getInstance().PowerAnalysis) + SC_REPORT_FATAL("DramGDDR6", "DRAMPower not supported for GDDR6"); + else + DRAMPower = new libDRAMPowerDummy(); +} diff --git a/DRAMSys/library/src/simulation/dram/DramGDDR6.h b/DRAMSys/library/src/simulation/dram/DramGDDR6.h new file mode 100644 index 00000000..07f586c2 --- /dev/null +++ b/DRAMSys/library/src/simulation/dram/DramGDDR6.h @@ -0,0 +1,51 @@ +/* + * 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. + * + * Authors: + * Lukas Steiner + */ + +#ifndef DRAMGDDR6_H +#define DRAMGDDR6_H + +#include +#include "Dram.h" + +class DramGDDR6 : public Dram +{ +public: + DramGDDR6(sc_module_name); + SC_HAS_PROCESS(DramGDDR6); + virtual ~DramGDDR6() {} +}; + + +#endif // DRAMGDDR6_H diff --git a/DRAMSys/library/src/simulation/dram/DramHBM2.cpp b/DRAMSys/library/src/simulation/dram/DramHBM2.cpp index cea6f476..3ee73ea0 100644 --- a/DRAMSys/library/src/simulation/dram/DramHBM2.cpp +++ b/DRAMSys/library/src/simulation/dram/DramHBM2.cpp @@ -51,9 +51,7 @@ DramHBM2::DramHBM2(sc_module_name name) : Dram(name) SC_REPORT_FATAL("DramHBM2", "Wrong MemSpec chosen"); if (Configuration::getInstance().PowerAnalysis) - { SC_REPORT_FATAL("DramHBM2", "DRAMPower not supported for HBM2"); - } else DRAMPower = new libDRAMPowerDummy(); } diff --git a/DRAMSys/library/src/simulation/dram/DramHBM2.h b/DRAMSys/library/src/simulation/dram/DramHBM2.h index 84cb5d0b..0b2861fa 100644 --- a/DRAMSys/library/src/simulation/dram/DramHBM2.h +++ b/DRAMSys/library/src/simulation/dram/DramHBM2.h @@ -37,11 +37,8 @@ #define DRAMHBM2_H #include -#include #include "Dram.h" -using namespace tlm; - class DramHBM2 : public Dram { public: diff --git a/DRAMSys/library/src/simulation/dram/DramLPDDR4.cpp b/DRAMSys/library/src/simulation/dram/DramLPDDR4.cpp index 4b0a9251..38df1da5 100644 --- a/DRAMSys/library/src/simulation/dram/DramLPDDR4.cpp +++ b/DRAMSys/library/src/simulation/dram/DramLPDDR4.cpp @@ -35,6 +35,9 @@ #include "DramLPDDR4.h" +#include "Dram.h" +#include "../../configuration/Configuration.h" +#include "../../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h" #include "../../configuration/memspec/MemSpecLPDDR4.h" DramLPDDR4::DramLPDDR4(sc_module_name name) : Dram(name) @@ -48,9 +51,7 @@ DramLPDDR4::DramLPDDR4(sc_module_name name) : Dram(name) SC_REPORT_FATAL("DramLPDDR4", "Wrong MemSpec chosen"); if (Configuration::getInstance().PowerAnalysis) - { SC_REPORT_FATAL("DramLPDDR4", "DRAMPower not supported for LPDDR4"); - } else DRAMPower = new libDRAMPowerDummy(); } diff --git a/DRAMSys/library/src/simulation/dram/DramLPDDR4.h b/DRAMSys/library/src/simulation/dram/DramLPDDR4.h index c63561b2..31271928 100644 --- a/DRAMSys/library/src/simulation/dram/DramLPDDR4.h +++ b/DRAMSys/library/src/simulation/dram/DramLPDDR4.h @@ -37,7 +37,6 @@ #define DRAMLPDDR4_H #include -#include #include "Dram.h" class DramLPDDR4 : public Dram diff --git a/DRAMSys/library/src/simulation/dram/DramRecordable.cpp b/DRAMSys/library/src/simulation/dram/DramRecordable.cpp index f52ee002..97c03e38 100644 --- a/DRAMSys/library/src/simulation/dram/DramRecordable.cpp +++ b/DRAMSys/library/src/simulation/dram/DramRecordable.cpp @@ -45,6 +45,9 @@ #include "DramLPDDR4.h" #include "DramWideIO2.h" #include "DramHBM2.h" +#include "DramGDDR5.h" +#include "DramGDDR5X.h" +#include "DramGDDR6.h" using namespace tlm; @@ -149,4 +152,7 @@ template class DramRecordable; template class DramRecordable; template class DramRecordable; template class DramRecordable; +template class DramRecordable; +template class DramRecordable; +template class DramRecordable; diff --git a/DRAMSys/library/src/simulation/dram/DramWideIO2.cpp b/DRAMSys/library/src/simulation/dram/DramWideIO2.cpp index 65299da3..dde791fa 100644 --- a/DRAMSys/library/src/simulation/dram/DramWideIO2.cpp +++ b/DRAMSys/library/src/simulation/dram/DramWideIO2.cpp @@ -51,9 +51,7 @@ DramWideIO2::DramWideIO2(sc_module_name name) : Dram(name) SC_REPORT_FATAL("DramWideIO2", "Wrong MemSpec chosen"); if (Configuration::getInstance().PowerAnalysis) - { SC_REPORT_FATAL("DramWideIO2", "DRAMPower not supported for WideIO2"); - } else DRAMPower = new libDRAMPowerDummy(); } diff --git a/DRAMSys/library/src/simulation/dram/DramWideIO2.h b/DRAMSys/library/src/simulation/dram/DramWideIO2.h index 674af83c..d51f7e4f 100644 --- a/DRAMSys/library/src/simulation/dram/DramWideIO2.h +++ b/DRAMSys/library/src/simulation/dram/DramWideIO2.h @@ -37,11 +37,8 @@ #define DRAMWIDEIO2_H #include -#include #include "Dram.h" -using namespace tlm; - class DramWideIO2 : public Dram { public: