Adapted timing checkers of DDR4 and WideIO to new refresh.

This commit is contained in:
Lukas Steiner (2)
2019-10-07 15:37:23 +02:00
parent 86d5082434
commit 932027112e
12 changed files with 160 additions and 333 deletions

View File

@@ -28,8 +28,8 @@
<parameter id="REFI" type="uint" value="3120" />
<parameter id="TAW" type="uint" value="10" />
<parameter id="RRD" type="uint" value="2" />
<parameter id="CCDR" type="uint" value="2" />
<parameter id="CCDW" type="uint" value="1" />
<parameter id="CCD_R" type="uint" value="2" />
<parameter id="CCD_W" type="uint" value="1" />
<parameter id="WTR" type="uint" value="3" />
<parameter id="CKE" type="uint" value="3" />
<parameter id="CKESR" type="uint" value="3" />

View File

@@ -28,8 +28,8 @@
<parameter id="REFI" type="uint" value="4160" />
<parameter id="TAW" type="uint" value="14" />
<parameter id="RRD" type="uint" value="3" />
<parameter id="CCDR" type="uint" value="2" />
<parameter id="CCDW" type="uint" value="1" />
<parameter id="CCD_R" type="uint" value="2" />
<parameter id="CCD_W" type="uint" value="1" />
<parameter id="WTR" type="uint" value="4" />
<parameter id="CKE" type="uint" value="3" />
<parameter id="CKESR" type="uint" value="4" />

View File

@@ -408,12 +408,12 @@ void ConfigurationLoader::loadWideIO(Configuration &config, XMLElement *xmlSpec)
memSpec->tRC = clk * queryUIntParameter(timings, "RC");
memSpec->tRCD = clk * queryUIntParameter(timings, "RCD");
memSpec->tRL = clk * queryUIntParameter(timings, "RL");
memSpec->tRTP = clk * queryUIntParameter(timings, "RTP");
memSpec->tWL = clk * queryUIntParameter(timings, "WL");
memSpec->tWR = clk * queryUIntParameter(timings, "WR");
memSpec->tXP = clk * queryUIntParameter(timings, "XP");
memSpec->tXS = clk * queryUIntParameter(timings, "XS");
memSpec->tCCD = clk * queryUIntParameter(timings, "CCD");
memSpec->tCCD_R = clk * queryUIntParameter(timings, "CCD_R");
memSpec->tCCD_W = clk * queryUIntParameter(timings, "CCD_W");
memSpec->tREFI = clk * queryUIntParameter(timings, "REFI");
memSpec->tRFC = clk * queryUIntParameter(timings, "RFC");
memSpec->tRP = clk * queryUIntParameter(timings, "RP");

View File

@@ -66,19 +66,17 @@ sc_time MemSpecWideIO::getExecutionTime(Command command) const
return tRP;
else if (command == Command::ACT)
return tRCD;
else if (command == Command::RD)
else if (command == Command::RD || command == Command::RDA)
return tRL + getReadAccessTime();
else if (command == Command::RDA)
// this time is wrong (controller internally waits for tRAS)
return tRTP + tRP;
else if (command == Command::WR)
// else if (command == Command::RDA)
// // this time is wrong (controller internally waits for tRAS)
// return tRTP + tRP;
else if (command == Command::WR || command == Command::WRA)
return tWL + getWriteAccessTime();
else if (command == Command::WRA)
return tWL + getWriteAccessTime() + tWR + tRP;
// else if (command == Command::WRA)
// return tWL + getWriteAccessTime() + tWR + tRP;
else if (command == Command::REFA)
return tRFC;
else if (command == Command::REFB)
return tRFC;
else
{
SC_REPORT_FATAL("getExecutionTime",

View File

@@ -47,7 +47,6 @@ struct MemSpecWideIO : public MemSpec
sc_time tRC; // RAS-cycle-time (min time bw 2 succesive ACT to same bank)
sc_time tRCD; // act -> read/write
sc_time tRL; // read latency (read command start to data strobe)
sc_time tRTP; // read to precharge
sc_time tWL; // write latency
sc_time tWR; // write recovery (write to precharge)
sc_time tXP; // min delay to row access command after pdnpx pdnax
@@ -56,7 +55,8 @@ struct MemSpecWideIO : public MemSpec
sc_time tRFC;
sc_time tRP;
sc_time tDQSCK;
sc_time tCCD;
sc_time tCCD_R;
sc_time tCCD_W;
sc_time tRRD;
sc_time tTAW;
sc_time tWTR;

View File

@@ -204,9 +204,8 @@ sc_time CheckerDDR3::delayToSatisfyConstraints(Command command, Rank rank, BankG
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC);
}
else
{
reportFatal("CheckerDDR3", "Unknown command!");
}
// Check if command bus is free
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk);

