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..7b7c076f --- /dev/null +++ b/DRAMSys/library/resources/configs/amconfigs/am_hbm3_8Gb_pc_brc.json @@ -0,0 +1,45 @@ +{ + "CONGEN": { + "PSEUDOCHANNEL_BIT":[ + 28 + ], + "BANKGROUP_BIT":[ + 26, + 27 + ], + "BANK_BIT": [ + 24, + 25 + ], + "BYTE_BIT": [ + 0, + 1 + ], + "COLUMN_BIT": [ + 2, + 3, + 4, + 5, + 6, + 7, + 8 + ], + "ROW_BIT": [ + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23 + ] + } +} diff --git a/DRAMSys/library/resources/configs/memspecs/HBM3.json b/DRAMSys/library/resources/configs/memspecs/HBM3.json new file mode 100644 index 00000000..16c18b75 --- /dev/null +++ b/DRAMSys/library/resources/configs/memspecs/HBM3.json @@ -0,0 +1,56 @@ +{ + "memspec": { + "memarchitecturespec": { + "burstLength": 8, + "dataRate": 4, + "nbrOfBankGroups": 4, + "nbrOfBanks": 16, + "nbrOfColumns": 128, + "nbrOfPseudoChannels": 2, + "nbrOfRows": 32768, + "width": 32, + "nbrOfDevices": 1, + "nbrOfChannels": 1, + "RAAIMT" : 16, + "RAAMMT" : 96, + "RAACDR" : 16 + }, + "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": 122, + "RFC": 260, + "RFCPB": 96, + "RL": 17, + "RP": 14, + "RRDL": 6, + "RRDS": 4, + "RREFD": 8, + "RTP": 5, + "RTW": 18, + "WL": 12, + "WR": 23, + "WTRL": 9, + "WTRS": 4, + "XP": 8, + "XS": 260, + "clkMhz": 1600 + }, + "memtimingspec_comments": { + "Annahme": "8-high, 8Gb/die", + "RFCPB": "TBD?" + } + } +} 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..2bbd1fac 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)); @@ -397,8 +390,7 @@ void TlmRecorder::insertCommandLengths() auto commandName = command.toString(); sqlite3_bind_text(insertCommandLengthsStatement, 1, commandName.c_str(), commandName.length(), nullptr); - sqlite3_bind_int(insertCommandLengthsStatement, 2, - static_cast(lround(memSpec.getCommandLength(command) / memSpec.tCK))); + sqlite3_bind_double(insertCommandLengthsStatement, 2, memSpec.getCommandLengthInCylcles(command)); executeSqlStatement(insertCommandLengthsStatement); }; diff --git a/DRAMSys/library/src/common/TlmRecorder.h b/DRAMSys/library/src/common/TlmRecorder.h index 1b63b41d..532c31d6 100644 --- a/DRAMSys/library/src/common/TlmRecorder.h +++ b/DRAMSys/library/src/common/TlmRecorder.h @@ -199,7 +199,7 @@ private: " \n" "CREATE TABLE CommandLengths( \n" " Command TEXT, \n" - " Length INTEGER \n" + " Length DOUBLE \n" "); \n" " \n" "CREATE TABLE Power( \n" diff --git a/DRAMSys/library/src/common/configuration/McConfig.cpp b/DRAMSys/library/src/common/configuration/McConfig.cpp index add44520..b87be4ea 100644 --- a/DRAMSys/library/src/common/configuration/McConfig.cpp +++ b/DRAMSys/library/src/common/configuration/McConfig.cpp @@ -54,7 +54,7 @@ void to_json(json &j, const McConfig &c) {"PowerDownPolicy", c.powerDownPolicy}, {"Arbiter", c.arbiter}, {"MaxActiveTransactions", c.maxActiveTransactions}, - {"RefreshManagment", c.refreshManagement}, + {"RefreshManagement", c.refreshManagement}, {"ArbitrationDelayFw", c.arbitrationDelayFw}, {"ArbitrationDelayBw", c.arbitrationDelayBw}, {"ThinkDelayFw", c.thinkDelayFw}, @@ -111,8 +111,8 @@ void from_json(const json &j, McConfig &c) if (j_mcconfig.contains("MaxActiveTransactions")) j_mcconfig.at("MaxActiveTransactions").get_to(c.maxActiveTransactions); - if (j_mcconfig.contains("RefreshManagment")) - j_mcconfig.at("RefreshManagment").get_to(c.refreshManagement); + if (j_mcconfig.contains("RefreshManagement")) + j_mcconfig.at("RefreshManagement").get_to(c.refreshManagement); if (j_mcconfig.contains("ArbitrationDelayFw")) j_mcconfig.at("ArbitrationDelayFw").get_to(c.arbitrationDelayFw); 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.cpp b/DRAMSys/library/src/configuration/memspec/MemSpec.cpp index 1b9f86f6..893dca70 100644 --- a/DRAMSys/library/src/configuration/memspec/MemSpec.cpp +++ b/DRAMSys/library/src/configuration/memspec/MemSpec.cpp @@ -74,7 +74,7 @@ MemSpec::MemSpec(const DRAMSysConfiguration::MemSpec &memSpec, burstDuration(tCK * (static_cast(defaultBurstLength) / dataRate)), memorySizeBytes(0) { - commandLengthInCycles = std::vector(Command::numberOfCommands(), 1); + commandLengthInCycles = std::vector(Command::numberOfCommands(), 1); } sc_time MemSpec::getCommandLength(Command command) const @@ -82,6 +82,11 @@ sc_time MemSpec::getCommandLength(Command command) const return tCK * commandLengthInCycles[command]; } +double MemSpec::getCommandLengthInCylcles(Command command) const +{ + return commandLengthInCycles[command]; +} + uint64_t MemSpec::getSimMemSizeInBytes() const { return memorySizeBytes; diff --git a/DRAMSys/library/src/configuration/memspec/MemSpec.h b/DRAMSys/library/src/configuration/memspec/MemSpec.h index ac6fca08..8aa64853 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; @@ -96,6 +96,7 @@ public: virtual TimeInterval getIntervalOnDataStrobe(Command command, const tlm::tlm_generic_payload &payload) const = 0; sc_core::sc_time getCommandLength(Command) const; + double getCommandLengthInCylcles(Command) const; uint64_t getSimMemSizeInBytes() const; protected: @@ -108,7 +109,7 @@ protected: unsigned devicesPerRank); // Command lengths in cycles on bus, usually one clock cycle - std::vector commandLengthInCycles; + std::vector commandLengthInCycles; sc_core::sc_time burstDuration; uint64_t memorySizeBytes; }; diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecHBM3.cpp b/DRAMSys/library/src/configuration/memspec/MemSpecHBM3.cpp new file mode 100644 index 00000000..d5aeaada --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecHBM3.cpp @@ -0,0 +1,195 @@ +/* + * 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")), + RAAIMT(memSpec.memArchitectureSpec.entries.at("RAAIMT")), + RAAMMT(memSpec.memArchitectureSpec.entries.at("RAAMMT")), + RAACDR(memSpec.memArchitectureSpec.entries.at("RAACDR")), + 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")), + tPPD (tCK * memSpec.memTimingSpec.entries.at("PPD")) +{ + commandLengthInCycles[Command::ACT] = 1.5; + commandLengthInCycles[Command::PREPB] = 0.5; + commandLengthInCycles[Command::PREAB] = 0.5; + commandLengthInCycles[Command::REFPB] = 0.5; + commandLengthInCycles[Command::REFAB] = 0.5; + commandLengthInCycles[Command::RFMPB] = 0.5; + commandLengthInCycles[Command::RFMAB] = 0.5; + commandLengthInCycles[Command::PDXA] = 0.5; + commandLengthInCycles[Command::SREFEX] = 0.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 || command == Command::RFMAB) + return tRFC; + else if (command == Command::REFPB || command == Command::RFMPB) + 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 {}; + } +} + +unsigned MemSpecHBM3::getRAACDR() const +{ + return RAACDR; +} + +unsigned MemSpecHBM3::getRAAIMT() const +{ + return RAAIMT; +} + +unsigned MemSpecHBM3::getRAAMMT() const +{ + return RAAMMT; +} diff --git a/DRAMSys/library/src/configuration/memspec/MemSpecHBM3.h b/DRAMSys/library/src/configuration/memspec/MemSpecHBM3.h new file mode 100644 index 00000000..f9a32241 --- /dev/null +++ b/DRAMSys/library/src/configuration/memspec/MemSpecHBM3.h @@ -0,0 +1,102 @@ +/* + * 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); + + const unsigned RAAIMT; + const unsigned RAAMMT; + const unsigned RAACDR; + + // 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; + const sc_core::sc_time tPPD; + + // Currents and Voltages: + // TODO: to be completed + + sc_core::sc_time getRefreshIntervalAB() const override; + sc_core::sc_time getRefreshIntervalPB() const override; + + unsigned getRAACDR() const override; + unsigned getRAAIMT() const override; + unsigned getRAAMMT() 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..dc924869 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) @@ -234,11 +237,14 @@ Controller::Controller(const sc_module_name& name, const Configuration& config) void Controller::controllerMethod() { - // (1) Finish last response (END_RESP) and start new response (BEGIN_RESP) - manageResponses(); + if (isFullCycle(sc_time_stamp())) + { + // (1) Finish last response (END_RESP) and start new response (BEGIN_RESP) + manageResponses(); - // (2) Insert new request into scheduler and send END_REQ or use backpressure - manageRequests(SC_ZERO_TIME); + // (2) Insert new request into scheduler and send END_REQ or use backpressure + manageRequests(SC_ZERO_TIME); + } // (3) Start refresh and power-down managers to issue requests for the current time for (auto& it : refreshManagers) @@ -328,6 +334,7 @@ void Controller::controllerMethod() powerDownManagers[rank.ID()]->triggerEntry(); sc_time fwDelay = thinkDelayFw + phyDelayFw; + sendToDram(command, *payload, fwDelay); } else @@ -508,3 +515,9 @@ void Controller::sendToDram(Command command, tlm_generic_payload& payload, sc_ti tlm_phase phase = command.toPhase(); iSocket->nb_transport_fw(payload, phase, delay); } + +bool Controller::isFullCycle(const sc_core::sc_time& time) const +{ + sc_time aligedAtHalfCycle = std::floor((time * 2 / memSpec.tCK + 0.5)) / 2 * memSpec.tCK; + return aligedAtHalfCycle % memSpec.tCK == SC_ZERO_TIME; +} diff --git a/DRAMSys/library/src/controller/Controller.h b/DRAMSys/library/src/controller/Controller.h index 12a9a879..58108539 100644 --- a/DRAMSys/library/src/controller/Controller.h +++ b/DRAMSys/library/src/controller/Controller.h @@ -96,6 +96,8 @@ private: void manageResponses(); void manageRequests(const sc_core::sc_time &delay); + bool isFullCycle(const sc_core::sc_time& time) const; + sc_core::sc_event beginReqEvent, endRespEvent, controllerEvent, dataResponseEvent; }; diff --git a/DRAMSys/library/src/controller/checker/CheckerHBM3.cpp b/DRAMSys/library/src/controller/checker/CheckerHBM3.cpp new file mode 100644 index 00000000..ce95d7b1 --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerHBM3.cpp @@ -0,0 +1,806 @@ +/* + * 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); + + tRDPDE = memSpec->tRL + memSpec->tPL + 2 * memSpec->tCK; + tRDSRE = memSpec->tRL + memSpec->tPL + 3 * memSpec->tCK; + tWRPRE = memSpec->tWL + 2 * memSpec->tCK + memSpec->tWR; + tWRPDE = memSpec->tWL + memSpec->tPL + 3 * memSpec->tCK + memSpec->tWR; + tWRAPDE = memSpec->tWL + memSpec->tPL + 3 * memSpec->tCK + memSpec->tWR; + tWRRDS = memSpec->tWL + 2 * memSpec->tCK + memSpec->tWTRS; + tWRRDL = memSpec->tWL + 2 * memSpec->tCK + 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::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 = lastScheduledByCommandAndRank[Command::PREPB][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREAB][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnRasBus + memSpec->tCK / 2); + } + else if (command == Command::RD) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDRD + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RD][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + 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); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRDL); + + 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 = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnCasBus + memSpec->tCK); + } + else if (command == Command::WR) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDWR + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RD][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankGroup.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankGroup.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 = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + 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 = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnCasBus + memSpec->tCK); + } + else if (command == Command::RDA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDRD + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RD][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + 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); + + lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + 2 * memSpec->tCK + + std::max(memSpec->tWR - memSpec->tRTP, memSpec->tWTRL)); + + 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 = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnCasBus + memSpec->tCK); + } + else if (command == Command::WRA) + { + lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDWR + memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RD][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankGroup.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankGroup.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 = lastScheduledByCommandAndBank[Command::WR][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL); + + 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 = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + 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 = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP - memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXP][rank.ID()]; + 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 = lastScheduledByCommandAndBankGroup[Command::REFPB][bankGroup.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD - memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFPB][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD - memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RFMAB][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC - memSpec->tCK); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RFMPB][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCPB); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RFMPB][bankGroup.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RFMPB][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD); + + lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()]; + 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); + 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 = lastScheduledByCommandAndRank[Command::PDXP][rank.ID()]; + 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 = lastScheduledByCommandAndRank[Command::RFMAB][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RFMPB][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCPB); + + lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXS); + + 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 = lastScheduledByCommandAndRank[Command::PREPB][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PREAB][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + 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 / 2); + } + else if (command == Command::REFAB) + { + 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 = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXP][rank.ID()]; + 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 = lastScheduledByCommandAndBankGroup[Command::REFPB][bankGroup.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFPB][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RFMAB][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RFMPB][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCPB); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RFMPB][bankGroup.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RFMPB][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD); + + lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXS); + + 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); + } + + 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::SREFEN) + { + 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 + std::max(memSpec->tRTP + memSpec->tRP, tRDSRE)); + + 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 = lastScheduledByCommandAndRank[Command::PDXP][rank.ID()]; + 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 = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXS); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnRasBus + memSpec->tCK); + } + else if (command == Command::RFMAB) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC + memSpec->tCK); + + 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 = lastScheduledByCommandAndRank[Command::RFMAB][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RFMPB][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::RFMAB) + { + 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 = 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 = lastScheduledByCommandAndBankGroup[Command::REFPB][bankGroup.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD); + + lastCommandStart = lastScheduledByCommandAndRank[Command::REFPB][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RFMAB][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC); + + lastCommandStart = lastScheduledByCommandAndBank[Command::RFMPB][bank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCPB); + + lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RFMPB][bankGroup.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RFMPB][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnRasBus + memSpec->tCK); + } + else if (command == Command::PDEA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDPDE); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDPDE); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPDE); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRAPDE); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCKE); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnRasBus + memSpec->tCK); + } + else if (command == Command::PDEP) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDPDE); + + lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDPDE); + + lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRAPDE); + + lastCommandStart = lastScheduledByCommandAndRank[Command::PDXP][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCKE); + + lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()]; + 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 = lastScheduledByCommandAndRank[Command::PDEP][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPD); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnRasBus + memSpec->tCK); + } + else if (command == Command::PDXA) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::PDEA][rank.ID()]; + if (lastCommandStart != sc_max_time()) + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPD); + + earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnRasBus + memSpec->tCK); + } + else if (command == Command::SREFEX) + { + lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEN][rank.ID()]; + 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!"); + } + + // Don't issue commands at half cycles. + if (command != Command::PREAB && command != Command::PREPB && !isFullCycle(earliestTimeToStart)) + earliestTimeToStart += memSpec->tCK / 2; + + 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; +} + +bool CheckerHBM3::isFullCycle(const sc_core::sc_time& time) const +{ + sc_time aligedAtHalfCycle = std::floor((time * 2 / memSpec->tCK + 0.5)) / 2 * memSpec->tCK; + return aligedAtHalfCycle % memSpec->tCK == SC_ZERO_TIME; +} diff --git a/DRAMSys/library/src/controller/checker/CheckerHBM3.h b/DRAMSys/library/src/controller/checker/CheckerHBM3.h new file mode 100644 index 00000000..8bd4423d --- /dev/null +++ b/DRAMSys/library/src/controller/checker/CheckerHBM3.h @@ -0,0 +1,78 @@ +/* + * 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: + bool isFullCycle(const sc_core::sc_time& time) const; + + 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 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 tWRRDS; + sc_core::sc_time tWRRDL; +}; + +#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; diff --git a/DRAMSys/traceAnalyzer/businessObjects/commandlengths.h b/DRAMSys/traceAnalyzer/businessObjects/commandlengths.h index 8cfd421b..1dc394bf 100644 --- a/DRAMSys/traceAnalyzer/businessObjects/commandlengths.h +++ b/DRAMSys/traceAnalyzer/businessObjects/commandlengths.h @@ -38,38 +38,38 @@ struct CommandLengths { - unsigned NOP = 1; - unsigned RD = 1; - unsigned WR = 1; - unsigned RDA = 1; - unsigned WRA = 1; - unsigned ACT = 1; - unsigned PREPB = 1; - unsigned REFPB = 1; - unsigned RFMPB = 1; - unsigned REFP2B = 1; - unsigned RFMP2B = 1; - unsigned PRESB = 1; - unsigned REFSB = 1; - unsigned RFMSB = 1; - unsigned PREAB = 1; - unsigned REFAB = 1; - unsigned RFMAB = 1; - unsigned PDEA = 1; - unsigned PDXA = 1; - unsigned PDEP = 1; - unsigned PDXP = 1; - unsigned SREFEN = 1; - unsigned SREFEX = 1; + double NOP = 1; + double RD = 1; + double WR = 1; + double RDA = 1; + double WRA = 1; + double ACT = 1; + double PREPB = 1; + double REFPB = 1; + double RFMPB = 1; + double REFP2B = 1; + double RFMP2B = 1; + double PRESB = 1; + double REFSB = 1; + double RFMSB = 1; + double PREAB = 1; + double REFAB = 1; + double RFMAB = 1; + double PDEA = 1; + double PDXA = 1; + double PDEP = 1; + double PDXP = 1; + double SREFEN = 1; + double SREFEX = 1; - CommandLengths(unsigned NOP, unsigned RD, unsigned WR, - unsigned RDA, unsigned WRA, unsigned ACT, - unsigned PREPB, unsigned REFPB, unsigned RFMPB, - unsigned REFP2B, unsigned RFMP2B, - unsigned PRESB, unsigned REFSB, unsigned RFMSB, - unsigned PREAB, unsigned REFAB, unsigned RFMAB, - unsigned PDEA, unsigned PDXA, unsigned PDEP, unsigned PDXP, - unsigned SREFEN, unsigned SREFEX) : + CommandLengths(double NOP, double RD, double WR, + double RDA, double WRA, double ACT, + double PREPB, double REFPB, double RFMPB, + double REFP2B, double RFMP2B, + double PRESB, double REFSB, double RFMSB, + double PREAB, double REFAB, double RFMAB, + double PDEA, double PDXA, double PDEP, double PDXP, + double SREFEN, double SREFEX) : NOP(NOP), RD(RD), WR(WR), RDA(RDA), WRA(WRA), ACT(ACT), PREPB(PREPB), REFPB(REFPB), RFMPB(RFMPB), diff --git a/DRAMSys/traceAnalyzer/businessObjects/configmodels.cpp b/DRAMSys/traceAnalyzer/businessObjects/configmodels.cpp index 38fef880..bcfbdf73 100644 --- a/DRAMSys/traceAnalyzer/businessObjects/configmodels.cpp +++ b/DRAMSys/traceAnalyzer/businessObjects/configmodels.cpp @@ -69,6 +69,10 @@ void McConfigModel::parseJson(const QString &jsonString) { entries.push_back({key, currentValue.toString()}); } + else if (currentValue.isBool()) + { + entries.push_back({key, currentValue.toBool() ? "True" : "False"}); + } } } @@ -183,6 +187,10 @@ void MemSpecModel::parseJson(const QString &jsonString) { value = currentValue.toString(); } + else if (currentValue.isBool()) + { + value = currentValue.toBool() ? "True" : "False"; + } std::unique_ptr node = std::unique_ptr(new Node({key, value}, parentNode.get())); addNodes(obj[key].toObject(), node); diff --git a/DRAMSys/traceAnalyzer/data/tracedb.cpp b/DRAMSys/traceAnalyzer/data/tracedb.cpp index 9f9b6e48..1f10bbf9 100644 --- a/DRAMSys/traceAnalyzer/data/tracedb.cpp +++ b/DRAMSys/traceAnalyzer/data/tracedb.cpp @@ -360,12 +360,12 @@ CommandLengths TraceDB::getCommandLengthsFromDB() return {}; }; - auto getCommandLength = [=, &table](const std::string &command) -> unsigned + auto getCommandLength = [=, &table](const std::string &command) -> double { QVariant length = getLengthFromDb(command); if (length.isValid()) - return length.toUInt(); + return length.toDouble(); else { qDebug() << "CommandLength for" << command.c_str() << "not present in table" << table.c_str() @@ -374,12 +374,12 @@ CommandLengths TraceDB::getCommandLengthsFromDB() } }; - auto getCommandLengthOrElse = [=, &table](const std::string &command, const std::string &elseCommand) -> unsigned + auto getCommandLengthOrElse = [=, &table](const std::string &command, const std::string &elseCommand) -> double { QVariant length = getLengthFromDb(command); if (length.isValid()) - return length.toUInt(); + return length.toDouble(); else { length = getLengthFromDb(command); @@ -395,33 +395,33 @@ CommandLengths TraceDB::getCommandLengthsFromDB() } }; - unsigned NOP = getCommandLength("NOP"); - unsigned RD = getCommandLength("RD"); - unsigned WR = getCommandLength("RD"); - unsigned RDA = getCommandLength("RDA"); - unsigned WRA = getCommandLength("WRA"); - unsigned ACT = getCommandLength("ACT"); + double NOP = getCommandLength("NOP"); + double RD = getCommandLength("RD"); + double WR = getCommandLength("RD"); + double RDA = getCommandLength("RDA"); + double WRA = getCommandLength("WRA"); + double ACT = getCommandLength("ACT"); - unsigned PREPB = getCommandLengthOrElse("PREPB", "PRE"); - unsigned REFPB = getCommandLengthOrElse("REFPB", "REFB"); + double PREPB = getCommandLengthOrElse("PREPB", "PRE"); + double REFPB = getCommandLengthOrElse("REFPB", "REFB"); - unsigned RFMPB = getCommandLength("RFMPB"); - unsigned REFP2B = getCommandLength("REFP2B"); - unsigned RFMP2B = getCommandLength("RFMP2B"); - unsigned PRESB = getCommandLength("PRESB"); - unsigned REFSB = getCommandLength("REFSB"); - unsigned RFMSB = getCommandLength("RFMSB"); + double RFMPB = getCommandLength("RFMPB"); + double REFP2B = getCommandLength("REFP2B"); + double RFMP2B = getCommandLength("RFMP2B"); + double PRESB = getCommandLength("PRESB"); + double REFSB = getCommandLength("REFSB"); + double RFMSB = getCommandLength("RFMSB"); - unsigned PREAB = getCommandLengthOrElse("PREAB", "PREA"); - unsigned REFAB = getCommandLengthOrElse("REFAB", "REFA"); + double PREAB = getCommandLengthOrElse("PREAB", "PREA"); + double REFAB = getCommandLengthOrElse("REFAB", "REFA"); - unsigned RFMAB = getCommandLength("RFMAB"); - unsigned PDEA = getCommandLength("PDEA"); - unsigned PDXA = getCommandLength("PDXA"); - unsigned PDEP = getCommandLength("PDEP"); - unsigned PDXP = getCommandLength("PDXP"); - unsigned SREFEN = getCommandLength("SREFEN"); - unsigned SREFEX = getCommandLength("SREFEX"); + double RFMAB = getCommandLength("RFMAB"); + double PDEA = getCommandLength("PDEA"); + double PDXA = getCommandLength("PDXA"); + double PDEP = getCommandLength("PDEP"); + double PDXP = getCommandLength("PDXP"); + double SREFEN = getCommandLength("SREFEN"); + double SREFEX = getCommandLength("SREFEX"); return {NOP, RD, WR, RDA, WRA, ACT, PREPB, REFPB, RFMPB, REFP2B, RFMP2B, PRESB, REFSB, RFMSB, PREAB, REFAB, RFMAB, PDEA, PDXA, PDEP, PDXP, SREFEN, SREFEX};