Updated CheckerLPDDR4 for new refresh, some renaming.

This commit is contained in:
Lukas Steiner
2019-10-02 21:54:05 +02:00
parent f4a018cfb3
commit 4328f4550b
12 changed files with 110 additions and 153 deletions

View File

@@ -57,7 +57,7 @@ struct MemSpec
sc_time getReadAccessTime() const;
virtual sc_time getRefreshIntervalAB() const = 0;
virtual sc_time getRefreshIntervalSB() const = 0;
virtual sc_time getRefreshIntervalPB() const = 0;
virtual sc_time getExecutionTime(Command) const = 0;
virtual TimeInterval getIntervalOnDataStrobe(Command) const = 0;

View File

@@ -40,7 +40,7 @@ sc_time MemSpecDDR3::getRefreshIntervalAB() const
return tREFI;
}
sc_time MemSpecDDR3::getRefreshIntervalSB() const
sc_time MemSpecDDR3::getRefreshIntervalPB() const
{
SC_REPORT_FATAL("MemSpecDDR3", "Per bank refresh not supported");
return SC_ZERO_TIME;

View File

@@ -70,7 +70,7 @@ struct MemSpecDDR3 : public MemSpec
double iDD3P1;
sc_time getRefreshIntervalAB() const override;
sc_time getRefreshIntervalSB() const override;
sc_time getRefreshIntervalPB() const override;
sc_time getExecutionTime(Command) const override;
TimeInterval getIntervalOnDataStrobe(Command) const override;

View File

@@ -40,7 +40,7 @@ sc_time MemSpecDDR4::getRefreshIntervalAB() const
return tREFI;
}
sc_time MemSpecDDR4::getRefreshIntervalSB() const
sc_time MemSpecDDR4::getRefreshIntervalPB() const
{
SC_REPORT_FATAL("MemSpecDDR4", "Per bank refresh not supported");
return SC_ZERO_TIME;

View File

@@ -75,7 +75,7 @@ struct MemSpecDDR4 : public MemSpec
double iDD62;
double vDD2;
sc_time getRefreshIntervalSB() const override;
sc_time getRefreshIntervalPB() const override;
sc_time getRefreshIntervalAB() const override;
sc_time getExecutionTime(Command) const override;

View File

@@ -55,7 +55,7 @@ sc_time MemSpecLPDDR4::getRefreshIntervalAB() const
return tREFI;
}
sc_time MemSpecLPDDR4::getRefreshIntervalSB() const
sc_time MemSpecLPDDR4::getRefreshIntervalPB() const
{
return tREFIpb;
}

View File

@@ -80,7 +80,7 @@ struct MemSpecLPDDR4 : public MemSpec
MemSpecLPDDR4();
sc_time getRefreshIntervalSB() const override;
sc_time getRefreshIntervalPB() const override;
sc_time getRefreshIntervalAB() const override;
sc_time getExecutionTime(Command) const override;

View File