View File

@@ -41,13 +41,6 @@ CheckerDDR4::CheckerDDR4()
if (memSpec == nullptr)
SC_REPORT_FATAL("CheckerDDR4", "Wrong MemSpec chosen");
if (config.ControllerCoreRefDisable)
refreshChecker = new RefreshCheckerDDR4Dummy(memSpec);
else if (config.BankwiseLogic)
refreshChecker = new RefreshCheckerDDR4Bankwise(memSpec);
else
refreshChecker = new RefreshCheckerDDR4(memSpec);
lastScheduledByCommandAndBank = std::vector<std::vector<sc_time>>
(numberOfCommands(), std::vector<sc_time>(memSpec->NumberOfBanks));
lastScheduledByCommandAndBankGroup = std::vector<std::vector<sc_time>>
@@ -61,11 +54,6 @@ CheckerDDR4::CheckerDDR4()
burstClocks = (memSpec->BurstLength / 2) * memSpec->clk;
}
CheckerDDR4::~CheckerDDR4()
{
delete refreshChecker;
}
sc_time CheckerDDR4::delayToSatisfyConstraints(Command command, Rank rank, BankGroup bankgroup, Bank bank) const
{
sc_time lastCommandStart;
@@ -86,6 +74,10 @@ sc_time CheckerDDR4::delayToSatisfyConstraints(Command command, Rank rank, BankG
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 = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC);
@@ -102,14 +94,8 @@ sc_time CheckerDDR4::delayToSatisfyConstraints(Command command, Rank rank, BankG
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->tRFC);
if (lastActivates[rank.ID()].size() >= 4)
earliestTimeToStart = std::max(earliestTimeToStart, lastActivates[rank.ID()].front() + memSpec->tFAW);
refreshChecker->delayToSatisfyACT(bank, earliestTimeToStart);
}
else if (command == Command::RD || command == Command::RDA)
{
@@ -151,8 +137,6 @@ sc_time CheckerDDR4::delayToSatisfyConstraints(Command command, Rank rank, BankG
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL
+ burstClocks + memSpec->tWTR_S);
refreshChecker->delayToSatisfyRD(bank, earliestTimeToStart);
}
else if (command == Command::WR || command == Command::WRA)
{
@@ -184,8 +168,6 @@ sc_time CheckerDDR4::delayToSatisfyConstraints(Command command, Rank rank, BankG
lastCommandStart = lastScheduledByCommand[Command::WRA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD_S);
refreshChecker->delayToSatisfyWR(bank, earliestTimeToStart);
}
else if (command == Command::PRE)
{
@@ -200,15 +182,62 @@ sc_time CheckerDDR4::delayToSatisfyConstraints(Command command, Rank rank, BankG
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL
+ burstClocks + memSpec->tWR);
}
else if (command == Command::PREA)
{
lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()];
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS);
refreshChecker->delayToSatisfyPRE(bank, earliestTimeToStart);
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);
}
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);
}
else
{
reportFatal("CheckerDDR4", "Unknown command!");
}
// Check if command bus is free
earliestTimeToStart = std::max(earliestTimeToStart, lastScheduled + memSpec->clk);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandOnBus + memSpec->clk);
return (earliestTimeToStart - sc_time_stamp());
}
@@ -222,7 +251,7 @@ void CheckerDDR4::insert(Command command, Rank rank, BankGroup bankgroup, Bank b
lastScheduledByCommandAndBankGroup[command][bankgroup.ID()] = sc_time_stamp();
lastScheduledByCommandAndRank[command][rank.ID()] = sc_time_stamp();
lastScheduledByCommand[command] = sc_time_stamp();
lastScheduled = sc_time_stamp();
lastCommandOnBus = sc_time_stamp();
if (command == Command::ACT)
{
@@ -230,75 +259,4 @@ void CheckerDDR4::insert(Command command, Rank rank, BankGroup bankgroup, Bank b
lastActivates[rank.ID()].pop();
lastActivates[rank.ID()].push(sc_time_stamp());
}
else if (command == Command::REFA || command == Command::REFB)
refreshChecker->insert(bank);
}
// TODO: max(earliestTimeToStart, ...) needed?
void RefreshCheckerDDR4::delayToSatisfyACT(Bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timeForNextPREA - memSpec->tRAS))
earliestTimeToStart = timeForNextREFA + memSpec->tRFC;
}
void RefreshCheckerDDR4::delayToSatisfyRD(Bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timeForNextPREA - memSpec->tRTP))
earliestTimeToStart = timeForNextREFA + memSpec->tRFC;
}
void RefreshCheckerDDR4::delayToSatisfyWR(Bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timeForNextPREA - memSpec->tWL - burstClocks - memSpec->tWR))
earliestTimeToStart = timeForNextREFA + memSpec->tRFC;
}
void RefreshCheckerDDR4::delayToSatisfyPRE(Bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= timeForNextPREA)
earliestTimeToStart = timeForNextREFA + memSpec->tRFC;
}
void RefreshCheckerDDR4::insert(Bank)
{
timeForNextREFA += memSpec->tREFI;
timeForNextPREA += memSpec->tREFI;
}
RefreshCheckerDDR4Bankwise::RefreshCheckerDDR4Bankwise(const MemSpecDDR4 *memSpec)
: RefreshCheckerDDR4Dummy(memSpec)
{
sc_time currentREFB = memSpec->tREFI - memSpec->clk * (memSpec->NumberOfBanks - 1);
sc_time currentPRE = currentREFB - std::max(memSpec->clk * memSpec->NumberOfBanks, memSpec->tRP);
for (unsigned bankID = 0; bankID < memSpec->NumberOfBanks; bankID++)
{
timesForNextREFB.push_back(currentREFB);
timesForNextPRE.push_back(currentPRE);
currentREFB += memSpec->clk;
currentPRE += memSpec->clk;
}
}
void RefreshCheckerDDR4Bankwise::delayToSatisfyACT(Bank bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timesForNextPRE[bank.ID()] - memSpec->tRAS))
earliestTimeToStart = timesForNextREFB[bank.ID()] + memSpec->tRFC;
}
void RefreshCheckerDDR4Bankwise::delayToSatisfyRD(Bank bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timesForNextPRE[bank.ID()] - memSpec->tRTP))
earliestTimeToStart = timesForNextREFB[bank.ID()] + memSpec->tRFC;
}
void RefreshCheckerDDR4Bankwise::delayToSatisfyWR(Bank bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timesForNextPRE[bank.ID()] - memSpec->tWL - burstClocks - memSpec->tWR))
earliestTimeToStart = timesForNextREFB[bank.ID()] + memSpec->tRFC;
}
void RefreshCheckerDDR4Bankwise::insert(Bank bank)
{
timesForNextREFB[bank.ID()] += memSpec->tREFI;
timesForNextPRE[bank.ID()] += memSpec->tREFI;
}

View File

@@ -41,13 +41,10 @@
#include "../../configuration/memspec/MemSpecDDR4.h"
#include "../../configuration/Configuration.h"
class RefreshCheckerDDR4Dummy;
class CheckerDDR4 final : public CheckerIF
{
public:
CheckerDDR4();
~CheckerDDR4();
sc_time delayToSatisfyConstraints(Command, Rank, BankGroup, Bank) const;
void insert(Command, Rank, BankGroup, Bank);
@@ -58,70 +55,15 @@ private:
std::vector<std::vector<sc_time>> lastScheduledByCommandAndBankGroup;
std::vector<std::vector<sc_time>> lastScheduledByCommandAndRank;
std::vector<sc_time> lastScheduledByCommand;
sc_time lastScheduled;
sc_time lastCommandOnBus;
// Four activate window
std::vector<std::queue<sc_time>> lastActivates;
RefreshCheckerDDR4Dummy *refreshChecker;
sc_time burstClocks;
// PowerDown TODO: Implement this method?
//sc_time getTimeConstraintToEnterPowerDown(Command lastCmd, Command pdnCmd) const;
};
class RefreshCheckerDDR4Dummy
{
protected:
friend class CheckerDDR4;
RefreshCheckerDDR4Dummy(const MemSpecDDR4 *memSpec) : memSpec(memSpec)
{
burstClocks = (memSpec->BurstLength / 2) * memSpec->clk;
}
virtual ~RefreshCheckerDDR4Dummy() {}
virtual void delayToSatisfyACT(Bank, sc_time &) {}
virtual void delayToSatisfyRD(Bank, sc_time &) {}
virtual void delayToSatisfyWR(Bank, sc_time &) {}
virtual void delayToSatisfyPRE(Bank, sc_time &) {}
virtual void insert(Bank) {}
const MemSpecDDR4 *memSpec;
sc_time burstClocks;
};
class RefreshCheckerDDR4 final : public RefreshCheckerDDR4Dummy
{
private:
friend class CheckerDDR4;
RefreshCheckerDDR4(const MemSpecDDR4 *memSpec)
: RefreshCheckerDDR4Dummy(memSpec) {}
void delayToSatisfyACT(Bank, sc_time &);
void delayToSatisfyRD(Bank, sc_time &);
void delayToSatisfyWR(Bank, sc_time &);
void delayToSatisfyPRE(Bank, sc_time &);
void insert(Bank);
sc_time timeForNextREFA = memSpec->tREFI;
sc_time timeForNextPREA = timeForNextREFA - memSpec->tRP;
};
class RefreshCheckerDDR4Bankwise final : public RefreshCheckerDDR4Dummy
{
private:
friend class CheckerDDR4;
RefreshCheckerDDR4Bankwise(const MemSpecDDR4 *);
void delayToSatisfyACT(Bank, sc_time &);
void delayToSatisfyRD(Bank, sc_time &);
void delayToSatisfyWR(Bank, sc_time &);
void insert(Bank);
std::vector<sc_time> timesForNextREFB;
std::vector<sc_time> timesForNextPRE;
};
#endif // CHECKERDDR4_H

View File

@@ -41,8 +41,6 @@
#include "../../configuration/memspec/MemSpecLPDDR4.h"
#include "../../configuration/Configuration.h"
class RefreshCheckerLPDDR4Dummy;
class CheckerLPDDR4 final : public CheckerIF
{
public:

View File

@@ -41,13 +41,6 @@ CheckerWideIO::CheckerWideIO()
if (memSpec == nullptr)
SC_REPORT_FATAL("CheckerWideIO", "Wrong MemSpec chosen");
if (config.ControllerCoreRefDisable)
refreshChecker = new RefreshCheckerWideIODummy(memSpec);
else if (config.BankwiseLogic)
refreshChecker = new RefreshCheckerWideIOBankwise(memSpec);
else
refreshChecker = new RefreshCheckerWideIO(memSpec);
lastScheduledByCommandAndBank = std::vector<std::vector<sc_time>>
(numberOfCommands(), std::vector<sc_time>(memSpec->NumberOfBanks));
lastScheduledByCommandAndRank = std::vector<std::vector<sc_time>>
@@ -55,11 +48,8 @@ CheckerWideIO::CheckerWideIO()
lastScheduledByCommand = std::vector<sc_time>(numberOfCommands());
lastActivates = std::vector<std::queue<sc_time>>(memSpec->NumberOfRanks);
}
CheckerWideIO::~CheckerWideIO()
{
delete refreshChecker;
burstClocks = memSpec->BurstLength * memSpec->clk;
}
sc_time CheckerWideIO::delayToSatisfyConstraints(Command command, Rank rank, BankGroup, Bank bank) const
@@ -71,16 +61,21 @@ sc_time CheckerWideIO::delayToSatisfyConstraints(Command command, Rank rank, Ban
{
lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRP);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + burstClocks + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + memSpec->tCCD + memSpec->tWR + memSpec->tRP);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL
+ burstClocks - memSpec->clk + 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 = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC);
@@ -93,14 +88,8 @@ sc_time CheckerWideIO::delayToSatisfyConstraints(Command command, Rank rank, Ban
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->tRFC);
if (lastActivates[rank.ID()].size() >= 2)
earliestTimeToStart = std::max(earliestTimeToStart, lastActivates[rank.ID()].front() + memSpec->tTAW);
refreshChecker->delayToSatisfyACT(bank, earliestTimeToStart);
}
else if (command == Command::RD || command == Command::RDA)
{
@@ -109,13 +98,21 @@ sc_time CheckerWideIO::delayToSatisfyConstraints(Command command, Rank rank, Ban
lastCommandStart = lastScheduledByCommand[Command::RD];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + burstClocks);
lastCommandStart = lastScheduledByCommand[Command::RDA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + burstClocks);
lastCommandStart = lastScheduledByCommand[Command::WR];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + memSpec->tCCD + memSpec->tWTR);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks - memSpec->clk + memSpec->tWTR);
refreshChecker->delayToSatisfyRD(bank, earliestTimeToStart);
lastCommandStart = lastScheduledByCommand[Command::WRA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks - memSpec->clk + memSpec->tWTR);
}
else if (command == Command::WR || command == Command::WRA)
{
@@ -124,13 +121,21 @@ sc_time CheckerWideIO::delayToSatisfyConstraints(Command command, Rank rank, Ban
lastCommandStart = lastScheduledByCommand[Command::RD];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRL + memSpec->tCCD + 2 * memSpec->clk - memSpec->tWL);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tRL + burstClocks + memSpec->clk);
lastCommandStart = lastScheduledByCommand[Command::RDA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tRL + burstClocks + memSpec->clk);
lastCommandStart = lastScheduledByCommand[Command::WR];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + burstClocks);
refreshChecker->delayToSatisfyWR(bank, earliestTimeToStart);
lastCommandStart = lastScheduledByCommand[Command::WRA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + burstClocks);
}
else if (command == Command::PRE)
{
@@ -139,13 +144,62 @@ sc_time CheckerWideIO::delayToSatisfyConstraints(Command command, Rank rank, Ban
lastCommandStart = lastScheduledByCommandAndBank[Command::RD][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + burstClocks);
lastCommandStart = lastScheduledByCommandAndBank[Command::WR][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + memSpec->tCCD + memSpec->tWR);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks - memSpec->clk + memSpec->tWR);
}
else if (command == Command::PREA)
{
lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()];
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS);
refreshChecker->delayToSatisfyPRE(bank, earliestTimeToStart);
lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + burstClocks);
lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + burstClocks);
lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks - memSpec->clk + memSpec->tWR);
lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks - memSpec->clk + memSpec->tWR);
}
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 + burstClocks + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
+ memSpec->tWL + burstClocks - memSpec->clk + 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);
}
else
{
@@ -173,75 +227,4 @@ void CheckerWideIO::insert(Command command, Rank rank, BankGroup, Bank bank)
lastActivates[rank.ID()].pop();
lastActivates[rank.ID()].push(sc_time_stamp());
}
else if (command == Command::REFA || command == Command::REFB)
refreshChecker->insert(bank);
}
// TODO: max(earliestTimeToStart, ...) needed?
void RefreshCheckerWideIO::delayToSatisfyACT(Bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timeForNextPREA - memSpec->tRAS))
earliestTimeToStart = timeForNextREFA + memSpec->tRFC;
}
void RefreshCheckerWideIO::delayToSatisfyRD(Bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timeForNextPREA - memSpec->tRTP))
earliestTimeToStart = timeForNextREFA + memSpec->tRFC;
}
void RefreshCheckerWideIO::delayToSatisfyWR(Bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timeForNextPREA - memSpec->tWL - memSpec->tCCD - memSpec->tWR))
earliestTimeToStart = timeForNextREFA + memSpec->tRFC;
}
void RefreshCheckerWideIO::delayToSatisfyPRE(Bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= timeForNextPREA)
earliestTimeToStart = timeForNextREFA + memSpec->tRFC;
}
void RefreshCheckerWideIO::insert(Bank)
{
timeForNextREFA += memSpec->tREFI;
timeForNextPREA += memSpec->tREFI;
}
RefreshCheckerWideIOBankwise::RefreshCheckerWideIOBankwise(const MemSpecWideIO *memSpec)
: RefreshCheckerWideIODummy(memSpec)
{
sc_time currentREFB = memSpec->tREFI - memSpec->clk * (memSpec->NumberOfBanks - 1);
sc_time currentPRE = currentREFB - std::max(memSpec->clk * memSpec->NumberOfBanks, memSpec->tRP);
for (unsigned bankID = 0; bankID < memSpec->NumberOfBanks; bankID++)
{
timesForNextREFB.push_back(currentREFB);
timesForNextPRE.push_back(currentPRE);
currentREFB += memSpec->clk;
currentPRE += memSpec->clk;
}
}
void RefreshCheckerWideIOBankwise::delayToSatisfyACT(Bank bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timesForNextPRE[bank.ID()] - memSpec->tRAS))
earliestTimeToStart = timesForNextREFB[bank.ID()] + memSpec->tRFC;
}
void RefreshCheckerWideIOBankwise::delayToSatisfyRD(Bank bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timesForNextPRE[bank.ID()] - memSpec->tRTP))
earliestTimeToStart = timesForNextREFB[bank.ID()] + memSpec->tRFC;
}
void RefreshCheckerWideIOBankwise::delayToSatisfyWR(Bank bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timesForNextPRE[bank.ID()] - memSpec->tWL - memSpec->tCCD - memSpec->tWR))
earliestTimeToStart = timesForNextREFB[bank.ID()] + memSpec->tRFC;
}
void RefreshCheckerWideIOBankwise::insert(Bank bank)
{
timesForNextREFB[bank.ID()] += memSpec->tREFI;
timesForNextPRE[bank.ID()] += memSpec->tREFI;
}

View File

@@ -41,13 +41,10 @@
#include "../../configuration/memspec/MemSpecWideIO.h"
#include "../../configuration/Configuration.h"
class RefreshCheckerWideIODummy;
class CheckerWideIO final : public CheckerIF
{
public:
CheckerWideIO();
~CheckerWideIO();
sc_time delayToSatisfyConstraints(Command, Rank, BankGroup, Bank) const;
void insert(Command, Rank, BankGroup, Bank);
@@ -62,58 +59,10 @@ private:
// Four activate window
std::vector<std::queue<sc_time>> lastActivates;
RefreshCheckerWideIODummy *refreshChecker;
sc_time burstClocks;
// PowerDown TODO: Implement this method?
//sc_time getTimeConstraintToEnterPowerDown(Command lastCmd, Command pdnCmd) const;
};
class RefreshCheckerWideIODummy
{
protected:
friend class CheckerWideIO;
RefreshCheckerWideIODummy(const MemSpecWideIO *memSpec) : memSpec(memSpec) {}
virtual ~RefreshCheckerWideIODummy() {}
virtual void delayToSatisfyACT(Bank, sc_time &) {}
virtual void delayToSatisfyRD(Bank, sc_time &) {}
virtual void delayToSatisfyWR(Bank, sc_time &) {}
virtual void delayToSatisfyPRE(Bank, sc_time &) {}
virtual void insert(Bank) {}
const MemSpecWideIO *memSpec;
};
class RefreshCheckerWideIO final : public RefreshCheckerWideIODummy
{
private:
friend class CheckerWideIO;
RefreshCheckerWideIO(const MemSpecWideIO *memSpec)
: RefreshCheckerWideIODummy(memSpec) {}
void delayToSatisfyACT(Bank, sc_time &);
void delayToSatisfyRD(Bank, sc_time &);
void delayToSatisfyWR(Bank, sc_time &);
void delayToSatisfyPRE(Bank, sc_time &);
void insert(Bank);
sc_time timeForNextREFA = memSpec->tREFI;
sc_time timeForNextPREA = timeForNextREFA - memSpec->tRP;
};
class RefreshCheckerWideIOBankwise final : public RefreshCheckerWideIODummy
{
private:
friend class CheckerWideIO;
RefreshCheckerWideIOBankwise(const MemSpecWideIO *);
void delayToSatisfyACT(Bank, sc_time &);
void delayToSatisfyRD(Bank, sc_time &);
void delayToSatisfyWR(Bank, sc_time &);
void insert(Bank);
std::vector<sc_time> timesForNextREFB;
std::vector<sc_time> timesForNextPRE;
};
#endif // CHECKERWIDEIO_H

