Included memspec, dram and checker for GDDR5, GDDR5X and GDDR6.

This commit is contained in:
Lukas Steiner (2)
2019-10-17 15:00:28 +02:00
parent a3fa363a87
commit 5f7cb7a326
40 changed files with 2521 additions and 46 deletions

View File

@@ -146,7 +146,16 @@ SOURCES += \
src/controller/checker/CheckerWideIO2.cpp \
src/configuration/memspec/MemSpecHBM2.cpp \
src/simulation/dram/DramHBM2.cpp \
src/controller/checker/CheckerHBM2.cpp
src/controller/checker/CheckerHBM2.cpp \
src/configuration/memspec/MemSpecGDDR5.cpp \
src/configuration/memspec/MemSpecGDDR5X.cpp \
src/configuration/memspec/MemSpecGDDR6.cpp \
src/controller/checker/CheckerGDDR5.cpp \
src/controller/checker/CheckerGDDR5X.cpp \
src/controller/checker/CheckerGDDR6.cpp \
src/simulation/dram/DramGDDR5.cpp \
src/simulation/dram/DramGDDR5X.cpp \
src/simulation/dram/DramGDDR6.cpp
HEADERS += \
src/common/third_party/tinyxml2/tinyxml2.h \
@@ -226,7 +235,16 @@ HEADERS += \
src/controller/checker/CheckerWideIO2.h \
src/configuration/memspec/MemSpecHBM2.h \
src/simulation/dram/DramHBM2.h \
src/controller/checker/CheckerHBM2.h
src/controller/checker/CheckerHBM2.h \
src/configuration/memspec/MemSpecGDDR5.h \
src/configuration/memspec/MemSpecGDDR5X.h \
src/configuration/memspec/MemSpecGDDR6.h \
src/controller/checker/CheckerGDDR5.h \
src/controller/checker/CheckerGDDR5X.h \
src/controller/checker/CheckerGDDR6.h \
src/simulation/dram/DramGDDR5.h \
src/simulation/dram/DramGDDR5X.h \
src/simulation/dram/DramGDDR6.h
#src/common/third_party/json/include/nlohmann/json.hpp \
thermalsim = $$(THERMALSIM)

View File

