Merge branch 'work/HBM3' into 'develop'

HBM3 implementation

See merge request ems/astdm/modeling.dram/dram.sys!359
This commit is contained in:
Lukas Steiner
2022-05-24 08:58:59 +00:00
25 changed files with 1544 additions and 82 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,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
]
}
}

View File

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

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));
@@ -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<int>(lround(memSpec.getCommandLength(command) / memSpec.tCK)));
sqlite3_bind_double(insertCommandLengthsStatement, 2, memSpec.getCommandLengthInCylcles(command));
executeSqlStatement(insertCommandLengthsStatement);
};

View File

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

View File

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

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

@@ -74,7 +74,7 @@ MemSpec::MemSpec(const DRAMSysConfiguration::MemSpec &memSpec,
burstDuration(tCK * (static_cast<double>(defaultBurstLength) / dataRate)),
memorySizeBytes(0)
{
commandLengthInCycles = std::vector<unsigned>(Command::numberOfCommands(), 1);
commandLengthInCycles = std::vector<double>(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;

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;
@@ -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<unsigned> commandLengthInCycles;
std::vector<double> commandLengthInCycles;
sc_core::sc_time burstDuration;
uint64_t memorySizeBytes;
};

View File

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

View File

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

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

View File

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

View File

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

View File

@@ -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 <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:
bool isFullCycle(const sc_core::sc_time& time) const;
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 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

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

View File

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

View File

@@ -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> node = std::unique_ptr<Node>(new Node({key, value}, parentNode.get()));
addNodes(obj[key].toObject(), node);

View File

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