@@ -40,7 +40,7 @@ sc_time MemSpecWideIO::getRefreshIntervalAB() const
return tREFI;
}
sc_time MemSpecWideIO::getRefreshIntervalSB() const
sc_time MemSpecWideIO::getRefreshIntervalPB() const
{
SC_REPORT_FATAL("MemSpecWideIO", "Per bank refresh not supported");
return SC_ZERO_TIME;

View File

@@ -78,7 +78,7 @@ struct MemSpecWideIO : public MemSpec
double iDD62;
double vDD2;
sc_time getRefreshIntervalSB() const override;
sc_time getRefreshIntervalPB() const override;
sc_time getRefreshIntervalAB() const override;
sc_time getExecutionTime(Command) const override;

View File

@@ -41,13 +41,6 @@ CheckerLPDDR4::CheckerLPDDR4()
if (memSpec == nullptr)
SC_REPORT_FATAL("CheckerLPDDR4", "Wrong MemSpec chosen");
if (config.ControllerCoreRefDisable)
refreshChecker = new RefreshCheckerLPDDR4Dummy(memSpec);
else if (config.BankwiseLogic)
refreshChecker = new RefreshCheckerLPDDR4Bankwise(memSpec);
else
refreshChecker = new RefreshCheckerLPDDR4(memSpec);
lastScheduledByCommandAndBank = std::vector<std::vector<sc_time>>
(numberOfCommands(), std::vector<sc_time>(memSpec->NumberOfBanks));
lastScheduledByCommandAndRank = std::vector<std::vector<sc_time>>
@@ -57,11 +50,6 @@ CheckerLPDDR4::CheckerLPDDR4()
lastActivates = std::vector<std::queue<sc_time>>(memSpec->NumberOfRanks);
}
CheckerLPDDR4::~CheckerLPDDR4()
{
delete refreshChecker;
}
sc_time CheckerLPDDR4::delayToSatisfyConstraints(Command command, Rank rank, BankGroup, Bank bank) const
{
sc_time lastCommandStart;
@@ -82,6 +70,10 @@ sc_time CheckerLPDDR4::delayToSatisfyConstraints(Command command, Rank rank, Ban
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRPpb - 2 * memSpec->clk);
lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRPab - 2 * memSpec->clk);
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS + memSpec->tRPpb);
@@ -98,10 +90,12 @@ sc_time CheckerLPDDR4::delayToSatisfyConstraints(Command command, Rank rank, Ban
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCpb - 2 * memSpec->clk);
lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRD - 2 * memSpec->clk);
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)
{
@@ -123,8 +117,6 @@ sc_time CheckerLPDDR4::delayToSatisfyConstraints(Command command, Rank rank, Ban
lastCommandStart = lastScheduledByCommand[Command::WRA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + memSpec->clk + memSpec->tCCD + memSpec->tWTR);
refreshChecker->delayToSatisfyRD(bank, earliestTimeToStart);
}
else if (command == Command::WR || command == Command::WRA)
{
@@ -146,8 +138,6 @@ sc_time CheckerLPDDR4::delayToSatisfyConstraints(Command command, Rank rank, Ban
lastCommandStart = lastScheduledByCommand[Command::WRA];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD);
refreshChecker->delayToSatisfyWR(bank, earliestTimeToStart);
}
else if (command == Command::PRE)
{
@@ -165,8 +155,97 @@ sc_time CheckerLPDDR4::delayToSatisfyConstraints(Command command, Rank rank, Ban
lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD);
}
else if (command == Command::PREA)
{
lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()];
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS + 2 * memSpec->clk);
refreshChecker->delayToSatisfyPRE(bank, earliestTimeToStart);
lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD + memSpec->tRTP - 6 * memSpec->clk);
lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + 2 * memSpec->clk);
lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + memSpec->tCCD + memSpec->tWR + 3 * memSpec->clk);
lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + memSpec->tCCD + memSpec->tWR + 3 * memSpec->clk);
lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCpb);
}
else if (command == Command::REFA)
{
lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS + memSpec->tRPpb + 2 * memSpec->clk);
lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRPpb + 2 * memSpec->clk);
lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + memSpec->tCCD
+ memSpec->tWR + 3 * memSpec->clk + memSpec->tRPpb);
lastCommandStart = lastScheduledByCommandAndRank[Command::PRE][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRPpb);
lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRPab);
lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCab);
lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()]; // remove this if REFA and REFB are not mixed
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCpb);
}
else if (command == Command::REFB)
{
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS + memSpec->tRPpb + 2 * memSpec->clk);
lastCommandStart = lastScheduledByCommandAndRank[Command::ACT][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRD + 2 * memSpec->clk);
lastCommandStart = lastScheduledByCommandAndBank[Command::RDA][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tRPpb + 2 * memSpec->clk);
lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tWL + memSpec->tCCD
+ memSpec->tWR + 3 * memSpec->clk + memSpec->tRPpb);
lastCommandStart = lastScheduledByCommandAndBank[Command::PRE][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRPpb);
lastCommandStart = lastScheduledByCommandAndRank[Command::PREA][rank.ID()]; // remove this
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRPab);
lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()]; // remove this
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCab);
lastCommandStart = lastScheduledByCommandAndRank[Command::REFB][rank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCpb);
}
else
{
@@ -188,81 +267,10 @@ void CheckerLPDDR4::insert(Command command, Rank rank, BankGroup, Bank bank)
lastScheduledByCommand[command] = sc_time_stamp();
lastCommandOnBus = sc_time_stamp() + (memSpec->getCommandLength(command) - 1) * memSpec->clk;
if (command == Command::ACT)
if (command == Command::ACT) // TODO: FAW for REFB
{
if (lastActivates[rank.ID()].size() == 4)
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 RefreshCheckerLPDDR4::delayToSatisfyACT(Bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timeForNextPREA - memSpec->tRAS))
earliestTimeToStart = timeForNextREFA + memSpec->tRFCab;
}
void RefreshCheckerLPDDR4::delayToSatisfyRD(Bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timeForNextPREA - memSpec->tRTP))
earliestTimeToStart = timeForNextREFA + memSpec->tRFCab;
}
void RefreshCheckerLPDDR4::delayToSatisfyWR(Bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timeForNextPREA - memSpec->tWL - memSpec->tCCD - memSpec->tWR))
earliestTimeToStart = timeForNextREFA + memSpec->tRFCab;
}
void RefreshCheckerLPDDR4::delayToSatisfyPRE(Bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= timeForNextPREA)
earliestTimeToStart = timeForNextREFA + memSpec->tRFCab;
}
void RefreshCheckerLPDDR4::insert(Bank)
{
timeForNextREFA += memSpec->tREFI;
timeForNextPREA += memSpec->tREFI;
}
RefreshCheckerLPDDR4Bankwise::RefreshCheckerLPDDR4Bankwise(const MemSpecLPDDR4 *memSpec)
: RefreshCheckerLPDDR4Dummy(memSpec)
{
sc_time currentREFB = memSpec->tREFI - memSpec->clk * (memSpec->NumberOfBanks - 1);
sc_time currentPRE = currentREFB - std::max(memSpec->clk * memSpec->NumberOfBanks, memSpec->tRPpb);
for (unsigned bankID = 0; bankID < memSpec->NumberOfBanks; bankID++)
{
timesForNextREFB.push_back(currentREFB);
timesForNextPRE.push_back(currentPRE);
currentREFB += memSpec->clk;
currentPRE += memSpec->clk;
}
}
void RefreshCheckerLPDDR4Bankwise::delayToSatisfyACT(Bank bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timesForNextPRE[bank.ID()] - memSpec->tRAS))
earliestTimeToStart = timesForNextREFB[bank.ID()] + memSpec->tRFCpb;
}
void RefreshCheckerLPDDR4Bankwise::delayToSatisfyRD(Bank bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timesForNextPRE[bank.ID()] - memSpec->tRTP))
earliestTimeToStart = timesForNextREFB[bank.ID()] + memSpec->tRFCpb;
}
void RefreshCheckerLPDDR4Bankwise::delayToSatisfyWR(Bank bank, sc_time &earliestTimeToStart)
{
if (earliestTimeToStart >= (timesForNextPRE[bank.ID()] - memSpec->tWL - memSpec->tCCD - memSpec->tWR))
earliestTimeToStart = timesForNextREFB[bank.ID()] + memSpec->tRFCpb;
}
void RefreshCheckerLPDDR4Bankwise::insert(Bank bank)
{
timesForNextREFB[bank.ID()] += memSpec->tREFI;
timesForNextPRE[bank.ID()] += memSpec->tREFI;
}