@@ -43,6 +43,9 @@
#include "memspec/MemSpecLPDDR4.h"
#include "memspec/MemSpecWideIO2.h"
#include "memspec/MemSpecHBM2.h"
#include "memspec/MemSpecGDDR5.h"
#include "memspec/MemSpecGDDR5X.h"
#include "memspec/MemSpecGDDR6.h"
#include "../common/timingCalculations.h"
using namespace tinyxml2;
@@ -182,6 +185,24 @@ void ConfigurationLoader::loadMemSpec(Configuration &config,
loadCommons(config, memspec);
loadHBM2(config, memspec);
}
else if (memoryType == "GDDR5")
{
Configuration::getInstance().memSpec = new MemSpecGDDR5();
loadCommons(config, memspec);
loadGDDR5(config, memspec);
}
else if (memoryType == "GDDR5X")
{
Configuration::getInstance().memSpec = new MemSpecGDDR5X();
loadCommons(config, memspec);
loadGDDR5X(config, memspec);
}
else if (memoryType == "GDDR6")
{
Configuration::getInstance().memSpec = new MemSpecGDDR6();
loadCommons(config, memspec);
loadGDDR6(config, memspec);
}
else
reportFatal("ConfigurationLoader", "Unsupported DRAM type");
}
@@ -549,8 +570,16 @@ void ConfigurationLoader::loadHBM2(Configuration &config, XMLElement *xmlSpec)
memSpec->tRTW = clk * queryUIntParameter(timings, "RTW");
memSpec->tXP = clk * queryUIntParameter(timings, "XP");
memSpec->tCKE = clk * queryUIntParameter(timings, "CKE");
// memSpec->tPD = clk * queryUIntParameter(timings, "PD");
// memSpec->tCKESR = clk * queryUIntParameter(timings, "CKESR");
memSpec->tPD = memSpec->tCKE;
memSpec->tRDPDE = memSpec->tRL + memSpec->tPL
+ (memSpec->BurstLength / memSpec->DataRate + 1) * memSpec->clk;
memSpec->tWRPDE = memSpec->tWL + memSpec->tPL
+ (memSpec->BurstLength / memSpec->DataRate + 1) * memSpec->clk + memSpec->tWR;
memSpec->tWRAPDE = memSpec->tWL + memSpec->tPL
+ (memSpec->BurstLength / memSpec->DataRate + 1) * memSpec->clk + memSpec->tWR;
memSpec->tCKESR = memSpec->tCKE + memSpec->clk;
memSpec->tRDSRE = memSpec->tRL + memSpec->tPL
+ (memSpec->BurstLength / memSpec->DataRate + 1) * memSpec->clk;
memSpec->tXS = clk * queryUIntParameter(timings, "XS");
memSpec->tRFC = clk * queryUIntParameter(timings, "RFC");
memSpec->tRFCSB = clk * queryUIntParameter(timings, "RFCSB");
@@ -561,3 +590,186 @@ void ConfigurationLoader::loadHBM2(Configuration &config, XMLElement *xmlSpec)
// Currents and voltages
// TODO: to be completed
}
void ConfigurationLoader::loadGDDR5(Configuration &config, XMLElement *xmlSpec)
{
MemSpecGDDR5 *memSpec = dynamic_cast<MemSpecGDDR5 *>(config.memSpec);
if (memSpec == nullptr)
SC_REPORT_FATAL("ConfigurationLoader", "Wrong MemSpec chosen");
// MemArchitecture
XMLElement *architecture = xmlSpec->FirstChildElement("memarchitecturespec");
memSpec->NumberOfRanks = queryUIntParameter(architecture, "nbrOfRanks");
memSpec->BanksPerRank = queryUIntParameter(architecture, "nbrOfBanks");
memSpec->GroupsPerRank = queryUIntParameter(architecture, "nbrOfBankGroups");
memSpec->BanksPerGroup = memSpec->BanksPerRank / memSpec->GroupsPerRank;
memSpec->NumberOfBanks = memSpec->BanksPerRank * memSpec->NumberOfRanks;
memSpec->NumberOfBankGroups = memSpec->GroupsPerRank * memSpec->NumberOfRanks;
// MemTimings specific for GDDR5
XMLElement *timings = xmlSpec->FirstChildElement("memtimingspec");
sc_time clk = memSpec->clk;
memSpec->tRP = clk * queryUIntParameter(timings, "RP");
memSpec->tRAS = clk * queryUIntParameter(timings, "RAS");
memSpec->tRC = clk * queryUIntParameter(timings, "RC");
memSpec->tRCDRD = clk * queryUIntParameter(timings, "RCDRD");
memSpec->tRCDWR = clk * queryUIntParameter(timings, "RCDWR");
memSpec->tRTP = clk * queryUIntParameter(timings, "RTP");
memSpec->tRRDS = clk * queryUIntParameter(timings, "RRDS");
memSpec->tRRDL = clk * queryUIntParameter(timings, "RRDL");
memSpec->tCCDS = clk * queryUIntParameter(timings, "CCDS");
memSpec->tCCDL = clk * queryUIntParameter(timings, "CCDL");
memSpec->tCL = clk * queryUIntParameter(timings, "CL");
memSpec->tWCK2CKPIN = clk * queryUIntParameter(timings, "WCK2CKPIN");
memSpec->tWCK2CK = clk * queryUIntParameter(timings, "WCK2CK");
memSpec->tWCK2DQO = clk * queryUIntParameter(timings, "WCK2DQO");
memSpec->tRTW = clk * queryUIntParameter(timings, "RTW");
memSpec->tWL = clk * queryUIntParameter(timings, "WL");
memSpec->tWCK2DQI = clk * queryUIntParameter(timings, "WCK2DQI");
memSpec->tWR = clk * queryUIntParameter(timings, "WR");
memSpec->tWTRS = clk * queryUIntParameter(timings, "WTRS");
memSpec->tWTRL = clk * queryUIntParameter(timings, "WTRL");
memSpec->tCKE = clk * queryUIntParameter(timings, "CKE");
memSpec->tPD = memSpec->tCKE;
memSpec->tXPN = clk * queryUIntParameter(timings, "XPN");
memSpec->tREFI = clk * queryUIntParameter(timings, "REFI");
memSpec->tREFIPB = clk * queryUIntParameter(timings, "REFIPB");
memSpec->tRFC = clk * queryUIntParameter(timings, "RFC");
memSpec->tRFCPB = clk * queryUIntParameter(timings, "RFCPB");
memSpec->tRREFD = clk * queryUIntParameter(timings, "RREFD");
memSpec->tXS = clk * queryUIntParameter(timings, "XS");
memSpec->tFAW = clk * queryUIntParameter(timings, "FAW");
memSpec->t32AW = clk * queryUIntParameter(timings, "32AW");
memSpec->tRDSRE = memSpec->tCL + memSpec->tWCK2CKPIN + memSpec->tWCK2CK
+ memSpec->tWCK2DQO + memSpec->BurstLength / memSpec->DataRate * clk;
memSpec->tWRSRE = memSpec->tWL + memSpec->tWCK2CKPIN + memSpec->tWCK2CK
+ memSpec->tWCK2DQI + memSpec->BurstLength / memSpec->DataRate * clk;
memSpec->tPPD = clk * queryUIntParameter(timings, "PPD");
memSpec->tLK = clk * queryUIntParameter(timings, "LK");
// Currents and voltages
// TODO: to be completed
}
void ConfigurationLoader::loadGDDR5X(Configuration &config, XMLElement *xmlSpec)
{
MemSpecGDDR5X *memSpec = dynamic_cast<MemSpecGDDR5X *>(config.memSpec);
if (memSpec == nullptr)
SC_REPORT_FATAL("ConfigurationLoader", "Wrong MemSpec chosen");
// MemArchitecture
XMLElement *architecture = xmlSpec->FirstChildElement("memarchitecturespec");
memSpec->NumberOfRanks = queryUIntParameter(architecture, "nbrOfRanks");
memSpec->BanksPerRank = queryUIntParameter(architecture, "nbrOfBanks");
memSpec->GroupsPerRank = queryUIntParameter(architecture, "nbrOfBankGroups");
memSpec->BanksPerGroup = memSpec->BanksPerRank / memSpec->GroupsPerRank;
memSpec->NumberOfBanks = memSpec->BanksPerRank * memSpec->NumberOfRanks;
memSpec->NumberOfBankGroups = memSpec->GroupsPerRank * memSpec->NumberOfRanks;
// MemTimings specific for GDDR5X
XMLElement *timings = xmlSpec->FirstChildElement("memtimingspec");
sc_time clk = memSpec->clk;
memSpec->tRP = clk * queryUIntParameter(timings, "RP");
memSpec->tRAS = clk * queryUIntParameter(timings, "RAS");
memSpec->tRC = clk * queryUIntParameter(timings, "RC");
memSpec->tRCDRD = clk * queryUIntParameter(timings, "RCDRD");
memSpec->tRCDWR = clk * queryUIntParameter(timings, "RCDWR");
memSpec->tRTP = clk * queryUIntParameter(timings, "RTP");
memSpec->tRRDS = clk * queryUIntParameter(timings, "RRDS");
memSpec->tRRDL = clk * queryUIntParameter(timings, "RRDL");
memSpec->tCCDS = clk * queryUIntParameter(timings, "CCDS");
memSpec->tCCDL = clk * queryUIntParameter(timings, "CCDL");
memSpec->tRL = clk * queryUIntParameter(timings, "RL");
memSpec->tWCK2CKPIN = clk * queryUIntParameter(timings, "WCK2CKPIN");
memSpec->tWCK2CK = clk * queryUIntParameter(timings, "WCK2CK");
memSpec->tWCK2DQO = clk * queryUIntParameter(timings, "WCK2DQO");
memSpec->tRTW = clk * queryUIntParameter(timings, "RTW");
memSpec->tWL = clk * queryUIntParameter(timings, "WL");
memSpec->tWCK2DQI = clk * queryUIntParameter(timings, "WCK2DQI");
memSpec->tWR = clk * queryUIntParameter(timings, "WR");
memSpec->tWTRS = clk * queryUIntParameter(timings, "WTRS");
memSpec->tWTRL = clk * queryUIntParameter(timings, "WTRL");
memSpec->tCKE = clk * queryUIntParameter(timings, "CKE");
memSpec->tPD = memSpec->tCKE;
memSpec->tXP = clk * queryUIntParameter(timings, "XP");
memSpec->tREFI = clk * queryUIntParameter(timings, "REFI");
memSpec->tREFIPB = clk * queryUIntParameter(timings, "REFIPB");
memSpec->tRFC = clk * queryUIntParameter(timings, "RFC");
memSpec->tRFCPB = clk * queryUIntParameter(timings, "RFCPB");
memSpec->tRREFD = clk * queryUIntParameter(timings, "RREFD");
memSpec->tXS = clk * queryUIntParameter(timings, "XS");
memSpec->tFAW = clk * queryUIntParameter(timings, "FAW");
memSpec->t32AW = clk * queryUIntParameter(timings, "32AW");
memSpec->tRDSRE = memSpec->tRL + memSpec->tWCK2CKPIN + memSpec->tWCK2CK
+ memSpec->tWCK2DQO + memSpec->BurstLength / memSpec->DataRate * clk;
memSpec->tWRSRE = memSpec->tWL + memSpec->tWCK2CKPIN + memSpec->tWCK2CK
+ memSpec->tWCK2DQI + memSpec->BurstLength / memSpec->DataRate * clk;
memSpec->tPPD = clk * queryUIntParameter(timings, "PPD");
memSpec->tLK = clk * queryUIntParameter(timings, "LK");
// Currents and voltages
// TODO: to be completed
}
void ConfigurationLoader::loadGDDR6(Configuration &config, XMLElement *xmlSpec)
{
MemSpecGDDR6 *memSpec = dynamic_cast<MemSpecGDDR6 *>(config.memSpec);
if (memSpec == nullptr)
SC_REPORT_FATAL("ConfigurationLoader", "Wrong MemSpec chosen");
// MemArchitecture
XMLElement *architecture = xmlSpec->FirstChildElement("memarchitecturespec");
memSpec->NumberOfRanks = queryUIntParameter(architecture, "nbrOfRanks");
memSpec->BanksPerRank = queryUIntParameter(architecture, "nbrOfBanks");
memSpec->GroupsPerRank = queryUIntParameter(architecture, "nbrOfBankGroups");
memSpec->BanksPerGroup = memSpec->BanksPerRank / memSpec->GroupsPerRank;
memSpec->NumberOfBanks = memSpec->BanksPerRank * memSpec->NumberOfRanks;
memSpec->NumberOfBankGroups = memSpec->GroupsPerRank * memSpec->NumberOfRanks;
// MemTimings specific for GDDR6
XMLElement *timings = xmlSpec->FirstChildElement("memtimingspec");
sc_time clk = memSpec->clk;
memSpec->tRP = clk * queryUIntParameter(timings, "RP");
memSpec->tRAS = clk * queryUIntParameter(timings, "RAS");
memSpec->tRC = clk * queryUIntParameter(timings, "RC");
memSpec->tRCDRD = clk * queryUIntParameter(timings, "RCDRD");
memSpec->tRCDWR = clk * queryUIntParameter(timings, "RCDWR");
memSpec->tRTP = clk * queryUIntParameter(timings, "RTP");
memSpec->tRRDS = clk * queryUIntParameter(timings, "RRDS");
memSpec->tRRDL = clk * queryUIntParameter(timings, "RRDL");
memSpec->tCCDS = clk * queryUIntParameter(timings, "CCDS");
memSpec->tCCDL = clk * queryUIntParameter(timings, "CCDL");
memSpec->tRL = clk * queryUIntParameter(timings, "RL");
memSpec->tWCK2CKPIN = clk * queryUIntParameter(timings, "WCK2CKPIN");
memSpec->tWCK2CK = clk * queryUIntParameter(timings, "WCK2CK");
memSpec->tWCK2DQO = clk * queryUIntParameter(timings, "WCK2DQO");
memSpec->tRTW = clk * queryUIntParameter(timings, "RTW");
memSpec->tWL = clk * queryUIntParameter(timings, "WL");
memSpec->tWCK2DQI = clk * queryUIntParameter(timings, "WCK2DQI");
memSpec->tWR = clk * queryUIntParameter(timings, "WR");
memSpec->tWTRS = clk * queryUIntParameter(timings, "WTRS");
memSpec->tWTRL = clk * queryUIntParameter(timings, "WTRL");
memSpec->tCKE = clk * queryUIntParameter(timings, "CKE");
memSpec->tPD = memSpec->tCKE;
memSpec->tCKESR = clk * queryUIntParameter(timings, "CKESR");
memSpec->tXP = clk * queryUIntParameter(timings, "XP");
memSpec->tREFI = clk * queryUIntParameter(timings, "REFI");
memSpec->tREFIPB = clk * queryUIntParameter(timings, "REFIPB");
memSpec->tRFC = clk * queryUIntParameter(timings, "RFC");
memSpec->tRFCPB = clk * queryUIntParameter(timings, "RFCPB");
memSpec->tRREFD = clk * queryUIntParameter(timings, "RREFD");
memSpec->tXS = clk * queryUIntParameter(timings, "XS");
memSpec->tFAW = clk * queryUIntParameter(timings, "FAW");
memSpec->tRDSRE = memSpec->tRL + memSpec->tWCK2CKPIN + memSpec->tWCK2CK
+ memSpec->tWCK2DQO + memSpec->BurstLength / memSpec->DataRate * clk;
memSpec->tWRSRE = memSpec->tWL + memSpec->tWCK2CKPIN + memSpec->tWCK2CK
+ memSpec->tWCK2DQI + memSpec->BurstLength / memSpec->DataRate * clk;
memSpec->tPPD = clk * queryUIntParameter(timings, "PPD");
memSpec->tLK = clk * queryUIntParameter(timings, "LK");
memSpec->tACTPDE = clk * queryUIntParameter(timings, "ACTPDE");
memSpec->tPREPDE = clk * queryUIntParameter(timings, "PREPDE");
memSpec->tREFPDE = clk * queryUIntParameter(timings, "REFPDE");
// Currents and voltages
// TODO: to be completed
}

