Add initial version of DDR5 based on DDR4.
This commit is contained in:
@@ -99,6 +99,7 @@ add_library(DRAMSysLibrary
|
||||
src/configuration/memspec/MemSpec.cpp
|
||||
src/configuration/memspec/MemSpecDDR3.cpp
|
||||
src/configuration/memspec/MemSpecDDR4.cpp
|
||||
src/configuration/memspec/MemSpecDDR5.cpp
|
||||
src/configuration/memspec/MemSpecLPDDR4.cpp
|
||||
src/configuration/memspec/MemSpecWideIO.cpp
|
||||
src/configuration/memspec/MemSpecWideIO2.cpp
|
||||
@@ -115,6 +116,7 @@ add_library(DRAMSysLibrary
|
||||
src/controller/checker/CheckerIF.h
|
||||
src/controller/checker/CheckerDDR3.cpp
|
||||
src/controller/checker/CheckerDDR4.cpp
|
||||
src/controller/checker/CheckerDDR5.cpp
|
||||
src/controller/checker/CheckerLPDDR4.cpp
|
||||
src/controller/checker/CheckerWideIO.cpp
|
||||
src/controller/checker/CheckerWideIO2.cpp
|
||||
@@ -161,6 +163,7 @@ add_library(DRAMSysLibrary
|
||||
src/simulation/dram/Dram.cpp
|
||||
src/simulation/dram/DramDDR3.cpp
|
||||
src/simulation/dram/DramDDR4.cpp
|
||||
src/simulation/dram/DramDDR5.cpp
|
||||
src/simulation/dram/DramLPDDR4.cpp
|
||||
src/simulation/dram/DramWideIO.cpp
|
||||
src/simulation/dram/DramWideIO2.cpp
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"CONGEN": {
|
||||
"BYTE_BIT": [
|
||||
0,
|
||||
1
|
||||
],
|
||||
"COLUMN_BIT": [
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
11
|
||||
],
|
||||
"BANKGROUP_BIT": [
|
||||
12,
|
||||
13,
|
||||
14
|
||||
],
|
||||
"BANK_BIT": [
|
||||
15
|
||||
],
|
||||
"ROW_BIT": [
|
||||
16,
|
||||
17,
|
||||
18,
|
||||
19,
|
||||
20,
|
||||
21,
|
||||
22,
|
||||
23,
|
||||
24,
|
||||
25,
|
||||
26,
|
||||
27,
|
||||
28,
|
||||
29,
|
||||
30,
|
||||
31
|
||||
],
|
||||
"CHANNEL_BIT": [
|
||||
32
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"memspec": {
|
||||
"memarchitecturespec": {
|
||||
"burstLength": 16,
|
||||
"dataRate": 2,
|
||||
"nbrOfBankGroups": 8,
|
||||
"nbrOfBanks": 16,
|
||||
"nbrOfColumns": 1024,
|
||||
"nbrOfRanks": 1,
|
||||
"nbrOfRows": 65536,
|
||||
"width": 8,
|
||||
"nbrOfDevicesOnDIMM": 4,
|
||||
"nbrOfChannels": 2
|
||||
},
|
||||
"memoryId": "JEDEC_2x8Gb_DDR5-3200A_8bit",
|
||||
"memoryType": "DDR5",
|
||||
|
||||
"memtimingspec": {
|
||||
"AL": 0,
|
||||
"CCD_L": 16,
|
||||
"CCD_S": 8,
|
||||
"CKE": 6,
|
||||
"CKESR": 7,
|
||||
"DQSCK": 2,
|
||||
"FAW": 32,
|
||||
"RAS": 52,
|
||||
"RC": 74,
|
||||
"RCD": 22,
|
||||
"REFM": 1,
|
||||
"REFI": 6240,
|
||||
"RFC": 312,
|
||||
"RL": 22,
|
||||
"RPRE": 1,
|
||||
"RP": 22,
|
||||
"RRD_L": 8,
|
||||
"RRD_S": 8,
|
||||
"RTP": 12,
|
||||
"WL": 20,
|
||||
"WPRE": 2,
|
||||
"WR": 48,
|
||||
"WTR_L": 16,
|
||||
"WTR_S": 4,
|
||||
"XP": 12,
|
||||
"XPDLL": 0,
|
||||
"XS": 312,
|
||||
"XSDLL": 1024,
|
||||
"ACTPDEN": 2,
|
||||
"PRPDEN": 2,
|
||||
"REFPDEN": 2,
|
||||
"RTRS": 1,
|
||||
"clkMhz": 1600
|
||||
}
|
||||
}
|
||||
}
|
||||
19
DRAMSys/library/resources/configs/simulator/ddr5.json
Normal file
19
DRAMSys/library/resources/configs/simulator/ddr5.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"simconfig": {
|
||||
"AddressOffset": 0,
|
||||
"CheckTLM2Protocol": false,
|
||||
"DatabaseRecording": true,
|
||||
"Debug": false,
|
||||
"ECCControllerMode": "Disabled",
|
||||
"EnableWindowing": false,
|
||||
"ErrorCSVFile": "",
|
||||
"ErrorChipSeed": 42,
|
||||
"PowerAnalysis": false,
|
||||
"SimulationName": "ddr5",
|
||||
"SimulationProgressBar": true,
|
||||
"StoreMode": "NoStorage",
|
||||
"ThermalSimulation": false,
|
||||
"UseMalloc": false,
|
||||
"WindowSize": 1000
|
||||
}
|
||||
}
|
||||
16
DRAMSys/library/resources/simulations/ddr5-example.json
Normal file
16
DRAMSys/library/resources/simulations/ddr5-example.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"simulation": {
|
||||
"addressmapping": "am_ddr5_2x4x8Gbx8_dimm_p1KB_rbc.json",
|
||||
"mcconfig": "fr_fcfs.json",
|
||||
"memspec": "JEDEC_2x8Gb_DDR5-3200A_8bit.json",
|
||||
"simconfig": "ddr5.json",
|
||||
"simulationid": "ddr5-example",
|
||||
"thermalconfig": "config.json",
|
||||
"tracesetup": [
|
||||
{
|
||||
"clkMhz": 200,
|
||||
"name": "ddr3_example.stl"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "Configuration.h"
|
||||
#include "memspec/MemSpecDDR3.h"
|
||||
#include "memspec/MemSpecDDR4.h"
|
||||
#include "memspec/MemSpecDDR5.h"
|
||||
#include "memspec/MemSpecWideIO.h"
|
||||
#include "memspec/MemSpecLPDDR4.h"
|
||||
#include "memspec/MemSpecWideIO2.h"
|
||||
@@ -291,6 +292,8 @@ void Configuration::loadMemSpec(Configuration &config, std::string memspecUri)
|
||||
memSpec = new MemSpecDDR3(jMemSpec);
|
||||
else if (memoryType == "DDR4")
|
||||
memSpec = new MemSpecDDR4(jMemSpec);
|
||||
else if (memoryType == "DDR5")
|
||||
memSpec = new MemSpecDDR5(jMemSpec);
|
||||
else if (memoryType == "LPDDR4")
|
||||
memSpec = new MemSpecLPDDR4(jMemSpec);
|
||||
else if (memoryType == "WIDEIO_SDR")
|
||||
|
||||
@@ -55,19 +55,17 @@ MemSpecDDR5::MemSpecDDR5(json &memspec)
|
||||
tCKE (tCK * parseUint(memspec["memtimingspec"]["CKE"], "CKE")),
|
||||
tPD (tCKE),
|
||||
tCKESR (tCK * parseUint(memspec["memtimingspec"]["CKESR"], "CKESR")),
|
||||
tDQSCK (tCK * parseUint(memspec["memtimingspec"]["DQSCK"], "DQSCK")),
|
||||
tRAS (tCK * parseUint(memspec["memtimingspec"]["RAS"], "RAS")),
|
||||
tRC (tCK * parseUint(memspec["memtimingspec"]["RC"], "RC")),
|
||||
tRCD (tCK * parseUint(memspec["memtimingspec"]["RCD"], "RCD")),
|
||||
tRL (tCK * parseUint(memspec["memtimingspec"]["RL"], "RL")),
|
||||
tRPRE (tCK * parseUint(memspec["memtimingspec"]["RPRE"], "RPRE")),
|
||||
tRTP (tCK * parseUint(memspec["memtimingspec"]["RTP"], "RTP")),
|
||||
tWL (tCK * parseUint(memspec["memtimingspec"]["WL"], "WL")),
|
||||
tWPRE (tCK * parseUint(memspec["memtimingspec"]["WPRE"], "WPRE")),
|
||||
tWR (tCK * parseUint(memspec["memtimingspec"]["WR"], "WR")),
|
||||
tXP (tCK * parseUint(memspec["memtimingspec"]["XP"], "XP")),
|
||||
tXS (tCK * parseUint(memspec["memtimingspec"]["XS"], "XS")),
|
||||
tCCD_S (tCK * parseUint(memspec["memtimingspec"]["CCD_S"], "CCD_S")),
|
||||
tCCD_L (tCK * parseUint(memspec["memtimingspec"]["CCD_L"], "CCD_L")),
|
||||
tFAW (tCK * parseUint(memspec["memtimingspec"]["FAW"], "FAW")),
|
||||
tREFI ((parseUint(memspec["memtimingspec"]["REFM"], "REFM") == 4) ?
|
||||
(tCK * (parseUint(memspec["memtimingspec"]["REFI"], "REFI") / 4)) :
|
||||
((parseUint(memspec["memtimingspec"]["REFM"], "REFM") == 2) ?
|
||||
@@ -79,6 +77,10 @@ MemSpecDDR5::MemSpecDDR5(json &memspec)
|
||||
(tCK * parseUint(memspec["memtimingspec"]["RFC2"], "RFC2")) :
|
||||
(tCK * parseUint(memspec["memtimingspec"]["RFC"], "RFC")))),
|
||||
tRP (tCK * parseUint(memspec["memtimingspec"]["RP"], "RP")),
|
||||
tDQSCK (tCK * parseUint(memspec["memtimingspec"]["DQSCK"], "DQSCK")),
|
||||
tCCD_S (tCK * parseUint(memspec["memtimingspec"]["CCD_S"], "CCD_S")),
|
||||
tCCD_L (tCK * parseUint(memspec["memtimingspec"]["CCD_L"], "CCD_L")),
|
||||
tFAW (tCK * parseUint(memspec["memtimingspec"]["FAW"], "FAW")),
|
||||
tRRD_S (tCK * parseUint(memspec["memtimingspec"]["RRD_S"], "RRD_S")),
|
||||
tRRD_L (tCK * parseUint(memspec["memtimingspec"]["RRD_L"], "RRD_L")),
|
||||
tWTR_S (tCK * parseUint(memspec["memtimingspec"]["WTR_S"], "WTR_S")),
|
||||
@@ -90,7 +92,13 @@ MemSpecDDR5::MemSpecDDR5(json &memspec)
|
||||
tPRPDEN (tCK * parseUint(memspec["memtimingspec"]["PRPDEN"], "PRPDEN")),
|
||||
tREFPDEN (tCK * parseUint(memspec["memtimingspec"]["REFPDEN"], "REFPDEN")),
|
||||
tRTRS (tCK * parseUint(memspec["memtimingspec"]["RTRS"], "RTRS"))
|
||||
{}
|
||||
{
|
||||
commandLengthInCycles[Command::ACT] = 2;
|
||||
commandLengthInCycles[Command::RD] = 2;
|
||||
commandLengthInCycles[Command::RDA] = 2;
|
||||
commandLengthInCycles[Command::WR] = 2;
|
||||
commandLengthInCycles[Command::WRA] = 2;
|
||||
}
|
||||
|
||||
sc_time MemSpecDDR5::getRefreshIntervalAB() const
|
||||
{
|
||||
@@ -109,15 +117,15 @@ sc_time MemSpecDDR5::getExecutionTime(Command command, const tlm_generic_payload
|
||||
if (command == Command::PRE || command == Command::PREA)
|
||||
return tRP;
|
||||
else if (command == Command::ACT)
|
||||
return tRCD;
|
||||
return tRCD + tCK;
|
||||
else if (command == Command::RD)
|
||||
return tRL + burstDuration;
|
||||
return tRL + burstDuration + tCK;
|
||||
else if (command == Command::RDA)
|
||||
return tRTP + tRP;
|
||||
return tRTP + tRP + tCK;
|
||||
else if (command == Command::WR)
|
||||
return tWL + burstDuration;
|
||||
return tWL + burstDuration + tCK;
|
||||
else if (command == Command::WRA)
|
||||
return tWL + burstDuration + tWR + tRP;
|
||||
return tWL + burstDuration + tWR + tRP + tCK;
|
||||
else if (command == Command::REFA)
|
||||
return tRFC;
|
||||
else
|
||||
@@ -131,9 +139,9 @@ sc_time MemSpecDDR5::getExecutionTime(Command command, const tlm_generic_payload
|
||||
TimeInterval MemSpecDDR5::getIntervalOnDataStrobe(Command command) const
|
||||
{
|
||||
if (command == Command::RD || command == Command::RDA)
|
||||
return TimeInterval(sc_time_stamp() + tRL, sc_time_stamp() + tRL + burstDuration);
|
||||
return TimeInterval(sc_time_stamp() + tRL + tCK, sc_time_stamp() + tRL + burstDuration + tCK);
|
||||
else if (command == Command::WR || command == Command::WRA)
|
||||
return TimeInterval(sc_time_stamp() + tWL, sc_time_stamp() + tWL + burstDuration);
|
||||
return TimeInterval(sc_time_stamp() + tWL + tCK, sc_time_stamp() + tWL + burstDuration + tCK);
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL("MemSpec", "Method was called with invalid argument");
|
||||
|
||||
@@ -45,36 +45,38 @@ public:
|
||||
MemSpecDDR5(nlohmann::json &memspec);
|
||||
|
||||
// Memspec Variables:
|
||||
const sc_time tRCD;
|
||||
const sc_time tPPD;
|
||||
const sc_time tRP;
|
||||
const sc_time tCKE;
|
||||
const sc_time tPD;
|
||||
const sc_time tCKESR;
|
||||
const sc_time tRAS;
|
||||
const sc_time tRC;
|
||||
const sc_time tRCD;
|
||||
const sc_time tRL;
|
||||
const sc_time tRTP;
|
||||
const sc_time tRPRE;
|
||||
const sc_time tRPST;
|
||||
const sc_time tRDQSOFF;
|
||||
const sc_time tRTP;
|
||||
const sc_time tWL;
|
||||
const sc_time tWR;
|
||||
const sc_time tWTR_L;
|
||||
const sc_time tWTR_S;
|
||||
const sc_time tWPRE;
|
||||
const sc_time tWPST;
|
||||
const sc_time tCCD_L_slr;
|
||||
const sc_time tCCD_S_slr;
|
||||
const sc_time tCCD_dlr;
|
||||
const sc_time tCCD_L_WR_slr;
|
||||
const sc_time tCCD_S_WR_slr;
|
||||
const sc_time tCCD_WR_dlr;
|
||||
const sc_time tCCD_WR_dpr;
|
||||
const sc_time
|
||||
const sc_time
|
||||
const sc_time
|
||||
const sc_time
|
||||
const sc_time
|
||||
const sc_time
|
||||
const sc_time
|
||||
const sc_time
|
||||
const sc_time tWR;
|
||||
const sc_time tXP;
|
||||
const sc_time tXS;
|
||||
const sc_time tREFI;
|
||||
const sc_time tRFC;
|
||||
const sc_time tRP;
|
||||
const sc_time tDQSCK;
|
||||
const sc_time tCCD_S;
|
||||
const sc_time tCCD_L;
|
||||
const sc_time tFAW;
|
||||
const sc_time tRRD_S;
|
||||
const sc_time tRRD_L;
|
||||
const sc_time tWTR_S;
|
||||
const sc_time tWTR_L;
|
||||
const sc_time tAL;
|
||||
const sc_time tXPDLL;
|
||||
const sc_time tXSDLL;
|
||||
const sc_time tACTPDEN;
|
||||
const sc_time tPRPDEN;
|
||||
const sc_time tREFPDEN;
|
||||
const sc_time tRTRS;
|
||||
|
||||
// Currents and Voltages:
|
||||
// TODO: to be completed
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "Command.h"
|
||||
#include "checker/CheckerDDR3.h"
|
||||
#include "checker/CheckerDDR4.h"
|
||||
#include "checker/CheckerDDR5.h"
|
||||
#include "checker/CheckerWideIO.h"
|
||||
#include "checker/CheckerLPDDR4.h"
|
||||
#include "checker/CheckerWideIO2.h"
|
||||
@@ -76,6 +77,8 @@ Controller::Controller(sc_module_name name) :
|
||||
checker = new CheckerDDR3();
|
||||
else if (memSpec->memoryType == "DDR4")
|
||||
checker = new CheckerDDR4();
|
||||
else if (memSpec->memoryType == "DDR5")
|
||||
checker = new CheckerDDR5();
|
||||
else if (memSpec->memoryType == "WIDEIO_SDR")
|
||||
checker = new CheckerWideIO();
|
||||
else if (memSpec->memoryType == "LPDDR4")
|
||||
|
||||
462
DRAMSys/library/src/controller/checker/CheckerDDR5.cpp
Normal file
462
DRAMSys/library/src/controller/checker/CheckerDDR5.cpp
Normal file
@@ -0,0 +1,462 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Technische Universität Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Author: Lukas Steiner
|
||||
*/
|
||||
|
||||
#include "CheckerDDR5.h"
|
||||
|
||||
CheckerDDR5::CheckerDDR5()
|
||||
{
|
||||
Configuration &config = Configuration::getInstance();
|
||||
memSpec = dynamic_cast<MemSpecDDR5 *>(config.memSpec);
|
||||
if (memSpec == nullptr)
|
||||
SC_REPORT_FATAL("CheckerDDR5", "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);
|
||||
|
||||
tBURST = memSpec->burstLength / memSpec->dataRate * memSpec->tCK;
|
||||
tRDWR = memSpec->tRL + tBURST + memSpec->tCK - memSpec->tWL + memSpec->tWPRE;
|
||||
tRDWR_R = memSpec->tRL + tBURST + memSpec->tRTRS - memSpec->tWL + memSpec->tWPRE;
|
||||
tWRRD_S = memSpec->tWL + tBURST + memSpec->tWTR_S;
|
||||
tWRRD_L = memSpec->tWL + tBURST + memSpec->tWTR_L;
|
||||
tWRRD_R = memSpec->tWL + tBURST + memSpec->tRTRS - memSpec->tRL + memSpec->tRPRE;
|
||||
tWRPRE = memSpec->tWL + tBURST + memSpec->tWR;
|
||||
tRDPDEN = memSpec->tRL + tBURST + memSpec->tCK;
|
||||
tWRPDEN = memSpec->tWL + tBURST + memSpec->tWR;
|
||||
tWRAPDEN = memSpec->tWL + tBURST + memSpec->tCK + memSpec->tWR;
|
||||
}
|
||||
|
||||
sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGroup bankgroup, Bank bank) const
|
||||
{
|
||||
sc_time lastCommandStart;
|
||||
sc_time earliestTimeToStart = sc_time_stamp();
|
||||
|
||||
if (command == Command::RD || command == Command::RDA)
|
||||
{
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD - memSpec->tAL);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RD][bankgroup.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_S);
|
||||
|
||||
lastCommandStart = lastScheduledByCommand[Command::RD] != lastScheduledByCommandAndRank[Command::RD][rank.ID()] ? lastScheduledByCommand[Command::RD] : SC_ZERO_TIME;
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST + memSpec->tRTRS);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::RDA][bankgroup.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_S);
|
||||
|
||||
lastCommandStart = lastScheduledByCommand[Command::RDA] != lastScheduledByCommandAndRank[Command::RDA][rank.ID()] ? lastScheduledByCommand[Command::RDA] : SC_ZERO_TIME;
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST + memSpec->tRTRS);
|
||||
|
||||
if (command == Command::RDA)
|
||||
{
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE - memSpec->tRTP);
|
||||
}
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_L);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_S);
|
||||
|
||||
lastCommandStart = lastScheduledByCommand[Command::WR];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_R);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_L);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_S);
|
||||
|
||||
lastCommandStart = lastScheduledByCommand[Command::WRA];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRRD_R);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXSDLL);
|
||||
}
|
||||
else if (command == Command::WR || command == Command::WRA)
|
||||
{
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRCD - memSpec->tAL);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR);
|
||||
|
||||
lastCommandStart = lastScheduledByCommand[Command::RD] != lastScheduledByCommandAndRank[Command::RD][rank.ID()] ? lastScheduledByCommand[Command::RD] : SC_ZERO_TIME;
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR_R);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR);
|
||||
|
||||
lastCommandStart = lastScheduledByCommand[Command::RDA] != lastScheduledByCommandAndRank[Command::RDA][rank.ID()] ? lastScheduledByCommand[Command::RDA] : SC_ZERO_TIME;
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDWR_R);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WR][bankgroup.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_S);
|
||||
|
||||
lastCommandStart = lastScheduledByCommand[Command::WR] != lastScheduledByCommandAndRank[Command::WR][rank.ID()] ? lastScheduledByCommand[Command::WR] : SC_ZERO_TIME;
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST + memSpec->tRTRS);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBankGroup[Command::WRA][bankgroup.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_L);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_S);
|
||||
|
||||
lastCommandStart = lastScheduledByCommand[Command::WRA] != lastScheduledByCommandAndRank[Command::WRA][rank.ID()] ? lastScheduledByCommand[Command::WRA] : SC_ZERO_TIME;
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tBURST + memSpec->tRTRS);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXSDLL);
|
||||
}
|
||||
else 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->tRRD_L);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRD_S);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tAL + memSpec->tRTP + memSpec->tRP);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + 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::PDXA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::PDXP][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXS);
|
||||
|
||||
if (last4Activates[rank.ID()].size() >= 4)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, last4Activates[rank.ID()].front() + memSpec->tFAW);
|
||||
}
|
||||
else if (command == Command::PRE)
|
||||
{
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::RD][bank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tAL + memSpec->tRTP);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP);
|
||||
}
|
||||
else if (command == Command::PREA)
|
||||
{
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tAL + memSpec->tRTP);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tAL + memSpec->tRTP);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP);
|
||||
}
|
||||
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->tAL + memSpec->tRTP + memSpec->tRP);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + 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::PDXP][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXS);
|
||||
}
|
||||
else if (command == Command::PDEA)
|
||||
{
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tACTPDEN);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDPDEN);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDPDEN);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPDEN);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRAPDEN);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPRPDEN);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCKE);
|
||||
}
|
||||
else if (command == Command::PDXA)
|
||||
{
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::PDEA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPD);
|
||||
}
|
||||
else if (command == Command::PDEP)
|
||||
{
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDPDEN);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDPDEN);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRAPDEN);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPRPDEN);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPRPDEN);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::PDXP][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCKE);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tREFPDEN);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXS);
|
||||
}
|
||||
else if (command == Command::PDXP)
|
||||
{
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::PDEP][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPD);
|
||||
}
|
||||
else if (command == Command::SREFEN)
|
||||
{
|
||||
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 + std::max(tRDPDEN, memSpec->tAL + memSpec->tRTP + memSpec->tRP));
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + std::max(tWRAPDEN, tWRPRE + 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::PDXP][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXS);
|
||||
}
|
||||
else if (command == Command::SREFEX)
|
||||
{
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEN][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCKESR);
|
||||
}
|
||||
else
|
||||
SC_REPORT_FATAL("CheckerDDR5", "Unknown command!");
|
||||
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->tCK);
|
||||
|
||||
return earliestTimeToStart;
|
||||
}
|
||||
|
||||
void CheckerDDR5::insert(Command command, Rank rank, BankGroup bankgroup, Bank bank)
|
||||
{
|
||||
PRINTDEBUGMESSAGE("CheckerDDR5", "Changing state on bank " + std::to_string(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)
|
||||
{
|
||||
if (last4Activates[rank.ID()].size() == 4)
|
||||
last4Activates[rank.ID()].pop();
|
||||
last4Activates[rank.ID()].push(sc_time_stamp());
|
||||
}
|
||||
}
|
||||
77
DRAMSys/library/src/controller/checker/CheckerDDR5.h
Normal file
77
DRAMSys/library/src/controller/checker/CheckerDDR5.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Technische Universität Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Author: Lukas Steiner
|
||||
*/
|
||||
|
||||
#ifndef CHECKERDDR5_H
|
||||
#define CHECKERDDR5_H
|
||||
|
||||
#include "CheckerIF.h"
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
#include "../../configuration/memspec/MemSpecDDR5.h"
|
||||
#include "../../configuration/Configuration.h"
|
||||
|
||||
class CheckerDDR5 final : public CheckerIF
|
||||
{
|
||||
public:
|
||||
CheckerDDR5();
|
||||
virtual sc_time timeToSatisfyConstraints(Command, Rank, BankGroup, Bank) const override;
|
||||
virtual void insert(Command, Rank, BankGroup, Bank) override;
|
||||
|
||||
private:
|
||||
const MemSpecDDR5 *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>> last4Activates;
|
||||
|
||||
sc_time tBURST;
|
||||
sc_time tRDWR;
|
||||
sc_time tRDWR_R;
|
||||
sc_time tWRRD_S;
|
||||
sc_time tWRRD_L;
|
||||
sc_time tWRRD_R;
|
||||
sc_time tRDAACT;
|
||||
sc_time tWRPRE;
|
||||
sc_time tWRAACT;
|
||||
sc_time tRDPDEN;
|
||||
sc_time tWRPDEN;
|
||||
sc_time tWRAPDEN;
|
||||
};
|
||||
|
||||
#endif // CHECKERDDR5_H
|
||||
@@ -51,6 +51,7 @@
|
||||
#include "../error/ecchamming.h"
|
||||
#include "dram/DramDDR3.h"
|
||||
#include "dram/DramDDR4.h"
|
||||
#include "dram/DramDDR5.h"
|
||||
#include "dram/DramWideIO.h"
|
||||
#include "dram/DramLPDDR4.h"
|
||||
#include "dram/DramWideIO2.h"
|
||||
@@ -216,6 +217,8 @@ void DRAMSys::instantiateModules(const std::string &pathToResources,
|
||||
dram = new DramWideIO(str.c_str());
|
||||
else if (memoryType == "DDR4")
|
||||
dram = new DramDDR4(str.c_str());
|
||||
else if (memoryType == "DDR5")
|
||||
dram = new DramDDR5(str.c_str());
|
||||
else if (memoryType == "LPDDR4")
|
||||
dram = new DramLPDDR4(str.c_str());
|
||||
else if (memoryType == "WIDEIO2")
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "dram/DramRecordable.h"
|
||||
#include "dram/DramDDR3.h"
|
||||
#include "dram/DramDDR4.h"
|
||||
#include "dram/DramDDR5.h"
|
||||
#include "dram/DramWideIO.h"
|
||||
#include "dram/DramLPDDR4.h"
|
||||
#include "dram/DramWideIO2.h"
|
||||
@@ -152,12 +153,14 @@ void DRAMSysRecordable::instantiateModules(const std::string &traceName,
|
||||
|
||||
if (memoryType == "DDR3")
|
||||
dram = new DramRecordable<DramDDR3>(str.c_str(), tlmRecorders[i]);
|
||||
else if (memoryType == "WIDEIO_SDR")
|
||||
dram = new DramRecordable<DramWideIO>(str.c_str(), tlmRecorders[i]);
|
||||
else if (memoryType == "DDR4")
|
||||
dram = new DramRecordable<DramDDR4>(str.c_str(), tlmRecorders[i]);
|
||||
else if (memoryType == "DDR5")
|
||||
dram = new DramRecordable<DramDDR5>(str.c_str(), tlmRecorders[i]);
|
||||
else if (memoryType == "LPDDR4")
|
||||
dram = new DramRecordable<DramLPDDR4>(str.c_str(), tlmRecorders[i]);
|
||||
else if (memoryType == "WIDEIO_SDR")
|
||||
dram = new DramRecordable<DramWideIO>(str.c_str(), tlmRecorders[i]);
|
||||
else if (memoryType == "WIDEIO2")
|
||||
dram = new DramRecordable<DramWideIO2>(str.c_str(), tlmRecorders[i]);
|
||||
else if (memoryType == "HBM2")
|
||||
|
||||
52
DRAMSys/library/src/simulation/dram/DramDDR5.cpp
Normal file
52
DRAMSys/library/src/simulation/dram/DramDDR5.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Technische Universität Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors:
|
||||
* Lukas Steiner
|
||||
*/
|
||||
|
||||
#include "DramDDR5.h"
|
||||
|
||||
#include "Dram.h"
|
||||
#include "../../configuration/Configuration.h"
|
||||
#include "../../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h"
|
||||
#include "../../configuration/memspec/MemSpecDDR5.h"
|
||||
|
||||
using namespace DRAMPower;
|
||||
|
||||
DramDDR5::DramDDR5(sc_module_name name) : Dram(name)
|
||||
{
|
||||
if (storeMode == StorageMode::ErrorModel)
|
||||
SC_REPORT_FATAL("DramDDR5", "Error Model not supported for DDR5");
|
||||
|
||||
if (Configuration::getInstance().powerAnalysis)
|
||||
SC_REPORT_FATAL("DramDDR5", "DRAMPower does not support DDR5");
|
||||
}
|
||||
50
DRAMSys/library/src/simulation/dram/DramDDR5.h
Normal file
50
DRAMSys/library/src/simulation/dram/DramDDR5.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Technische Universität Kaiserslautern
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors:
|
||||
* Lukas Steiner
|
||||
*/
|
||||
|
||||
#ifndef DRAMDDR5_H
|
||||
#define DRAMDDR5_H
|
||||
|
||||
#include <systemc.h>
|
||||
#include "Dram.h"
|
||||
|
||||
class DramDDR5 : public Dram
|
||||
{
|
||||
public:
|
||||
DramDDR5(sc_module_name);
|
||||
SC_HAS_PROCESS(DramDDR5);
|
||||
virtual ~DramDDR5() {}
|
||||
};
|
||||
|
||||
#endif // DRAMDDR5_H
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "../../common/utils.h"
|
||||
#include "DramDDR3.h"
|
||||
#include "DramDDR4.h"
|
||||
#include "DramDDR5.h"
|
||||
#include "DramWideIO.h"
|
||||
#include "DramLPDDR4.h"
|
||||
#include "DramWideIO2.h"
|
||||
@@ -147,6 +148,7 @@ void DramRecordable<BaseDram>::powerWindow()
|
||||
|
||||
template class DramRecordable<DramDDR3>;
|
||||
template class DramRecordable<DramDDR4>;
|
||||
template class DramRecordable<DramDDR5>;
|
||||
template class DramRecordable<DramLPDDR4>;
|
||||
template class DramRecordable<DramWideIO>;
|
||||
template class DramRecordable<DramWideIO2>;
|
||||
|
||||
Reference in New Issue
Block a user