Merge branch 'work/HBM3' into 'develop'
HBM3 implementation See merge request ems/astdm/modeling.dram/dram.sys!359
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
]
|
||||
}
|
||||
}
|
||||
56
DRAMSys/library/resources/configs/memspecs/HBM3.json
Normal file
56
DRAMSys/library/resources/configs/memspecs/HBM3.json
Normal 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?"
|
||||
}
|
||||
}
|
||||
}
|
||||
19
DRAMSys/library/resources/configs/simulator/hbm3.json
Normal file
19
DRAMSys/library/resources/configs/simulator/hbm3.json
Normal 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
|
||||
}
|
||||
}
|
||||
16
DRAMSys/library/resources/simulations/hbm3-example.json
Normal file
16
DRAMSys/library/resources/simulations/hbm3-example.json
Normal 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"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
195
DRAMSys/library/src/configuration/memspec/MemSpecHBM3.cpp
Normal file
195
DRAMSys/library/src/configuration/memspec/MemSpecHBM3.cpp
Normal 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;
|
||||
}
|
||||
102
DRAMSys/library/src/configuration/memspec/MemSpecHBM3.h
Normal file
102
DRAMSys/library/src/configuration/memspec/MemSpecHBM3.h
Normal 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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
806
DRAMSys/library/src/controller/checker/CheckerHBM3.cpp
Normal file
806
DRAMSys/library/src/controller/checker/CheckerHBM3.cpp
Normal 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;
|
||||
}
|
||||
78
DRAMSys/library/src/controller/checker/CheckerHBM3.h
Normal file
78
DRAMSys/library/src/controller/checker/CheckerHBM3.h
Normal 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
|
||||
@@ -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));
|
||||
|
||||
@@ -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]));
|
||||
|
||||
52
DRAMSys/library/src/simulation/dram/DramHBM3.cpp
Normal file
52
DRAMSys/library/src/simulation/dram/DramHBM3.cpp
Normal 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");
|
||||
}
|
||||
52
DRAMSys/library/src/simulation/dram/DramHBM3.h
Normal file
52
DRAMSys/library/src/simulation/dram/DramHBM3.h
Normal 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
|
||||
@@ -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>;
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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};
|
||||
|
||||
Reference in New Issue
Block a user