View File

@@ -77,9 +77,9 @@ DramWideIO::DramWideIO(sc_module_name name) : Dram(name)
memTimingSpec.RRDB_L = memSpec->tRRD / clk;
memTimingSpec.RRDB_S = memSpec->tRRD / clk;
memTimingSpec.AL = 0;
memTimingSpec.CCD = memSpec->tCCD / clk;
memTimingSpec.CCD_L = memSpec->tCCD / clk;
memTimingSpec.CCD_S = memSpec->tCCD / clk;
memTimingSpec.CCD = memSpec->BurstLength;
memTimingSpec.CCD_L = memSpec->BurstLength;
memTimingSpec.CCD_S = memSpec->BurstLength;
memTimingSpec.CKE = memSpec->tCKE / clk;
memTimingSpec.CKESR = memSpec->tCKESR / clk;
memTimingSpec.clkMhz = memSpec->clkMHz;
@@ -97,7 +97,7 @@ DramWideIO::DramWideIO(sc_module_name name) : Dram(name)
memTimingSpec.RRD = memSpec->tRRD / clk;
memTimingSpec.RRD_L = memSpec->tRRD / clk;
memTimingSpec.RRD_S = memSpec->tRRD / clk;
memTimingSpec.RTP = memSpec->tRTP / clk;
memTimingSpec.RTP = memSpec->BurstLength;
memTimingSpec.TAW = memSpec->tTAW / clk;
memTimingSpec.WL = memSpec->tWL / clk;
memTimingSpec.WR = memSpec->tWR / clk;