View File

@@ -47,7 +47,6 @@ class CheckerLPDDR4 final : public CheckerIF
{
public:
CheckerLPDDR4();
~CheckerLPDDR4();
sc_time delayToSatisfyConstraints(Command, Rank, BankGroup, Bank) const;
void insert(Command, Rank, BankGroup, Bank);
@@ -62,58 +61,8 @@ private:
// Four activate window
std::vector<std::queue<sc_time>> lastActivates;
RefreshCheckerLPDDR4Dummy *refreshChecker;
// PowerDown TODO: Implement this method?
//sc_time getTimeConstraintToEnterPowerDown(Command lastCmd, Command pdnCmd) const;
};
class RefreshCheckerLPDDR4Dummy
{
protected:
friend class CheckerLPDDR4;
RefreshCheckerLPDDR4Dummy(const MemSpecLPDDR4 *memSpec) : memSpec(memSpec) {}
virtual ~RefreshCheckerLPDDR4Dummy() {}
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 MemSpecLPDDR4 *memSpec;
};
class RefreshCheckerLPDDR4 final : public RefreshCheckerLPDDR4Dummy
{
private:
friend class CheckerLPDDR4;
RefreshCheckerLPDDR4(const MemSpecLPDDR4 *memSpec)
: RefreshCheckerLPDDR4Dummy(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->tRPpb;
};
class RefreshCheckerLPDDR4Bankwise final : public RefreshCheckerLPDDR4Dummy
{
private:
friend class CheckerLPDDR4;
RefreshCheckerLPDDR4Bankwise(const MemSpecLPDDR4 *);
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 // CHECKERLPDDR4_H

View File

@@ -42,7 +42,7 @@ RefreshManagerBankwise::RefreshManagerBankwise(std::vector<BankMachine *> &bankM
{
memSpec = Configuration::getInstance().memSpec;
// TODO: implement for multiple ranks
sc_time currentREFB = memSpec->getRefreshIntervalSB() - memSpec->clk * (memSpec->NumberOfBanks - 1);
sc_time currentREFB = memSpec->getRefreshIntervalPB() - memSpec->clk * (memSpec->NumberOfBanks - 1);
sc_time currentPRE = currentREFB - std::max(memSpec->clk * memSpec->NumberOfBanks, memSpec->getExecutionTime(Command::PRE));
timeForNextTrigger = currentPRE;
@@ -65,7 +65,7 @@ std::pair<Command, tlm_generic_payload *> RefreshManagerBankwise::getNextCommand
auto it = triggerTimes.begin();
Bank bank = it->second;
triggerTimes.erase(it);
triggerTimes.insert(std::pair<sc_time, Bank>(timeForNextTrigger + memSpec->getRefreshIntervalSB(), bank));
triggerTimes.insert(std::pair<sc_time, Bank>(timeForNextTrigger + memSpec->getRefreshIntervalPB(), bank));
timeForNextTrigger = triggerTimes.begin()->first;
if (states[bank.ID()] == RmState::IDLE)
{