From a3b073836497b48d2a5db9cfa21bb36c226b17bd Mon Sep 17 00:00:00 2001 From: Derek Christ Date: Wed, 20 Apr 2022 11:21:21 +0200 Subject: [PATCH] Add skeleton for HBM3 implementation --- DRAMSys/library/CMakeLists.txt | 7 + .../configs/amconfigs/am_hbm3_8Gb_pc_brc.json | 46 ++ .../resources/configs/memspecs/HBM3.json | 61 ++ .../resources/configs/simulator/hbm3.json | 19 + .../resources/simulations/hbm3-example.json | 16 + DRAMSys/library/src/common/TlmRecorder.cpp | 15 +- .../src/configuration/Configuration.cpp | 3 + .../src/configuration/memspec/MemSpec.h | 2 +- .../src/configuration/memspec/MemSpecHBM3.cpp | 168 ++++++ .../src/configuration/memspec/MemSpecHBM3.h | 93 +++ DRAMSys/library/src/controller/Controller.cpp | 3 + .../src/controller/checker/CheckerHBM3.cpp | 549 ++++++++++++++++++ .../src/controller/checker/CheckerHBM3.h | 79 +++ DRAMSys/library/src/simulation/DRAMSys.cpp | 4 + .../src/simulation/DRAMSysRecordable.cpp | 4 + .../library/src/simulation/dram/DramHBM3.cpp | 52 ++ .../library/src/simulation/dram/DramHBM3.h | 52 ++ .../src/simulation/dram/DramRecordable.cpp | 2 + 18 files changed, 1163 insertions(+), 12 deletions(-) create mode 100644 DRAMSys/library/resources/configs/amconfigs/am_hbm3_8Gb_pc_brc.json create mode 100644 DRAMSys/library/resources/configs/memspecs/HBM3.json create mode 100644 DRAMSys/library/resources/configs/simulator/hbm3.json create mode 100644 DRAMSys/library/resources/simulations/hbm3-example.json create mode 100644 DRAMSys/library/src/configuration/memspec/MemSpecHBM3.cpp create mode 100644 DRAMSys/library/src/configuration/memspec/MemSpecHBM3.h create mode 100644 DRAMSys/library/src/controller/checker/CheckerHBM3.cpp create mode 100644 DRAMSys/library/src/controller/checker/CheckerHBM3.h create mode 100644 DRAMSys/library/src/simulation/dram/DramHBM3.cpp create mode 100644 DRAMSys/library/src/simulation/dram/DramHBM3.h diff --git a/DRAMSys/library/CMakeLists.txt b/DRAMSys/library/CMakeLists.txt index 44a42618..1042eff9 100644 --- a/DRAMSys/library/CMakeLists.txt +++ b/DRAMSys/library/CMakeLists.txt @@ -98,6 +98,7 @@ add_library(DRAMSysLibrary src/configuration/memspec/MemSpecGDDR5X.cpp src/configuration/memspec/MemSpecGDDR6.cpp src/configuration/memspec/MemSpecHBM2.cpp + src/configuration/memspec/MemSpecHBM3.cpp src/configuration/memspec/MemSpecSTTMRAM.cpp src/controller/BankMachine.cpp @@ -117,6 +118,7 @@ add_library(DRAMSysLibrary src/controller/checker/CheckerGDDR5X.cpp src/controller/checker/CheckerGDDR6.cpp src/controller/checker/CheckerHBM2.cpp + src/controller/checker/CheckerHBM3.cpp src/controller/checker/CheckerSTTMRAM.cpp src/controller/cmdmux/CmdMuxIF.h @@ -176,6 +178,7 @@ add_library(DRAMSysLibrary src/simulation/dram/DramGDDR5X.cpp src/simulation/dram/DramGDDR6.cpp src/simulation/dram/DramHBM2.cpp + src/simulation/dram/DramHBM3.cpp src/simulation/dram/DramSTTMRAM.cpp ${RECORDING_SOURCES} @@ -187,6 +190,7 @@ add_library(DRAMSysLibrary resources/simulations/ddr3-gem5-se.json resources/simulations/ddr4-example.json resources/simulations/hbm2-example.json + resources/simulations/hbm3-example.json resources/simulations/lpddr4-example.json resources/simulations/ranktest.json resources/simulations/wideio-example.json @@ -203,6 +207,7 @@ add_library(DRAMSysLibrary resources/configs/amconfigs/am_ddr3_x16_rbc.json resources/configs/amconfigs/am_ddr4_8x4Gbx8_dimm_p1KB_brc.json resources/configs/amconfigs/am_hbm2_8Gb_pc_brc.json + resources/configs/amconfigs/am_hbm3_8Gb_pc_brc.json resources/configs/amconfigs/am_lpddr4_8Gbx16_brc.json resources/configs/amconfigs/am_ranktest.json resources/configs/amconfigs/am_wideio2_4x64_4x2Gb_brc.json @@ -226,6 +231,7 @@ add_library(DRAMSysLibrary # Memspec Config Files resources/configs/memspecs/HBM2.json + resources/configs/memspecs/HBM3.json resources/configs/memspecs/JEDEC_256Mb_WIDEIO-200_128bit.json resources/configs/memspecs/JEDEC_256Mb_WIDEIO-266_128bit.json resources/configs/memspecs/JEDEC_4Gb_DDR4-1866_8bit_A.json @@ -280,6 +286,7 @@ add_library(DRAMSysLibrary resources/configs/simulator/ddr3_gem5_se.json resources/configs/simulator/ddr4.json resources/configs/simulator/hbm2.json + resources/configs/simulator/hbm3.json resources/configs/simulator/lpddr4.json resources/configs/simulator/wideio.json resources/configs/simulator/wideio_thermal.json diff --git a/DRAMSys/library/resources/configs/amconfigs/am_hbm3_8Gb_pc_brc.json b/DRAMSys/library/resources/configs/amconfigs/am_hbm3_8Gb_pc_brc.json new file mode 100644 index 00000000..687e35d7 --- /dev/null +++ b/DRAMSys/library/resources/configs/amconfigs/am_hbm3_8Gb_pc_brc.json @@ -0,0 +1,46 @@ +{ + "CONGEN": { + "PSEUDOCHANNEL_BIT":[ + 29 + ], + "BANKGROUP_BIT":[ + 27, + 28 + ], + "BANK_BIT": [ + 25, + 26 + ], + "BYTE_BIT": [ + 0, + 1, + 2 + ], + "COLUMN_BIT": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ], + "ROW_BIT": [ + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24 + ] + } +} diff --git a/DRAMSys/library/resources/configs/memspecs/HBM3.json b/DRAMSys/library/resources/configs/memspecs/HBM3.json new file mode 100644 index 00000000..0d6b82b1 --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/HBM3.json @@ -0,0 +1,61 @@ +{ + "memspec": { + "memarchitecturespec": { + "burstLength": 8, + "dataRate": 2, + "nbrOfBankGroups": 4, + "nbrOfBanks": 16, + "nbrOfColumns": 128, + "nbrOfPseudoChannels": 2, + "nbrOfRows": 32768, + "width": 64, + "nbrOfDevices": 1, + "nbrOfChannels": 1 + }, + "memoryId": "", + "memoryType": "HBM3", + "memtimingspec": { + "CCDL": 4, + "CCDS": 2, + "CKE": 8, + "DQSCK": 1, + "FAW": 16, + "PL": 0, + "PPD": 2, + "RAS": 28, + "RC": 42, + "RCDRD": 12, + "RCDWR": 6, + "REFI": 3900, + "REFIPB": 244, + "RFC": 220, + "RFCPB": 96, + "RL": 17, + "RP": 14, + "RRDL": 6, + "RRDS": 4, + "RREFD": 8, + "RTP": 5, + "RTW": 18, + "WL": 7, + "WR": 14, + "WTRL": 9, + "WTRS": 4, + "XP": 8, + "XS": 216, + "clkMhz": 1600 + }, + "memtimingspec_comments": { + "CKE": "no entry in HBM3", + "DQSCK": "?", + "PL": "?", + "PPD": "added", + "REFIPB": "renamed from REFISB; value TODO", + "RFC": "TODO", + "RFCPB": "renamed from RFCSB to RFCPB; TODO", + "RL": "?", + "WL": "?", + "XS": "TODO (tRFC(min) + 10)" + } + } +} diff --git a/DRAMSys/library/resources/configs/simulator/hbm3.json b/DRAMSys/library/resources/configs/simulator/hbm3.json new file mode 100644 index 00000000..901dc498 --- /dev/null +++ b/DRAMSys/library/resources/configs/simulator/hbm3.json @@ -0,0 +1,19 @@ +{ + "simconfig": { + "AddressOffset": 0, + "CheckTLM2Protocol": false, + "DatabaseRecording": true, + "Debug": false, + "ECCControllerMode": "Disabled", + "EnableWindowing": false, + "ErrorCSVFile": "", + "ErrorChipSeed": 42, + "PowerAnalysis": false, + "SimulationName": "hbm3", + "SimulationProgressBar": true, + "StoreMode": "NoStorage", + "ThermalSimulation": false, + "UseMalloc": false, + "WindowSize": 1000 + } +} diff --git a/DRAMSys/library/resources/simulations/hbm3-example.json b/DRAMSys/library/resources/simulations/hbm3-example.json new file mode 100644 index 00000000..6f64aa04 --- /dev/null +++ b/DRAMSys/library/resources/simulations/hbm3-example.json @@ -0,0 +1,16 @@ +{ + "simulation": { + "addressmapping": "am_hbm3_8Gb_pc_brc.json", + "mcconfig": "fr_fcfs.json", + "memspec": "HBM3.json", + "simconfig": "hbm3.json", + "simulationid": "hbm3-example", + "thermalconfig": "config.json", + "tracesetup": [ + { + "clkMhz": 1000, + "name": "ddr3_example.stl" + } + ] + } +} diff --git a/DRAMSys/library/src/common/TlmRecorder.cpp b/DRAMSys/library/src/common/TlmRecorder.cpp index dd22ec4a..0878f7f6 100644 --- a/DRAMSys/library/src/common/TlmRecorder.cpp +++ b/DRAMSys/library/src/common/TlmRecorder.cpp @@ -367,21 +367,14 @@ void TlmRecorder::insertGeneralInfo() const MemSpec& memSpec = *config.memSpec; const auto memoryType = memSpec.memoryType; - bool rowColumnCommandBus = [memoryType]() -> bool { - if (memoryType == MemSpec::MemoryType::HBM2) - return true; - else - return false; - }(); + + bool rowColumnCommandBus = (memoryType == MemSpec::MemoryType::HBM2) || (memoryType == MemSpec::MemoryType::HBM3); bool pseudoChannelMode = [&memSpec, memoryType]() -> bool { - if (memoryType != MemSpec::MemoryType::HBM2) + if (memoryType != MemSpec::MemoryType::HBM2 && memoryType != MemSpec::MemoryType::HBM3) return false; - if (memSpec.pseudoChannelsPerChannel != 1) - return true; - else - return false; + return memSpec.pseudoChannelsPerChannel != 1; }(); sqlite3_bind_int(insertGeneralInfoStatement, 17, static_cast(rowColumnCommandBus)); diff --git a/DRAMSys/library/src/configuration/Configuration.cpp b/DRAMSys/library/src/configuration/Configuration.cpp index dd89f37d..a4532f6f 100644 --- a/DRAMSys/library/src/configuration/Configuration.cpp +++ b/DRAMSys/library/src/configuration/Configuration.cpp @@ -48,6 +48,7 @@ #include "memspec/MemSpecLPDDR5.h" #include "memspec/MemSpecWideIO2.h" #include "memspec/MemSpecHBM2.h" +#include "memspec/MemSpecHBM3.h" #include "memspec/MemSpecGDDR5.h" #include "memspec/MemSpecGDDR5X.h" #include "memspec/MemSpecGDDR6.h" @@ -337,6 +338,8 @@ void Configuration::loadMemSpec(const DRAMSysConfiguration::MemSpec &memSpecConf memSpec = std::make_unique(memSpecConfig); else if (memoryType == "HBM2") memSpec = std::make_unique(memSpecConfig); + else if (memoryType == "HBM3") + memSpec = std::make_unique(memSpecConfig); else if (memoryType == "GDDR5") memSpec = std::make_unique(memSpecConfig); else if (memoryType == "GDDR5X") diff --git a/DRAMSys/library/src/configuration/memspec/MemSpec.h b/DRAMSys/library/src/configuration/memspec/MemSpec.h index ac6fca08..911b0686 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpec.h +++ b/DRAMSys/library/src/configuration/memspec/MemSpec.h @@ -75,7 +75,7 @@ public: const std::string memoryId; const enum class MemoryType {DDR3, DDR4, DDR5, LPDDR4, LPDDR5, WideIO, - WideIO2, GDDR5, GDDR5X, GDDR6, HBM2, STTMRAM} memoryType; + WideIO2, GDDR5, GDDR5X, GDDR6, HBM2, HBM3, STTMRAM} memoryType; virtual ~MemSpec() = default; diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecHBM3.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecHBM3.cpp new file mode 100644 index 00000000..804388fb --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecHBM3.cpp @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2019, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + * Derek Christ + */ + +#include + +#include "../../common/utils.h" +#include "MemSpecHBM3.h" + +using namespace sc_core; +using namespace tlm; + +MemSpecHBM3::MemSpecHBM3(const DRAMSysConfiguration::MemSpec &memSpec) + : MemSpec(memSpec, MemoryType::HBM3, + memSpec.memArchitectureSpec.entries.at("nbrOfChannels"), + memSpec.memArchitectureSpec.entries.at("nbrOfPseudoChannels"), + memSpec.memArchitectureSpec.entries.at("nbrOfPseudoChannels"), + memSpec.memArchitectureSpec.entries.at("nbrOfBanks"), + memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"), + memSpec.memArchitectureSpec.entries.at("nbrOfBanks") + / memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups"), + memSpec.memArchitectureSpec.entries.at("nbrOfBanks") + * memSpec.memArchitectureSpec.entries.at("nbrOfPseudoChannels"), + memSpec.memArchitectureSpec.entries.at("nbrOfBankGroups") + * memSpec.memArchitectureSpec.entries.at("nbrOfPseudoChannels"), + memSpec.memArchitectureSpec.entries.at("nbrOfDevices")), + tDQSCK (tCK * memSpec.memTimingSpec.entries.at("DQSCK")), + tRC (tCK * memSpec.memTimingSpec.entries.at("RC")), + tRAS (tCK * memSpec.memTimingSpec.entries.at("RAS")), + tRCDRD (tCK * memSpec.memTimingSpec.entries.at("RCDRD")), + tRCDWR (tCK * memSpec.memTimingSpec.entries.at("RCDWR")), + tRRDL (tCK * memSpec.memTimingSpec.entries.at("RRDL")), + tRRDS (tCK * memSpec.memTimingSpec.entries.at("RRDS")), + tFAW (tCK * memSpec.memTimingSpec.entries.at("FAW")), + tRTP (tCK * memSpec.memTimingSpec.entries.at("RTP")), + tRP (tCK * memSpec.memTimingSpec.entries.at("RP")), + tRL (tCK * memSpec.memTimingSpec.entries.at("RL")), + tWL (tCK * memSpec.memTimingSpec.entries.at("WL")), + tPL (tCK * memSpec.memTimingSpec.entries.at("PL")), + tWR (tCK * memSpec.memTimingSpec.entries.at("WR")), + tCCDL (tCK * memSpec.memTimingSpec.entries.at("CCDL")), + tCCDS (tCK * memSpec.memTimingSpec.entries.at("CCDS")), + tWTRL (tCK * memSpec.memTimingSpec.entries.at("WTRL")), + tWTRS (tCK * memSpec.memTimingSpec.entries.at("WTRS")), + tRTW (tCK * memSpec.memTimingSpec.entries.at("RTW")), + tXP (tCK * memSpec.memTimingSpec.entries.at("XP")), + tCKE (tCK * memSpec.memTimingSpec.entries.at("CKE")), + tPD (tCKE), + tCKESR (tCKE + tCK), + tXS (tCK * memSpec.memTimingSpec.entries.at("XS")), + tRFC (tCK * memSpec.memTimingSpec.entries.at("RFC")), + tRFCPB (tCK * memSpec.memTimingSpec.entries.at("RFCPB")), + tRREFD (tCK * memSpec.memTimingSpec.entries.at("RREFD")), + tREFI (tCK * memSpec.memTimingSpec.entries.at("REFI")), + tREFIPB (tCK * memSpec.memTimingSpec.entries.at("REFIPB")) +{ + commandLengthInCycles[Command::ACT] = 2; // TODO 1.5 + + uint64_t deviceSizeBits = static_cast(banksPerRank) * rowsPerBank * columnsPerRow * bitWidth; + uint64_t deviceSizeBytes = deviceSizeBits / 8; + memorySizeBytes = deviceSizeBytes * ranksPerChannel * numberOfChannels; + + std::cout << headline << std::endl; + std::cout << "Memory Configuration:" << std::endl << std::endl; + std::cout << " Memory type: " << "HBM3" << std::endl; + std::cout << " Memory size in bytes: " << memorySizeBytes << std::endl; + std::cout << " Channels: " << numberOfChannels << std::endl; + std::cout << " Pseudo channels per channel: " << ranksPerChannel << std::endl; + std::cout << " Bank groups per pseudo channel: " << groupsPerRank << std::endl; + std::cout << " Banks per pseudo channel: " << banksPerRank << std::endl; + std::cout << " Rows per bank: " << rowsPerBank << std::endl; + std::cout << " Columns per row: " << columnsPerRow << std::endl; + std::cout << " Pseudo channel width in bits: " << bitWidth << std::endl; + std::cout << " Pseudo channel size in bits: " << deviceSizeBits << std::endl; + std::cout << " Pseudo channel size in bytes: " << deviceSizeBytes << std::endl; + std::cout << std::endl; +} + +sc_time MemSpecHBM3::getRefreshIntervalAB() const +{ + return tREFI; +} + +sc_time MemSpecHBM3::getRefreshIntervalPB() const +{ + return tREFIPB; +} + +bool MemSpecHBM3::hasRasAndCasBus() const +{ + return true; +} + +sc_time MemSpecHBM3::getExecutionTime(Command command, const tlm_generic_payload &payload) const +{ + if (command == Command::PREPB || command == Command::PREAB) + return tRP; + else if (command == Command::ACT) + { + if (payload.get_command() == TLM_READ_COMMAND) + return tRCDRD + tCK; + else + return tRCDWR + tCK; + } + else if (command == Command::RD) + return tRL + tDQSCK + burstDuration; + else if (command == Command::RDA) + return tRTP + tRP; + else if (command == Command::WR) + return tWL + burstDuration; + else if (command == Command::WRA) + return tWL + burstDuration + tWR + tRP; + else if (command == Command::REFAB) + return tRFC; + else if (command == Command::REFPB) + return tRFCPB; + else + { + SC_REPORT_FATAL("getExecutionTime", + "command not known or command doesn't have a fixed execution time"); + return SC_ZERO_TIME; + } +} + +TimeInterval MemSpecHBM3::getIntervalOnDataStrobe(Command command, const tlm_generic_payload &) const +{ + if (command == Command::RD || command == Command::RDA) + return {tRL + tDQSCK, tRL + tDQSCK + burstDuration}; + else if (command == Command::WR || command == Command::WRA) + return {tWL, tWL + burstDuration}; + else + { + SC_REPORT_FATAL("MemSpecHBM3", "Method was called with invalid argument"); + return {}; + } +} diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecHBM3.h b/DRAMSys/library/src/configuration/memspec/MemSpecHBM3.h new file mode 100644 index 00000000..57927851 --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecHBM3.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2019, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + * Derek Christ + */ + +#ifndef MemSpecHBM3_H +#define MemSpecHBM3_H + +#include +#include "MemSpec.h" + +class MemSpecHBM3 final : public MemSpec +{ +public: + explicit MemSpecHBM3(const DRAMSysConfiguration::MemSpec &memSpec); + + // Memspec Variables: + const sc_core::sc_time tDQSCK; +// sc_time tDQSQ; // TODO: check actual value of this parameter + const sc_core::sc_time tRC; + const sc_core::sc_time tRAS; + const sc_core::sc_time tRCDRD; + const sc_core::sc_time tRCDWR; + const sc_core::sc_time tRRDL; + const sc_core::sc_time tRRDS; + const sc_core::sc_time tFAW; + const sc_core::sc_time tRTP; + const sc_core::sc_time tRP; + const sc_core::sc_time tRL; + const sc_core::sc_time tWL; + const sc_core::sc_time tPL; + const sc_core::sc_time tWR; + const sc_core::sc_time tCCDL; + const sc_core::sc_time tCCDS; +// sc_time tCCDR; // TODO: consecutive reads to different stack IDs + const sc_core::sc_time tWTRL; + const sc_core::sc_time tWTRS; + const sc_core::sc_time tRTW; + const sc_core::sc_time tXP; + const sc_core::sc_time tCKE; + const sc_core::sc_time tPD; // = tCKE; + const sc_core::sc_time tCKESR; // = tCKE + tCK; + const sc_core::sc_time tXS; + const sc_core::sc_time tRFC; + const sc_core::sc_time tRFCPB; + const sc_core::sc_time tRREFD; + const sc_core::sc_time tREFI; + const sc_core::sc_time tREFIPB; + + // Currents and Voltages: + // TODO: to be completed + + sc_core::sc_time getRefreshIntervalAB() const override; + sc_core::sc_time getRefreshIntervalPB() const override; + + bool hasRasAndCasBus() const override; + + sc_core::sc_time getExecutionTime(Command command, const tlm::tlm_generic_payload &payload) const override; + TimeInterval getIntervalOnDataStrobe(Command command, const tlm::tlm_generic_payload &payload) const override; +}; + +#endif // MemSpecHBM3_H diff --git a/DRAMSys/library/src/controller/Controller.cpp b/DRAMSys/library/src/controller/Controller.cpp index b1afbdee..14d77a5a 100644 --- a/DRAMSys/library/src/controller/Controller.cpp +++ b/DRAMSys/library/src/controller/Controller.cpp @@ -45,6 +45,7 @@ #include "checker/CheckerLPDDR5.h" #include "checker/CheckerWideIO2.h" #include "checker/CheckerHBM2.h" +#include "checker/CheckerHBM3.h" #include "checker/CheckerGDDR5.h" #include "checker/CheckerGDDR5X.h" #include "checker/CheckerGDDR6.h" @@ -98,6 +99,8 @@ Controller::Controller(const sc_module_name& name, const Configuration& config) checker = std::make_unique(config); else if (memSpec.memoryType == MemSpec::MemoryType::HBM2) checker = std::make_unique(config); + else if (memSpec.memoryType == MemSpec::MemoryType::HBM3) + checker = std::make_unique(config); else if (memSpec.memoryType == MemSpec::MemoryType::GDDR5) checker = std::make_unique(config); else if (memSpec.memoryType == MemSpec::MemoryType::GDDR5X) diff --git a/DRAMSys/library/src/controller/checker/CheckerHBM3.cpp b/DRAMSys/library/src/controller/checker/CheckerHBM3.cpp new file mode 100644 index 00000000..aa2f47f0 --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerHBM3.cpp @@ -0,0 +1,549 @@ +/* + * Copyright (c) 2019, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#include + +#include "CheckerHBM3.h" + +using namespace sc_core; +using namespace tlm; + +CheckerHBM3::CheckerHBM3(const Configuration& config) +{ + memSpec = dynamic_cast(config.memSpec.get()); + if (memSpec == nullptr) + SC_REPORT_FATAL("CheckerHBM3", "Wrong MemSpec chosen"); + + lastScheduledByCommandAndBank = std::vector> + (Command::numberOfCommands(), std::vector(memSpec->banksPerChannel, sc_max_time())); + lastScheduledByCommandAndBankGroup = std::vector> + (Command::numberOfCommands(), std::vector(memSpec->bankGroupsPerChannel, sc_max_time())); + lastScheduledByCommandAndRank = std::vector> + (Command::numberOfCommands(), std::vector(memSpec->ranksPerChannel, sc_max_time())); + lastScheduledByCommand = std::vector(Command::numberOfCommands(), sc_max_time()); + lastCommandOnRasBus = sc_max_time(); + lastCommandOnCasBus = sc_max_time(); + last4Activates = std::vector>(memSpec->ranksPerChannel); + + bankwiseRefreshCounter = std::vector(memSpec->ranksPerChannel); + + tBURST = memSpec->defaultBurstLength / memSpec->dataRate * memSpec->tCK; + tRDPDE = memSpec->tRL + memSpec->tPL + tBURST + memSpec->tCK; + tRDSRE = tRDPDE; + tWRPRE = memSpec->tWL + tBURST + memSpec->tWR; + tWRPDE = memSpec->tWL + memSpec->tPL + tBURST + memSpec->tCK + memSpec->tWR; + tWRAPDE = memSpec->tWL + memSpec->tPL + tBURST + memSpec->tCK + memSpec->tWR; + tWRRDS = memSpec->tWL + tBURST + memSpec->tWTRS; + tWRRDL = memSpec->tWL + tBURST + memSpec->tWTRL; +} + +sc_time CheckerHBM3::timeToSatisfyConstraints(Command command, const tlm_generic_payload& payload) const +{ + Rank rank = DramExtension::getRank(payload); + BankGroup bankGroup = DramExtension::getBankGroup(payload); + Bank bank = DramExtension::getBank(payload); + + sc_time lastCommandStart; + sc_time earliestTimeToStart = sc_time_stamp(); + + if (command == Command::RD || command == Command::RDA) + { + unsigned burstLength = DramExtension::getBurstLength(payload); + assert(!(memSpec->ranksPerChannel == 1) || (burstLength == 2 || burstLength == 4)); // Legacy mode + // assert(!(memSpec->ranksPerChannel == 2) || (burstLength == 4)); // Pseudo-channel mode + + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDRD + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankGroup.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankGroup.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + if (command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE - memSpec->tRTP); + } + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankGroup.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRDL); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRDS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankGroup.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRDL); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRDS); + + lastCommandStart = lastScheduledByCommand[Command::PDXA]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnCasBus + memSpec->tCK); + } + else if (command == Command::WR || command == Command::WRA) + { + unsigned burstLength = DramExtension::getBurstLength(payload); + assert(!(memSpec->ranksPerChannel == 1) || (burstLength == 2)); // Legacy mode + // assert(!(memSpec->ranksPerChannel == 2) || (burstLength == 4)); // Pseudo-channel mode + + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDWR + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankGroup.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankGroup.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS); + + lastCommandStart = lastScheduledByCommand[Command::PDXA]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnCasBus + memSpec->tCK); + } + else if (command == Command::ACT) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::ACT][bankGroup.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDL); + + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDS); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP - memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + memSpec->tRP - memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBank[Command::PREPB][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP - memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREAB][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP - memSpec->tCK); + + lastCommandStart = lastScheduledByCommand[Command::PDXA]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP - memSpec->tCK); + + lastCommandStart = lastScheduledByCommand[Command::PDXP]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP - memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFAB][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC - memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBank[Command::REFPB][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCPB - memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFPB][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD - memSpec->tCK); + + lastCommandStart = lastScheduledByCommand[Command::SREFEX]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXS - memSpec->tCK); + + if (last4Activates[rank.ID()].size() >= 4) + earliestTimeToStart = std::max(earliestTimeToStart, last4Activates[rank.ID()].front() + memSpec->tFAW - memSpec->tCK); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnRasBus + memSpec->tCK); + } + else if (command == Command::PREPB) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RD][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE); + + lastCommandStart = lastScheduledByCommand[Command::PDXA]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnRasBus + memSpec->tCK); + } + else if (command == Command::PREAB) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE); + + lastCommandStart = lastScheduledByCommand[Command::PDXA]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFPB][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCPB); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnRasBus + memSpec->tCK); + } + else if (command == Command::REFAB) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREPB][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREAB][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommand[Command::PDXP]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFAB][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFPB][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCPB); + + lastCommandStart = lastScheduledByCommand[Command::SREFEX]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXS); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnRasBus + memSpec->tCK); + } + else if (command == Command::REFPB) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::ACT][bankGroup.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDL + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDS + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndBank[Command::PREPB][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREAB][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommand[Command::PDXA]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + lastCommandStart = lastScheduledByCommand[Command::PDXP]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFAB][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + + lastCommandStart = lastScheduledByCommandAndBank[Command::REFPB][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCPB); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFPB][rank.ID()]; + if (lastCommandStart != sc_max_time()) + { + if (bankwiseRefreshCounter[rank.ID()] == 0) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCPB); + else + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD); + } + + lastCommandStart = lastScheduledByCommand[Command::SREFEX]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXS); + + if (last4Activates[rank.ID()].size() >= 4) + earliestTimeToStart = std::max(earliestTimeToStart, last4Activates[rank.ID()].front() + memSpec->tFAW); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnRasBus + memSpec->tCK); + } + else if (command == Command::PDEA) + { + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDPDE); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDPDE); + + lastCommandStart = lastScheduledByCommand[Command::WR]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPDE); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRAPDE); + + lastCommandStart = lastScheduledByCommand[Command::PDXA]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCKE); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnRasBus + memSpec->tCK); + } + else if (command == Command::PDXA) + { + lastCommandStart = lastScheduledByCommand[Command::PDEA]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPD); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnRasBus + memSpec->tCK); + } + else if (command == Command::PDEP) + { + lastCommandStart = lastScheduledByCommand[Command::RD]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDPDE); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDPDE); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRAPDE); + + lastCommandStart = lastScheduledByCommand[Command::PDXP]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCKE); + + lastCommandStart = lastScheduledByCommand[Command::SREFEX]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXS); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnRasBus + memSpec->tCK); + } + else if (command == Command::PDXP) + { + lastCommandStart = lastScheduledByCommand[Command::PDEP]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPD); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnRasBus + memSpec->tCK); + } + else if (command == Command::SREFEN) + { + lastCommandStart = lastScheduledByCommand[Command::ACT]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC + memSpec->tCK); + + lastCommandStart = lastScheduledByCommand[Command::RDA]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + std::max(memSpec->tRTP + memSpec->tRP, tRDSRE)); + + lastCommandStart = lastScheduledByCommand[Command::WRA]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + memSpec->tRP); + + lastCommandStart = lastScheduledByCommand[Command::PREPB]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommand[Command::PREAB]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP); + + lastCommandStart = lastScheduledByCommand[Command::PDXP]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + lastCommandStart = lastScheduledByCommand[Command::REFAB]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + + lastCommandStart = lastScheduledByCommand[Command::REFPB]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCPB); + + lastCommandStart = lastScheduledByCommand[Command::SREFEX]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXS); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnRasBus + memSpec->tCK); + } + else if (command == Command::SREFEX) + { + lastCommandStart = lastScheduledByCommand[Command::SREFEN]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCKESR); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnRasBus + memSpec->tCK); + } + else + SC_REPORT_FATAL("CheckerHBM3", "Unknown command!"); + + if (command.isRasCommand()) + { + if (lastCommandOnRasBus != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnRasBus + memSpec->tCK); + } + else + { + if (lastCommandOnCasBus != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnCasBus + memSpec->tCK); + } + + return earliestTimeToStart; +} + +void CheckerHBM3::insert(Command command, const tlm_generic_payload& payload) +{ + Rank rank = DramExtension::getRank(payload); + BankGroup bankGroup = DramExtension::getBankGroup(payload); + Bank bank = DramExtension::getBank(payload); + + PRINTDEBUGMESSAGE("CheckerHBM3", "Changing state on bank " + std::to_string(bank.ID()) + + " command is " + command.toString()); + + 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(); + + if (command.isCasCommand()) + lastCommandOnCasBus = sc_time_stamp(); + else if (command == Command::ACT) + lastCommandOnRasBus = sc_time_stamp() + memSpec->tCK; + else + lastCommandOnRasBus = sc_time_stamp(); + + if (command == Command::ACT || command == Command::REFPB) + { + if (last4Activates[rank.ID()].size() == 4) + last4Activates[rank.ID()].pop(); + last4Activates[rank.ID()].push(lastCommandOnRasBus); + } + + if (command == Command::REFPB) + bankwiseRefreshCounter[rank.ID()] = (bankwiseRefreshCounter[rank.ID()] + 1) % memSpec->banksPerRank; +} diff --git a/DRAMSys/library/src/controller/checker/CheckerHBM3.h b/DRAMSys/library/src/controller/checker/CheckerHBM3.h new file mode 100644 index 00000000..0798fa01 --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerHBM3.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2019, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Lukas Steiner + */ + +#ifndef CHECKERHBM3_H +#define CHECKERHBM3_H + +#include +#include + +#include "CheckerIF.h" +#include "../../configuration/memspec/MemSpecHBM3.h" +#include "../../configuration/Configuration.h" + +class CheckerHBM3 final : public CheckerIF +{ +public: + explicit CheckerHBM3(const Configuration& config); + sc_core::sc_time timeToSatisfyConstraints(Command command, const tlm::tlm_generic_payload& payload) const override; + void insert(Command command, const tlm::tlm_generic_payload& payload) override; + +private: + const MemSpecHBM3 *memSpec; + + std::vector> lastScheduledByCommandAndBank; + std::vector> lastScheduledByCommandAndBankGroup; + std::vector> lastScheduledByCommandAndRank; + std::vector lastScheduledByCommand; + + sc_core::sc_time lastCommandOnRasBus; + sc_core::sc_time lastCommandOnCasBus; + + // Four activate window + std::vector> last4Activates; + std::vector bankwiseRefreshCounter; + + sc_core::sc_time tBURST; + sc_core::sc_time tRDPDE; + sc_core::sc_time tRDSRE; + sc_core::sc_time tWRPRE; + sc_core::sc_time tWRPDE; + sc_core::sc_time tWRAPDE; + sc_core::sc_time tRTWR; + sc_core::sc_time tWRRDS; + sc_core::sc_time tWRRDL; + sc_core::sc_time tWRRDR; +}; + +#endif // CHECKERHBM3_H diff --git a/DRAMSys/library/src/simulation/DRAMSys.cpp b/DRAMSys/library/src/simulation/DRAMSys.cpp index dcdf9f5b..bb02397d 100644 --- a/DRAMSys/library/src/simulation/DRAMSys.cpp +++ b/DRAMSys/library/src/simulation/DRAMSys.cpp @@ -57,6 +57,7 @@ #include "dram/DramLPDDR5.h" #include "dram/DramWideIO2.h" #include "dram/DramHBM2.h" +#include "dram/DramHBM3.h" #include "dram/DramGDDR5.h" #include "dram/DramGDDR5X.h" #include "dram/DramGDDR6.h" @@ -191,6 +192,9 @@ void DRAMSys::instantiateModules(const DRAMSysConfiguration::AddressMapping &add else if (memoryType == MemSpec::MemoryType::HBM2) drams.emplace_back(std::make_unique(("dram" + std::to_string(i)).c_str(), config, *temperatureController)); + else if (memoryType == MemSpec::MemoryType::HBM3) + drams.emplace_back(std::make_unique(("dram" + std::to_string(i)).c_str(), config, + *temperatureController)); else if (memoryType == MemSpec::MemoryType::GDDR5) drams.emplace_back(std::make_unique(("dram" + std::to_string(i)).c_str(), config, *temperatureController)); diff --git a/DRAMSys/library/src/simulation/DRAMSysRecordable.cpp b/DRAMSys/library/src/simulation/DRAMSysRecordable.cpp index 77bd94e7..3f16c0f6 100644 --- a/DRAMSys/library/src/simulation/DRAMSysRecordable.cpp +++ b/DRAMSys/library/src/simulation/DRAMSysRecordable.cpp @@ -47,6 +47,7 @@ #include "dram/DramLPDDR5.h" #include "dram/DramWideIO2.h" #include "dram/DramHBM2.h" +#include "dram/DramHBM3.h" #include "dram/DramGDDR5.h" #include "dram/DramGDDR5X.h" #include "dram/DramGDDR6.h" @@ -153,6 +154,9 @@ void DRAMSysRecordable::instantiateModules(const std::string &traceName, else if (memoryType == MemSpec::MemoryType::HBM2) drams.emplace_back(std::make_unique>(("dram" + std::to_string(i)).c_str(), config, *temperatureController, tlmRecorders[i])); + else if (memoryType == MemSpec::MemoryType::HBM3) + drams.emplace_back(std::make_unique>(("dram" + std::to_string(i)).c_str(), + config, *temperatureController, tlmRecorders[i])); else if (memoryType == MemSpec::MemoryType::GDDR5) drams.emplace_back(std::make_unique>(("dram" + std::to_string(i)).c_str(), config, *temperatureController, tlmRecorders[i])); diff --git a/DRAMSys/library/src/simulation/dram/DramHBM3.cpp b/DRAMSys/library/src/simulation/dram/DramHBM3.cpp new file mode 100644 index 00000000..10ed3cf1 --- /dev/null +++ b/DRAMSys/library/src/simulation/dram/DramHBM3.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2019, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#include "DramHBM3.h" +#include "../../configuration/Configuration.h" +#include "../../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h" +#include "../../configuration/memspec/MemSpecHBM3.h" + +using namespace sc_core; + +DramHBM3::DramHBM3(const sc_module_name& name, const Configuration& config, + TemperatureController& temperatureController) + : Dram(name, config) +{ + if (storeMode == Configuration::StoreMode::ErrorModel) + SC_REPORT_FATAL("DramHBM3", "Error Model not supported for HBM3"); + + if (powerAnalysis) + SC_REPORT_FATAL("DramHBM3", "DRAMPower does not support HBM3"); +} diff --git a/DRAMSys/library/src/simulation/dram/DramHBM3.h b/DRAMSys/library/src/simulation/dram/DramHBM3.h new file mode 100644 index 00000000..e1137002 --- /dev/null +++ b/DRAMSys/library/src/simulation/dram/DramHBM3.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2019, Technische Universität Kaiserslautern + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: + * Lukas Steiner + */ + +#ifndef DRAMHBM3_H +#define DRAMHBM3_H + +#include + +#include "Dram.h" +#include "../TemperatureController.h" + +class DramHBM3 : public Dram +{ +public: + DramHBM3(const sc_core::sc_module_name &name, const Configuration& config, + TemperatureController& temperatureController); + SC_HAS_PROCESS(DramHBM3); +}; + +#endif // DRAMHBM3_H diff --git a/DRAMSys/library/src/simulation/dram/DramRecordable.cpp b/DRAMSys/library/src/simulation/dram/DramRecordable.cpp index 90c75dd2..9d4cc8d2 100644 --- a/DRAMSys/library/src/simulation/dram/DramRecordable.cpp +++ b/DRAMSys/library/src/simulation/dram/DramRecordable.cpp @@ -46,6 +46,7 @@ #include "DramLPDDR5.h" #include "DramWideIO2.h" #include "DramHBM2.h" +#include "DramHBM3.h" #include "DramGDDR5.h" #include "DramGDDR5X.h" #include "DramGDDR6.h" @@ -162,4 +163,5 @@ template class DramRecordable; template class DramRecordable; template class DramRecordable; template class DramRecordable; +template class DramRecordable; template class DramRecordable;