View File

@@ -75,6 +75,9 @@ private:
static void loadWideIO(Configuration &config, tinyxml2::XMLElement *memspec);
static void loadWideIO2(Configuration &config, tinyxml2::XMLElement *memspec);
static void loadHBM2(Configuration &config, tinyxml2::XMLElement *memspec);
static void loadGDDR5(Configuration &config, tinyxml2::XMLElement *memspec);
static void loadGDDR5X(Configuration &config, tinyxml2::XMLElement *memspec);
static void loadGDDR6(Configuration &config, tinyxml2::XMLElement *memspec);
};

View File

@@ -0,0 +1,88 @@
/*
* Copyright (c) 2019, University of 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 "MemSpecGDDR5.h"
sc_time MemSpecGDDR5::getRefreshIntervalAB() const
{
return tREFI;
}
sc_time MemSpecGDDR5::getRefreshIntervalPB() const
{
return tREFIPB;
}
sc_time MemSpecGDDR5::getExecutionTime(Command command, const tlm_generic_payload &payload) const
{
if (command == Command::PRE || command == Command::PREA)
return tRP;
else if (command == Command::ACT)
{
if (payload.get_command() == TLM_READ_COMMAND)
return tRCDRD + clk;
else
return tRCDWR + clk;
}
else if (command == Command::RD || command == Command::RDA)
return tCL + tWCK2CKPIN + tWCK2CK + tWCK2DQO + getReadAccessTime();
else if (command == Command::WR || command == Command::WRA)
return tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI + getWriteAccessTime();
else if (command == Command::REFA)
return tRFC;
else if (command == Command::REFB)
return tRFCPB;
else
{
SC_REPORT_FATAL("getExecutionTime",
"command not known or command doesn't have a fixed execution time");
return SC_ZERO_TIME;
}
}
TimeInterval MemSpecGDDR5::getIntervalOnDataStrobe(Command command) const
{
if (command == Command::RD || command == Command::RDA)
return TimeInterval(sc_time_stamp() + tCL + tWCK2CKPIN + tWCK2CK + tWCK2DQO,
sc_time_stamp() + tCL + tWCK2CKPIN + tWCK2CK + tWCK2DQO + getReadAccessTime());
else if (command == Command::WR || command == Command::WRA)
return TimeInterval(sc_time_stamp() + tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI,
sc_time_stamp() + tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI + getWriteAccessTime());
else
{
SC_REPORT_FATAL("MemSpecGDDR5", "Method was called with invalid argument");
return TimeInterval();
}
}

View File

@@ -0,0 +1,90 @@
/*
* Copyright (c) 2019, University of 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 MEMSPECGDDR5_H
#define MEMSPECGDDR5_H
#include "MemSpec.h"
struct MemSpecGDDR5 final : public MemSpec
{
// Memspec Variables:
sc_time tRP;
sc_time tRAS;
sc_time tRC;
sc_time tRCDRD;
sc_time tRCDWR;
sc_time tRTP;
sc_time tRRDS;
sc_time tRRDL;
sc_time tCCDS;
sc_time tCCDL;
sc_time tCL;
sc_time tWCK2CKPIN;
sc_time tWCK2CK;
sc_time tWCK2DQO;
sc_time tRTW;
sc_time tWL;
sc_time tWCK2DQI;
sc_time tWR;
sc_time tWTRS;
sc_time tWTRL;
sc_time tCKE;
sc_time tPD; // = tCKE;
sc_time tXPN;
sc_time tREFI;
sc_time tREFIPB;
sc_time tRFC;
sc_time tRFCPB;
sc_time tRREFD;
sc_time tXS;
sc_time tFAW;
sc_time t32AW;
sc_time tRDSRE; // = tCL + tWCK2CKPIN + tWCK2CK + tWCK2DQO + BurstLength / DataRate * tCK;
sc_time tWRSRE; // = tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI + BurstLength / DataRate * tCK;
sc_time tPPD;
sc_time tLK;
// Currents and Voltages:
// TODO: to be completed
virtual sc_time getRefreshIntervalPB() const override;
virtual sc_time getRefreshIntervalAB() const override;
virtual sc_time getExecutionTime(Command, const tlm_generic_payload &) const override;
virtual TimeInterval getIntervalOnDataStrobe(Command) const override;
};
#endif // MEMSPECGDDR5_H

View File

@@ -0,0 +1,88 @@
/*
* Copyright (c) 2019, University of 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 "MemSpecGDDR5X.h"
sc_time MemSpecGDDR5X::getRefreshIntervalAB() const
{
return tREFI;
}
sc_time MemSpecGDDR5X::getRefreshIntervalPB() const
{
return tREFIPB;
}
sc_time MemSpecGDDR5X::getExecutionTime(Command command, const tlm_generic_payload &payload) const
{
if (command == Command::PRE || command == Command::PREA)
return tRP;
else if (command == Command::ACT)
{
if (payload.get_command() == TLM_READ_COMMAND)
return tRCDRD + clk;
else
return tRCDWR + clk;
}
else if (command == Command::RD || command == Command::RDA)
return tRL + tWCK2CKPIN + tWCK2CK + tWCK2DQO + getReadAccessTime();
else if (command == Command::WR || command == Command::WRA)
return tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI + getWriteAccessTime();
else if (command == Command::REFA)
return tRFC;
else if (command == Command::REFB)
return tRFCPB;
else
{
SC_REPORT_FATAL("getExecutionTime",
"command not known or command doesn't have a fixed execution time");
return SC_ZERO_TIME;
}
}
TimeInterval MemSpecGDDR5X::getIntervalOnDataStrobe(Command command) const
{
if (command == Command::RD || command == Command::RDA)
return TimeInterval(sc_time_stamp() + tRL + tWCK2CKPIN + tWCK2CK + tWCK2DQO,
sc_time_stamp() + tRL + tWCK2CKPIN + tWCK2CK + tWCK2DQO + getReadAccessTime());
else if (command == Command::WR || command == Command::WRA)
return TimeInterval(sc_time_stamp() + tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI,
sc_time_stamp() + tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI + getWriteAccessTime());
else
{
SC_REPORT_FATAL("MemSpecGDDR5X", "Method was called with invalid argument");
return TimeInterval();
}
}

View File

@@ -0,0 +1,90 @@
/*
* Copyright (c) 2019, University of 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 MEMSPECGDDR5X_H
#define MEMSPECGDDR5X_H
#include "MemSpec.h"
struct MemSpecGDDR5X final : public MemSpec
{
// Memspec Variables:
sc_time tRP;
sc_time tRAS;
sc_time tRC;
sc_time tRCDRD;
sc_time tRCDWR;
sc_time tRTP;
sc_time tRRDS;
sc_time tRRDL;
sc_time tCCDS;
sc_time tCCDL;
sc_time tRL;
sc_time tWCK2CKPIN;
sc_time tWCK2CK;
sc_time tWCK2DQO;
sc_time tRTW;
sc_time tWL;
sc_time tWCK2DQI;
sc_time tWR;
sc_time tWTRS;
sc_time tWTRL;
sc_time tCKE;
sc_time tPD; // = tCKE;
sc_time tXP;
sc_time tREFI;
sc_time tREFIPB;
sc_time tRFC;
sc_time tRFCPB;
sc_time tRREFD;
sc_time tXS;
sc_time tFAW;
sc_time t32AW;
sc_time tRDSRE; // = tCL + tWCK2CKPIN + tWCK2CK + tWCK2DQO + BurstLength / DataRate * tCK;
sc_time tWRSRE; // = tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI + BurstLength / DataRate * tCK;
sc_time tPPD;
sc_time tLK;
// Currents and Voltages:
// TODO: to be completed
virtual sc_time getRefreshIntervalPB() const override;
virtual sc_time getRefreshIntervalAB() const override;
virtual sc_time getExecutionTime(Command, const tlm_generic_payload &) const override;
virtual TimeInterval getIntervalOnDataStrobe(Command) const override;
};
#endif // MEMSPECGDDR5X_H

View File

@@ -0,0 +1,88 @@
/*
* Copyright (c) 2019, University of 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 "MemSpecGDDR6.h"
sc_time MemSpecGDDR6::getRefreshIntervalAB() const
{
return tREFI;
}
sc_time MemSpecGDDR6::getRefreshIntervalPB() const
{
return tREFIPB;
}
sc_time MemSpecGDDR6::getExecutionTime(Command command, const tlm_generic_payload &payload) const
{
if (command == Command::PRE || command == Command::PREA)
return tRP;
else if (command == Command::ACT)
{
if (payload.get_command() == TLM_READ_COMMAND)
return tRCDRD + clk;
else
return tRCDWR + clk;
}
else if (command == Command::RD || command == Command::RDA)
return tRL + tWCK2CKPIN + tWCK2CK + tWCK2DQO + getReadAccessTime();
else if (command == Command::WR || command == Command::WRA)
return tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI + getWriteAccessTime();
else if (command == Command::REFA)
return tRFC;
else if (command == Command::REFB)
return tRFCPB;
else
{
SC_REPORT_FATAL("getExecutionTime",
"command not known or command doesn't have a fixed execution time");
return SC_ZERO_TIME;
}
}
TimeInterval MemSpecGDDR6::getIntervalOnDataStrobe(Command command) const
{
if (command == Command::RD || command == Command::RDA)
return TimeInterval(sc_time_stamp() + tRL + tWCK2CKPIN + tWCK2CK + tWCK2DQO,
sc_time_stamp() + tRL + tWCK2CKPIN + tWCK2CK + tWCK2DQO + getReadAccessTime());
else if (command == Command::WR || command == Command::WRA)
return TimeInterval(sc_time_stamp() + tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI,
sc_time_stamp() + tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI + getWriteAccessTime());
else
{
SC_REPORT_FATAL("MemSpecGDDR6", "Method was called with invalid argument");
return TimeInterval();
}
}

View File

@@ -0,0 +1,93 @@
/*
* Copyright (c) 2019, University of 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 MEMSPECGDDR6_H
#define MEMSPECGDDR6_H
#include "MemSpec.h"
struct MemSpecGDDR6 final : public MemSpec
{
// Memspec Variables:
sc_time tRP;
sc_time tRAS;
sc_time tRC;
sc_time tRCDRD;
sc_time tRCDWR;
sc_time tRTP;
sc_time tRRDS;
sc_time tRRDL;
sc_time tCCDS;
sc_time tCCDL;
sc_time tRL;
sc_time tWCK2CKPIN;
sc_time tWCK2CK;
sc_time tWCK2DQO;
sc_time tRTW;
sc_time tWL;
sc_time tWCK2DQI;
sc_time tWR;
sc_time tWTRS;
sc_time tWTRL;
sc_time tCKE;
sc_time tPD; // = tCKE;
sc_time tCKESR;
sc_time tXP;
sc_time tREFI;
sc_time tREFIPB;
sc_time tRFC;
sc_time tRFCPB;
sc_time tRREFD;
sc_time tXS;
sc_time tFAW;
sc_time tRDSRE; // = tCL + tWCK2CKPIN + tWCK2CK + tWCK2DQO + BurstLength / DataRate * tCK;
sc_time tWRSRE; // = tWL + tWCK2CKPIN + tWCK2CK + tWCK2DQI + BurstLength / DataRate * tCK;
sc_time tPPD;
sc_time tLK;
sc_time tACTPDE;
sc_time tPREPDE;
sc_time tREFPDE;
// Currents and Voltages:
// TODO: to be completed
virtual sc_time getRefreshIntervalPB() const override;
virtual sc_time getRefreshIntervalAB() const override;
virtual sc_time getExecutionTime(Command, const tlm_generic_payload &) const override;
virtual TimeInterval getIntervalOnDataStrobe(Command) const override;
};
#endif // MEMSPECGDDR6_H

View File

@@ -66,12 +66,12 @@ struct MemSpecHBM2 final : public MemSpec
sc_time tRTW;
sc_time tXP;
sc_time tCKE;
sc_time tPD = tCKE;
sc_time tRDPDE = tRL + tPL + (BurstLength / 2) * clk + clk;
sc_time tWRPDE = tWL + tPL + (BurstLength / 2) * clk + clk + tWR;
sc_time tWRAPDE = tWL + tPL + (BurstLength / 2) * clk + clk + tWR;
sc_time tCKESR = tCKE + clk;
sc_time tRDSRE = tRL + tPL + (BurstLength / 2) * clk + clk;
sc_time tPD; // = tCKE;
sc_time tRDPDE; // = tRL + tPL + (BurstLength / DataRate) * clk + clk;
sc_time tWRPDE; // = tWL + tPL + (BurstLength / DataRate) * clk + clk + tWR;
sc_time tWRAPDE; // = tWL + tPL + (BurstLength / DataRate) * clk + clk + tWR;
sc_time tCKESR; // = tCKE + clk;
sc_time tRDSRE; // = tRL + tPL + (BurstLength / DataRate) * clk + clk;
sc_time tXS;
sc_time tRFC;
sc_time tRFCSB;

View File

@@ -47,6 +47,9 @@
#include "checker/CheckerLPDDR4.h"
#include "checker/CheckerWideIO2.h"
#include "checker/CheckerHBM2.h"
#include "checker/CheckerGDDR5.h"
#include "checker/CheckerGDDR5X.h"
#include "checker/CheckerGDDR6.h"
#include "refresh/RefreshManager.h"
#include "refresh/RefreshManagerDummy.h"
#include "refresh/RefreshManagerBankwise.h"
@@ -74,6 +77,12 @@ Controller::Controller(sc_module_name name) :
checker = new CheckerWideIO2();
else if (memSpec->MemoryType == "HBM2")
checker = new CheckerHBM2();
else if (memSpec->MemoryType == "GDDR5")
checker = new CheckerGDDR5();
else if (memSpec->MemoryType == "GDDR5X")
checker = new CheckerGDDR5X();
else if (memSpec->MemoryType == "GDDR6")
checker = new CheckerGDDR6();
else
SC_REPORT_FATAL("Controller", "Unsupported DRAM type");

View File

@@ -58,9 +58,6 @@ private:
// Four activate window
std::vector<std::queue<sc_time>> lastActivates;
// PowerDown TODO: Implement this method?
//sc_time getTimeConstraintToEnterPowerDown(Command lastCmd, Command pdnCmd) const;
};
#endif // CHECKERDDR3_H

View File

@@ -61,9 +61,6 @@ private:
std::vector<std::queue<sc_time>> lastActivates;
sc_time burstClocks;
// PowerDown TODO: Implement this method?
//sc_time getTimeConstraintToEnterPowerDown(Command lastCmd, Command pdnCmd) const;
};
#endif // CHECKERDDR4_H

View File

@@ -0,0 +1,394 @@
/*
* Copyright (c) 2019, University of 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 "CheckerGDDR5.h"
CheckerGDDR5::CheckerGDDR5()
{
Configuration &config = Configuration::getInstance();
memSpec = dynamic_cast<MemSpecGDDR5 *>(config.memSpec);
if (memSpec == nullptr)
SC_REPORT_FATAL("CheckerGDDR5", "Wrong MemSpec chosen");
lastScheduledByCommandAndBank = std::vector<std::vector<sc_time>>
(numberOfCommands(), std::vector<sc_time>(memSpec->NumberOfBanks));
lastScheduledByCommandAndBankGroup = std::vector<std::vector<sc_time>>
(numberOfCommands(), std::vector<sc_time>(memSpec->NumberOfBankGroups));
lastScheduledByCommandAndRank = std::vector<std::vector<sc_time>>
(numberOfCommands(), std::vector<sc_time>(memSpec->NumberOfRanks));
lastScheduledByCommand = std::vector<sc_time>(numberOfCommands());
last4Activates = std::vector<std::queue<sc_time>>(memSpec->NumberOfRanks);
last32Activates = std::vector<std::queue<sc_time>>(memSpec->NumberOfRanks);
burstClocks = (memSpec->BurstLength / memSpec->DataRate) * memSpec->clk;
}
sc_time CheckerGDDR5::delayToSatisfyConstraints(Command command, Rank rank, BankGroup bankgroup, Bank bank) const
{
sc_time lastCommandStart;
sc_time earliestTimeToStart = sc_time_stamp();
if (command == Command::ACT)
{
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::ACT][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDL);
lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDS);
lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWR + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC);
lastCommandStart = lastScheduledByCommandAndBank[Command::REFB][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCPB);
lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD);
if (last4Activates[rank.ID()].size() == 4)
earliestTimeToStart = std::max(earliestTimeToStart, last4Activates[rank.ID()].front() + memSpec->tFAW);
if (last32Activates[rank.ID()].size() == 32)
earliestTimeToStart = std::max(earliestTimeToStart, last32Activates[rank.ID()].front() + memSpec->t32AW);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk);
}
else if (command == Command::RD)
{
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDRD);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL);
lastCommandStart = lastScheduledByCommand[Command::RD];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL);
lastCommandStart = lastScheduledByCommand[Command::RDA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWTRL);
lastCommandStart = lastScheduledByCommand[Command::WR];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWTRS);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWTRL);
lastCommandStart = lastScheduledByCommand[Command::WRA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWTRS);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk);
}
else if (command == Command::RDA)
{
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDRD);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL);
lastCommandStart = lastScheduledByCommand[Command::RD];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL);
lastCommandStart = lastScheduledByCommand[Command::RDA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS);
lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + std::max(memSpec->tWR - memSpec->tRTP, memSpec->tWTRL));
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWTRL);
lastCommandStart = lastScheduledByCommand[Command::WR];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWTRS);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWTRL);
lastCommandStart = lastScheduledByCommand[Command::WRA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWTRS);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk);
}
else if (command == Command::WR || command == Command::WRA)
{
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDWR);
lastCommandStart = lastScheduledByCommand[Command::RD];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW);
lastCommandStart = lastScheduledByCommand[Command::RDA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL);
lastCommandStart = lastScheduledByCommand[Command::WR];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL);
lastCommandStart = lastScheduledByCommand[Command::WRA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk);
}
else if (command == Command::PRE)
{
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS);
lastCommandStart = lastScheduledByCommandAndBank[Command::RD][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP);
lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWR);
lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk);
}
else if (command == Command::PREA)
{
lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()];
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS);
lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP);
lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP);
lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWR);
lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWR);
lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk);
}
else if (command == Command::REFA)
{
lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC);
lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWR + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk);
}
else if (command == Command::REFB)
{
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::ACT][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDL);
lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDS);
lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWR + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP);
// lastCommandStart = lastScheduledByCommandAndBank[Command::REFB][bank.ID()];
// if (lastCommandStart != SC_ZERO_TIME)
// earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCSB);
lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
{
if (bankwiseRefreshCounter == 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);
if (last32Activates[rank.ID()].size() == 32)
earliestTimeToStart = std::max(earliestTimeToStart, last32Activates[rank.ID()].front() + memSpec->t32AW);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk);
}
else
{
reportFatal("CheckerGDDR5", "Unknown command!");
}
return (earliestTimeToStart - sc_time_stamp());
}
void CheckerGDDR5::insert(Command command, Rank rank, BankGroup bankgroup, Bank bank)
{
PRINTDEBUGMESSAGE("CheckerGDDR5", "Changing state on bank " + bank.ID()
+ " command is " + commandToString(command));
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();
lastCommandOnBus = sc_time_stamp();
if (command == Command::ACT || command == Command::REFB)
{
if (last4Activates[rank.ID()].size() == 4)
last4Activates[rank.ID()].pop();
last4Activates[rank.ID()].push(lastCommandOnBus);
if (last32Activates[rank.ID()].size() == 32)
last32Activates[rank.ID()].pop();
last32Activates[rank.ID()].push(lastCommandOnBus);
}
if (command == Command::REFB)
bankwiseRefreshCounter = (bankwiseRefreshCounter + 1) % memSpec->BanksPerRank;
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2019, University of 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 CHECKERGDDR5_H
#define CHECKERGDDR5_H
#include "CheckerIF.h"
#include <queue>
#include <vector>
#include "../../configuration/memspec/MemSpecGDDR5.h"
#include "../../configuration/Configuration.h"
class CheckerGDDR5 final : public CheckerIF
{
public:
CheckerGDDR5();
virtual sc_time delayToSatisfyConstraints(Command, Rank, BankGroup, Bank) const override;
virtual void insert(Command, Rank, BankGroup, Bank) override;
private:
const MemSpecGDDR5 *memSpec;
std::vector<std::vector<sc_time>> lastScheduledByCommandAndBank;
std::vector<std::vector<sc_time>> lastScheduledByCommandAndBankGroup;
std::vector<std::vector<sc_time>> lastScheduledByCommandAndRank;
std::vector<sc_time> lastScheduledByCommand;
sc_time lastCommandOnBus;
// 4 and 32 activate window
std::vector<std::queue<sc_time>> last4Activates;
std::vector<std::queue<sc_time>> last32Activates;
sc_time burstClocks;
unsigned bankwiseRefreshCounter = 0;
};
#endif // CHECKERGDDR5_H

View File

@@ -0,0 +1,394 @@
/*
* Copyright (c) 2019, University of 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 "CheckerGDDR5X.h"
CheckerGDDR5X::CheckerGDDR5X()
{
Configuration &config = Configuration::getInstance();
memSpec = dynamic_cast<MemSpecGDDR5X *>(config.memSpec);
if (memSpec == nullptr)
SC_REPORT_FATAL("CheckerGDDR5X", "Wrong MemSpec chosen");
lastScheduledByCommandAndBank = std::vector<std::vector<sc_time>>
(numberOfCommands(), std::vector<sc_time>(memSpec->NumberOfBanks));
lastScheduledByCommandAndBankGroup = std::vector<std::vector<sc_time>>
(numberOfCommands(), std::vector<sc_time>(memSpec->NumberOfBankGroups));
lastScheduledByCommandAndRank = std::vector<std::vector<sc_time>>
(numberOfCommands(), std::vector<sc_time>(memSpec->NumberOfRanks));
lastScheduledByCommand = std::vector<sc_time>(numberOfCommands());
last4Activates = std::vector<std::queue<sc_time>>(memSpec->NumberOfRanks);
last32Activates = std::vector<std::queue<sc_time>>(memSpec->NumberOfRanks);
burstClocks = (memSpec->BurstLength / memSpec->DataRate) * memSpec->clk;
}
sc_time CheckerGDDR5X::delayToSatisfyConstraints(Command command, Rank rank, BankGroup bankgroup, Bank bank) const
{
sc_time lastCommandStart;
sc_time earliestTimeToStart = sc_time_stamp();
if (command == Command::ACT)
{
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::ACT][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDL);
lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDS);
lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWR + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC);
lastCommandStart = lastScheduledByCommandAndBank[Command::REFB][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCPB);
lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD);
if (last4Activates[rank.ID()].size() == 4)
earliestTimeToStart = std::max(earliestTimeToStart, last4Activates[rank.ID()].front() + memSpec->tFAW);
if (last32Activates[rank.ID()].size() == 32)
earliestTimeToStart = std::max(earliestTimeToStart, last32Activates[rank.ID()].front() + memSpec->t32AW);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk);
}
else if (command == Command::RD)
{
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDRD);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL);
lastCommandStart = lastScheduledByCommand[Command::RD];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL);
lastCommandStart = lastScheduledByCommand[Command::RDA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWTRL);
lastCommandStart = lastScheduledByCommand[Command::WR];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWTRS);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWTRL);
lastCommandStart = lastScheduledByCommand[Command::WRA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWTRS);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk);
}
else if (command == Command::RDA)
{
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDRD);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL);
lastCommandStart = lastScheduledByCommand[Command::RD];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL);
lastCommandStart = lastScheduledByCommand[Command::RDA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS);
lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + std::max(memSpec->tWR - memSpec->tRTP, memSpec->tWTRL));
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWTRL);
lastCommandStart = lastScheduledByCommand[Command::WR];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWTRS);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWTRL);
lastCommandStart = lastScheduledByCommand[Command::WRA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWTRS);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk);
}
else if (command == Command::WR || command == Command::WRA)
{
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDWR);
lastCommandStart = lastScheduledByCommand[Command::RD];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW);
lastCommandStart = lastScheduledByCommand[Command::RDA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL);
lastCommandStart = lastScheduledByCommand[Command::WR];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL);
lastCommandStart = lastScheduledByCommand[Command::WRA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk);
}
else if (command == Command::PRE)
{
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS);
lastCommandStart = lastScheduledByCommandAndBank[Command::RD][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP);
lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWR);
lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk);
}
else if (command == Command::PREA)
{
lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()];
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS);
lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP);
lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP);
lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWR);
lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWR);
lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk);
}
else if (command == Command::REFA)
{
lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC);
lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWR + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk);
}
else if (command == Command::REFB)
{
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::ACT][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDL);
lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDS);
lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWR + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP);
// lastCommandStart = lastScheduledByCommandAndBank[Command::REFB][bank.ID()];
// if (lastCommandStart != SC_ZERO_TIME)
// earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCSB);
lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
{
if (bankwiseRefreshCounter == 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);
if (last32Activates[rank.ID()].size() == 32)
earliestTimeToStart = std::max(earliestTimeToStart, last32Activates[rank.ID()].front() + memSpec->t32AW);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk);
}
else
{
reportFatal("CheckerGDDR5X", "Unknown command!");
}
return (earliestTimeToStart - sc_time_stamp());
}
void CheckerGDDR5X::insert(Command command, Rank rank, BankGroup bankgroup, Bank bank)
{
PRINTDEBUGMESSAGE("CheckerGDDR5X", "Changing state on bank " + bank.ID()
+ " command is " + commandToString(command));
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();
lastCommandOnBus = sc_time_stamp();
if (command == Command::ACT || command == Command::REFB)
{
if (last4Activates[rank.ID()].size() == 4)
last4Activates[rank.ID()].pop();
last4Activates[rank.ID()].push(lastCommandOnBus);
if (last32Activates[rank.ID()].size() == 32)
last32Activates[rank.ID()].pop();
last32Activates[rank.ID()].push(lastCommandOnBus);
}
if (command == Command::REFB)
bankwiseRefreshCounter = (bankwiseRefreshCounter + 1) % memSpec->BanksPerRank;
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2019, University of 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 CHECKERGDDR5X_H
#define CHECKERGDDR5X_H
#include "CheckerIF.h"
#include <queue>
#include <vector>
#include "../../configuration/memspec/MemSpecGDDR5X.h"
#include "../../configuration/Configuration.h"
class CheckerGDDR5X final : public CheckerIF
{
public:
CheckerGDDR5X();
virtual sc_time delayToSatisfyConstraints(Command, Rank, BankGroup, Bank) const override;
virtual void insert(Command, Rank, BankGroup, Bank) override;
private:
const MemSpecGDDR5X *memSpec;
std::vector<std::vector<sc_time>> lastScheduledByCommandAndBank;
std::vector<std::vector<sc_time>> lastScheduledByCommandAndBankGroup;
std::vector<std::vector<sc_time>> lastScheduledByCommandAndRank;
std::vector<sc_time> lastScheduledByCommand;
sc_time lastCommandOnBus;
// 4 and 32 activate window
std::vector<std::queue<sc_time>> last4Activates;
std::vector<std::queue<sc_time>> last32Activates;
sc_time burstClocks;
unsigned bankwiseRefreshCounter = 0;
};
#endif // CHECKERGDDR5X_H

View File

@@ -0,0 +1,383 @@
/*
* Copyright (c) 2019, University of 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 "CheckerGDDR6.h"
CheckerGDDR6::CheckerGDDR6()
{
Configuration &config = Configuration::getInstance();
memSpec = dynamic_cast<MemSpecGDDR6 *>(config.memSpec);
if (memSpec == nullptr)
SC_REPORT_FATAL("CheckerGDDR6", "Wrong MemSpec chosen");
lastScheduledByCommandAndBank = std::vector<std::vector<sc_time>>
(numberOfCommands(), std::vector<sc_time>(memSpec->NumberOfBanks));
lastScheduledByCommandAndBankGroup = std::vector<std::vector<sc_time>>
(numberOfCommands(), std::vector<sc_time>(memSpec->NumberOfBankGroups));
lastScheduledByCommandAndRank = std::vector<std::vector<sc_time>>
(numberOfCommands(), std::vector<sc_time>(memSpec->NumberOfRanks));
lastScheduledByCommand = std::vector<sc_time>(numberOfCommands());
lastActivates = std::vector<std::queue<sc_time>>(memSpec->NumberOfRanks);
burstClocks = (memSpec->BurstLength / memSpec->DataRate) * memSpec->clk;
}
sc_time CheckerGDDR6::delayToSatisfyConstraints(Command command, Rank rank, BankGroup bankgroup, Bank bank) const
{
sc_time lastCommandStart;
sc_time earliestTimeToStart = sc_time_stamp();
if (command == Command::ACT)
{
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::ACT][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDL);
lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDS);
lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWR + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC);
lastCommandStart = lastScheduledByCommandAndBank[Command::REFB][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCPB);
lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD);
if (lastActivates[rank.ID()].size() == 4)
earliestTimeToStart = std::max(earliestTimeToStart, lastActivates[rank.ID()].front() + memSpec->tFAW);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk);
}
else if (command == Command::RD)
{
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDRD);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL);
lastCommandStart = lastScheduledByCommand[Command::RD];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL);
lastCommandStart = lastScheduledByCommand[Command::RDA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWTRL);
lastCommandStart = lastScheduledByCommand[Command::WR];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWTRS);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWTRL);
lastCommandStart = lastScheduledByCommand[Command::WRA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWTRS);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk);
}
else if (command == Command::RDA)
{
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDRD);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL);
lastCommandStart = lastScheduledByCommand[Command::RD];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL);
lastCommandStart = lastScheduledByCommand[Command::RDA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS);
lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + std::max(memSpec->tWR - memSpec->tRTP, memSpec->tWTRL));
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWTRL);
lastCommandStart = lastScheduledByCommand[Command::WR];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWTRS);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWTRL);
lastCommandStart = lastScheduledByCommand[Command::WRA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWTRS);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk);
}
else if (command == Command::WR || command == Command::WRA)
{
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCDWR);
lastCommandStart = lastScheduledByCommand[Command::RD];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW);
lastCommandStart = lastScheduledByCommand[Command::RDA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTW);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL);
lastCommandStart = lastScheduledByCommand[Command::WR];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDL);
lastCommandStart = lastScheduledByCommand[Command::WRA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCDS);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk);
}
else if (command == Command::PRE)
{
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS);
lastCommandStart = lastScheduledByCommandAndBank[Command::RD][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP);
lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWR);
lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk);
}
else if (command == Command::PREA)
{
lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()];
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS);
lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP);
lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP);
lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWR);
lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWR);
lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk);
}
else if (command == Command::REFA)
{
lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC);
lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWR + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk);
}
else if (command == Command::REFB)
{
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC);
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::ACT][bankgroup.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDL);
lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRDS);
lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks + memSpec->tWR + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP);
// lastCommandStart = lastScheduledByCommandAndBank[Command::REFB][bank.ID()];
// if (lastCommandStart != SC_ZERO_TIME)
// earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCSB);
lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
{
if (bankwiseRefreshCounter == 0)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCPB);
else
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRREFD);
}
if (lastActivates[rank.ID()].size() == 4)
earliestTimeToStart = std::max(earliestTimeToStart, lastActivates[rank.ID()].front() + memSpec->tFAW);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk);
}
else
{
reportFatal("CheckerGDDR6", "Unknown command!");
}
return (earliestTimeToStart - sc_time_stamp());
}
void CheckerGDDR6::insert(Command command, Rank rank, BankGroup bankgroup, Bank bank)
{
PRINTDEBUGMESSAGE("CheckerGDDR6", "Changing state on bank " + bank.ID()
+ " command is " + commandToString(command));
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();
lastCommandOnBus = sc_time_stamp();
if (command == Command::ACT || command == Command::REFB)
{
if (lastActivates[rank.ID()].size() == 4)
lastActivates[rank.ID()].pop();
lastActivates[rank.ID()].push(lastCommandOnBus);
}
if (command == Command::REFB)
bankwiseRefreshCounter = (bankwiseRefreshCounter + 1) % memSpec->BanksPerRank;
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 2019, University of 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 CHECKERGDDR6_H
#define CHECKERGDDR6_H
#include "CheckerIF.h"
#include <queue>
#include <vector>
#include "../../configuration/memspec/MemSpecGDDR6.h"
#include "../../configuration/Configuration.h"
class CheckerGDDR6 final : public CheckerIF
{
public:
CheckerGDDR6();
virtual sc_time delayToSatisfyConstraints(Command, Rank, BankGroup, Bank) const override;
virtual void insert(Command, Rank, BankGroup, Bank) override;
private:
const MemSpecGDDR6 *memSpec;
std::vector<std::vector<sc_time>> lastScheduledByCommandAndBank;
std::vector<std::vector<sc_time>> lastScheduledByCommandAndBankGroup;
std::vector<std::vector<sc_time>> lastScheduledByCommandAndRank;
std::vector<sc_time> lastScheduledByCommand;
sc_time lastCommandOnBus;
// four activate window
std::vector<std::queue<sc_time>> lastActivates;
sc_time burstClocks;
unsigned bankwiseRefreshCounter = 0;
};
#endif // CHECKERGDDR6_H

View File

@@ -64,9 +64,6 @@ private:
sc_time burstClocks;
unsigned bankwiseRefreshCounter = 0;
// PowerDown TODO: Implement this method?
//sc_time getTimeConstraintToEnterPowerDown(Command lastCmd, Command pdnCmd) const;
};
#endif // CHECKERHBM2_H

View File

@@ -48,9 +48,6 @@ public:
virtual sc_time delayToSatisfyConstraints(Command, Rank, BankGroup, Bank) const = 0;
virtual void insert(Command, Rank, BankGroup, Bank) = 0;
// PowerDown TODO: Implement this method?
//sc_time getTimeConstraintToEnterPowerDown(Command lastCmd, Command pdnCmd) const;
};
#endif // CHECKERIF_H

View File

@@ -58,9 +58,6 @@ private:
// Four activate window
std::vector<std::queue<sc_time>> lastActivates;
// PowerDown TODO: Implement this method?
//sc_time getTimeConstraintToEnterPowerDown(Command lastCmd, Command pdnCmd) const;
};
#endif // CHECKERLPDDR4_H

View File

@@ -60,9 +60,6 @@ private:
std::vector<std::queue<sc_time>> lastActivates;
sc_time burstClocks;
// PowerDown TODO: Implement this method?
//sc_time getTimeConstraintToEnterPowerDown(Command lastCmd, Command pdnCmd) const;
};
#endif // CHECKERWIDEIO_H

View File

@@ -58,9 +58,6 @@ private:
// Four activate window
std::vector<std::queue<sc_time>> lastActivates;
// PowerDown TODO: Implement this method?
//sc_time getTimeConstraintToEnterPowerDown(Command lastCmd, Command pdnCmd) const;
};
#endif // CHECKERWIDEIO2_H

View File

@@ -59,6 +59,9 @@
#include "dram/DramLPDDR4.h"
#include "dram/DramWideIO2.h"
#include "dram/DramHBM2.h"
#include "dram/DramGDDR5.h"
#include "dram/DramGDDR5X.h"
#include "dram/DramGDDR6.h"
#include "../controller/Controller.h"
#include "../controller/ControllerRecordable.h"
@@ -306,6 +309,27 @@ void DRAMSys::instantiateModules(const string &traceName,
else
dram = new DramHBM2(str.c_str());
}
else if (memoryType == "GDDR5")
{
if (recordingEnabled)
dram = new DramRecordable<DramGDDR5>(str.c_str(), tlmRecorders[i]);
else
dram = new DramGDDR5(str.c_str());
}
else if (memoryType == "GDDR5X")
{
if (recordingEnabled)
dram = new DramRecordable<DramGDDR5X>(str.c_str(), tlmRecorders[i]);
else
dram = new DramGDDR5X(str.c_str());
}
else if (memoryType == "GDDR6")
{
if (recordingEnabled)
dram = new DramRecordable<DramGDDR6>(str.c_str(), tlmRecorders[i]);
else
dram = new DramGDDR6(str.c_str());
}
else
{
SC_REPORT_FATAL("DRAMSys", "Unsupported DRAM type");

View File

@@ -37,7 +37,6 @@
#define DRAMDDR3_H
#include <systemc.h>
#include <tlm.h>
#include "Dram.h"
class DramDDR3 : public Dram

View File

@@ -37,7 +37,6 @@
#define DRAMDDR4_H
#include <systemc.h>
#include <tlm.h>
#include "Dram.h"
class DramDDR4 : public Dram

View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 2019, University of 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 "DramGDDR5.h"
#include "Dram.h"
#include "../../configuration/Configuration.h"
#include "../../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h"
#include "../../configuration/memspec/MemSpecGDDR5.h"
DramGDDR5::DramGDDR5(sc_module_name name) : Dram(name)
{
if (StoreMode == StorageMode::ErrorModel)
SC_REPORT_FATAL("DramGDDR5", "Error Model not supported for GDDR5");
// Parameters for DRAMPower
MemSpecGDDR5 *memSpec = dynamic_cast<MemSpecGDDR5 *>(this->memSpec);
if (memSpec == nullptr)
SC_REPORT_FATAL("DramGDDR5", "Wrong MemSpec chosen");
if (Configuration::getInstance().PowerAnalysis)
SC_REPORT_FATAL("DramGDDR5", "DRAMPower not supported for GDDR5");
else
DRAMPower = new libDRAMPowerDummy();
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (c) 2019, University of 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 DRAMGDDR5_H
#define DRAMGDDR5_H
#include <systemc.h>
#include "Dram.h"
class DramGDDR5 : public Dram
{
public:
DramGDDR5(sc_module_name);
SC_HAS_PROCESS(DramGDDR5);
virtual ~DramGDDR5() {}
};
#endif // DRAMGDDR5_H

View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 2019, University of 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 "DramGDDR5X.h"
#include "Dram.h"
#include "../../configuration/Configuration.h"
#include "../../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h"
#include "../../configuration/memspec/MemSpecGDDR5X.h"
DramGDDR5X::DramGDDR5X(sc_module_name name) : Dram(name)
{
if (StoreMode == StorageMode::ErrorModel)
SC_REPORT_FATAL("DramGDDR5X", "Error Model not supported for GDDR5X");
// Parameters for DRAMPower
MemSpecGDDR5X *memSpec = dynamic_cast<MemSpecGDDR5X *>(this->memSpec);
if (memSpec == nullptr)
SC_REPORT_FATAL("DramGDDR5X", "Wrong MemSpec chosen");
if (Configuration::getInstance().PowerAnalysis)
SC_REPORT_FATAL("DramGDDR5X", "DRAMPower not supported for GDDR5X");
else
DRAMPower = new libDRAMPowerDummy();
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (c) 2019, University of 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 DRAMGDDR5X_H
#define DRAMGDDR5X_H
#include <systemc.h>
#include "Dram.h"
class DramGDDR5X : public Dram
{
public:
DramGDDR5X(sc_module_name);
SC_HAS_PROCESS(DramGDDR5X);
virtual ~DramGDDR5X() {}
};
#endif // DRAMGDDR5X_H

View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 2019, University of 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 "DramGDDR6.h"
#include "Dram.h"
#include "../../configuration/Configuration.h"
#include "../../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h"
#include "../../configuration/memspec/MemSpecGDDR6.h"
DramGDDR6::DramGDDR6(sc_module_name name) : Dram(name)
{
if (StoreMode == StorageMode::ErrorModel)
SC_REPORT_FATAL("DramGDDR6", "Error Model not supported for GDDR6");
// Parameters for DRAMPower
MemSpecGDDR6 *memSpec = dynamic_cast<MemSpecGDDR6 *>(this->memSpec);
if (memSpec == nullptr)
SC_REPORT_FATAL("DramGDDR6", "Wrong MemSpec chosen");
if (Configuration::getInstance().PowerAnalysis)
SC_REPORT_FATAL("DramGDDR6", "DRAMPower not supported for GDDR6");
else
DRAMPower = new libDRAMPowerDummy();
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2019, University of 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 DRAMGDDR6_H
#define DRAMGDDR6_H
#include <systemc.h>
#include "Dram.h"
class DramGDDR6 : public Dram
{
public:
DramGDDR6(sc_module_name);
SC_HAS_PROCESS(DramGDDR6);
virtual ~DramGDDR6() {}
};
#endif // DRAMGDDR6_H

View File

@@ -51,9 +51,7 @@ DramHBM2::DramHBM2(sc_module_name name) : Dram(name)
SC_REPORT_FATAL("DramHBM2", "Wrong MemSpec chosen");
if (Configuration::getInstance().PowerAnalysis)
{
SC_REPORT_FATAL("DramHBM2", "DRAMPower not supported for HBM2");
}
else
DRAMPower = new libDRAMPowerDummy();
}

View File

@@ -37,11 +37,8 @@
#define DRAMHBM2_H
#include <systemc.h>
#include <tlm.h>
#include "Dram.h"
using namespace tlm;
class DramHBM2 : public Dram
{
public:

View File

@@ -35,6 +35,9 @@
#include "DramLPDDR4.h"
#include "Dram.h"
#include "../../configuration/Configuration.h"
#include "../../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h"
#include "../../configuration/memspec/MemSpecLPDDR4.h"
DramLPDDR4::DramLPDDR4(sc_module_name name) : Dram(name)
@@ -48,9 +51,7 @@ DramLPDDR4::DramLPDDR4(sc_module_name name) : Dram(name)
SC_REPORT_FATAL("DramLPDDR4", "Wrong MemSpec chosen");
if (Configuration::getInstance().PowerAnalysis)
{
SC_REPORT_FATAL("DramLPDDR4", "DRAMPower not supported for LPDDR4");
}
else
DRAMPower = new libDRAMPowerDummy();
}

View File

@@ -37,7 +37,6 @@
#define DRAMLPDDR4_H
#include <systemc.h>
#include <tlm.h>
#include "Dram.h"
class DramLPDDR4 : public Dram

View File

@@ -45,6 +45,9 @@
#include "DramLPDDR4.h"
#include "DramWideIO2.h"
#include "DramHBM2.h"
#include "DramGDDR5.h"
#include "DramGDDR5X.h"
#include "DramGDDR6.h"
using namespace tlm;
@@ -149,4 +152,7 @@ template class DramRecordable<DramWideIO>;
template class DramRecordable<DramLPDDR4>;
template class DramRecordable<DramWideIO2>;
template class DramRecordable<DramHBM2>;
template class DramRecordable<DramGDDR5>;
template class DramRecordable<DramGDDR5X>;
template class DramRecordable<DramGDDR6>;

View File

@@ -51,9 +51,7 @@ DramWideIO2::DramWideIO2(sc_module_name name) : Dram(name)
SC_REPORT_FATAL("DramWideIO2", "Wrong MemSpec chosen");
if (Configuration::getInstance().PowerAnalysis)
{
SC_REPORT_FATAL("DramWideIO2", "DRAMPower not supported for WideIO2");
}
else
DRAMPower = new libDRAMPowerDummy();
}

View File

@@ -37,11 +37,8 @@
#define DRAMWIDEIO2_H
#include <systemc.h>
#include <tlm.h>
#include "Dram.h"
using namespace tlm;
class DramWideIO2 : public Dram
{
public: