Adapted timing checkers of DDR4 and WideIO to new refresh.
This commit is contained in:
@@ -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" />
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -41,8 +41,6 @@
|
||||
#include "../../configuration/memspec/MemSpecLPDDR4.h"
|
||||
#include "../../configuration/Configuration.h"
|
||||
|
||||
class RefreshCheckerLPDDR4Dummy;
|
||||
|
||||
class CheckerLPDDR4 final : public CheckerIF
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user