Add skeleton for HBM3 implementation

This commit is contained in:
2022-04-20 11:21:21 +02:00
parent 38057667b0
commit a3b0738364
18 changed files with 1163 additions and 12 deletions

View File

@@ -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

View File

@@ -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
]
}
}

View File

@@ -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)"
}
}
}

View File

@@ -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
}
}

View File

@@ -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"
}
]
}
}

View File

@@ -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<int>(rowColumnCommandBus));

View File

@@ -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<const MemSpecWideIO2>(memSpecConfig);
else if (memoryType == "HBM2")
memSpec = std::make_unique<const MemSpecHBM2>(memSpecConfig);
else if (memoryType == "HBM3")
memSpec = std::make_unique<const MemSpecHBM3>(memSpecConfig);
else if (memoryType == "GDDR5")
memSpec = std::make_unique<const MemSpecGDDR5>(memSpecConfig);
else if (memoryType == "GDDR5X")

View File

@@ -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;

View File

@@ -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 <iostream>
#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<uint64_t>(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 {};
}
}

View File

@@ -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 <systemc>
#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

View File

@@ -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<CheckerWideIO2>(config);
else if (memSpec.memoryType == MemSpec::MemoryType::HBM2)
checker = std::make_unique<CheckerHBM2>(config);
else if (memSpec.memoryType == MemSpec::MemoryType::HBM3)
checker = std::make_unique<CheckerHBM3>(config);
else if (memSpec.memoryType == MemSpec::MemoryType::GDDR5)
checker = std::make_unique<CheckerGDDR5>(config);
else if (memSpec.memoryType == MemSpec::MemoryType::GDDR5X)

View File

@@ -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 <algorithm>
#include "CheckerHBM3.h"
using namespace sc_core;
using namespace tlm;
CheckerHBM3::CheckerHBM3(const Configuration& config)
{
memSpec = dynamic_cast<const MemSpecHBM3 *>(config.memSpec.get());
if (memSpec == nullptr)
SC_REPORT_FATAL("CheckerHBM3", "Wrong MemSpec chosen");
lastScheduledByCommandAndBank = std::vector<std::vector<sc_time>>
(Command::numberOfCommands(), std::vector<sc_time>(memSpec->banksPerChannel, sc_max_time()));
lastScheduledByCommandAndBankGroup = std::vector<std::vector<sc_time>>
(Command::numberOfCommands(), std::vector<sc_time>(memSpec->bankGroupsPerChannel, sc_max_time()));
lastScheduledByCommandAndRank = std::vector<std::vector<sc_time>>
(Command::numberOfCommands(), std::vector<sc_time>(memSpec->ranksPerChannel, sc_max_time()));
lastScheduledByCommand = std::vector<sc_time>(Command::numberOfCommands(), sc_max_time());
lastCommandOnRasBus = sc_max_time();
lastCommandOnCasBus = sc_max_time();
last4Activates = std::vector<std::queue<sc_time>>(memSpec->ranksPerChannel);
bankwiseRefreshCounter = std::vector<unsigned>(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;
}

View File

@@ -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 <queue>
#include <vector>
#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<std::vector<sc_core::sc_time>> lastScheduledByCommandAndBank;
std::vector<std::vector<sc_core::sc_time>> lastScheduledByCommandAndBankGroup;
std::vector<std::vector<sc_core::sc_time>> lastScheduledByCommandAndRank;
std::vector<sc_core::sc_time> lastScheduledByCommand;
sc_core::sc_time lastCommandOnRasBus;
sc_core::sc_time lastCommandOnCasBus;
// Four activate window
std::vector<std::queue<sc_core::sc_time>> last4Activates;
std::vector<unsigned> 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

View File

@@ -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<DramHBM2>(("dram" + std::to_string(i)).c_str(), config,
*temperatureController));
else if (memoryType == MemSpec::MemoryType::HBM3)
drams.emplace_back(std::make_unique<DramHBM3>(("dram" + std::to_string(i)).c_str(), config,
*temperatureController));
else if (memoryType == MemSpec::MemoryType::GDDR5)
drams.emplace_back(std::make_unique<DramGDDR5>(("dram" + std::to_string(i)).c_str(), config,
*temperatureController));

View File

@@ -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<DramRecordable<DramHBM2>>(("dram" + std::to_string(i)).c_str(),
config, *temperatureController, tlmRecorders[i]));
else if (memoryType == MemSpec::MemoryType::HBM3)
drams.emplace_back(std::make_unique<DramRecordable<DramHBM3>>(("dram" + std::to_string(i)).c_str(),
config, *temperatureController, tlmRecorders[i]));
else if (memoryType == MemSpec::MemoryType::GDDR5)
drams.emplace_back(std::make_unique<DramRecordable<DramGDDR5>>(("dram" + std::to_string(i)).c_str(),
config, *temperatureController, tlmRecorders[i]));

View File

@@ -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");
}

View File

@@ -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 <systemc>
#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

View File

@@ -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<DramGDDR5>;
template class DramRecordable<DramGDDR5X>;
template class DramRecordable<DramGDDR6>;
template class DramRecordable<DramHBM2>;
template class DramRecordable<DramHBM3>;
template class DramRecordable<DramSTTMRAM>;