First part of same bank refresh (manager not done).

This commit is contained in:
Lukas Steiner
2020-08-28 16:17:47 +02:00
parent e9d206441e
commit ef90bfbb91
27 changed files with 508 additions and 59 deletions

View File

@@ -137,6 +137,7 @@ add_library(DRAMSysLibrary
src/controller/refresh/RefreshManagerDummy.cpp
src/controller/refresh/RefreshManagerRankwise.cpp
src/controller/refresh/RefreshManagerBankwise.cpp
src/controller/refresh/RefreshManagerGroupwise.cpp
src/controller/respqueue/RespQueueIF.h
src/controller/respqueue/RespQueueFifo.cpp

View File

@@ -28,6 +28,7 @@
"RCD": 22,
"REFM": 1,
"REFI": 6240,
"REFISB": 1560,
"RFC": 312,
"RL": 22,
"RPRE": 1,

View File

@@ -50,7 +50,8 @@
"RFC_dpr": 104,
"RFCsb_slr": 184,
"RFCsb_dlr": 62,
"REFI": 6240,
"REFI": 6240,
"REFISB": 1560,
"REFSBRD_slr": 48,
"REFSBRD_dlr": 24,
"RTRS": 2,

View File

@@ -74,3 +74,21 @@ sc_time MemSpec::getCommandLength(Command command) const
{
return tCK * commandLengthInCycles[command];
}
sc_time MemSpec::getRefreshIntervalAB() const
{
SC_REPORT_FATAL("MemSpec", "All bank refresh not supported");
return SC_ZERO_TIME;
}
sc_time MemSpec::getRefreshIntervalPB() const
{
SC_REPORT_FATAL("MemSpec", "Per bank refresh not supported");
return SC_ZERO_TIME;
}
sc_time MemSpec::getRefreshIntervalSB() const
{
SC_REPORT_FATAL("MemSpec", "Same bank refresh not supported");
return SC_ZERO_TIME;
}

View File

@@ -71,8 +71,9 @@ public:
virtual ~MemSpec() {}
virtual sc_time getRefreshIntervalAB() const = 0;
virtual sc_time getRefreshIntervalPB() const = 0;
virtual sc_time getRefreshIntervalAB() const;
virtual sc_time getRefreshIntervalPB() const;
virtual sc_time getRefreshIntervalSB() const;
virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const = 0;
virtual TimeInterval getIntervalOnDataStrobe(Command) const = 0;

View File

@@ -95,12 +95,6 @@ sc_time MemSpecDDR3::getRefreshIntervalAB() const
return tREFI;
}
sc_time MemSpecDDR3::getRefreshIntervalPB() const
{
SC_REPORT_FATAL("MemSpecDDR3", "Per bank refresh not supported");
return SC_ZERO_TIME;
}
// Returns the execution time for commands that have a fixed execution time
sc_time MemSpecDDR3::getExecutionTime(Command command, const tlm_generic_payload &) const
{

View File

@@ -88,7 +88,6 @@ public:
const double iDD3P1;
virtual sc_time getRefreshIntervalAB() const override;
virtual sc_time getRefreshIntervalPB() const override;
virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override;
virtual TimeInterval getIntervalOnDataStrobe(Command) const override;

View File

@@ -114,12 +114,6 @@ sc_time MemSpecDDR4::getRefreshIntervalAB() const
return tREFI;
}
sc_time MemSpecDDR4::getRefreshIntervalPB() const
{
SC_REPORT_FATAL("MemSpecDDR4", "Per bank refresh not supported");
return SC_ZERO_TIME;
}
// Returns the execution time for commands that have a fixed execution time
sc_time MemSpecDDR4::getExecutionTime(Command command, const tlm_generic_payload &) const
{

View File

@@ -95,7 +95,6 @@ public:
const double iDD62;
const double vDD2;
virtual sc_time getRefreshIntervalPB() const override;
virtual sc_time getRefreshIntervalAB() const override;
virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override;

View File

@@ -91,6 +91,7 @@ MemSpecDDR5::MemSpecDDR5(json &memspec)
tRFCsb_slr (tCK * parseUint(memspec["memtimingspec"]["RFCsb_slr"], "RFCsb_slr")),
tRFCsb_dlr (tCK * parseUint(memspec["memtimingspec"]["RFCsb_dlr"], "RFCsb_dlr")),
tREFI (tCK * parseUint(memspec["memtimingspec"]["REFI"], "REFI")),
tREFIsb (tCK * parseUint(memspec["memtimingspec"]["REFISB"], "REFISB")),
tREFSBRD_slr (tCK * parseUint(memspec["memtimingspec"]["REFSBRD_slr"], "REFSBRD_slr")),
tREFSBRD_dlr (tCK * parseUint(memspec["memtimingspec"]["REFSBRD_dlr"], "REFSBRD_dlr")),
tRTRS (tCK * parseUint(memspec["memtimingspec"]["RTRS"], "RTRS")),
@@ -113,10 +114,9 @@ sc_time MemSpecDDR5::getRefreshIntervalAB() const
return tREFI;
}
sc_time MemSpecDDR5::getRefreshIntervalPB() const
sc_time MemSpecDDR5::getRefreshIntervalSB() const
{
SC_REPORT_FATAL("MemSpecDDR5", "Per bank refresh not supported");
return SC_ZERO_TIME;
return tREFIsb;
}
// Returns the execution time for commands that have a fixed execution time

View File

@@ -85,6 +85,7 @@ public:
const sc_time tRFCsb_slr;
const sc_time tRFCsb_dlr;
const sc_time tREFI;
const sc_time tREFIsb;
const sc_time tREFSBRD_slr;
const sc_time tREFSBRD_dlr;
const sc_time tRTRS;
@@ -99,8 +100,8 @@ public:
// Currents and Voltages:
// TODO: to be completed
virtual sc_time getRefreshIntervalPB() const override;
virtual sc_time getRefreshIntervalAB() const override;
virtual sc_time getRefreshIntervalSB() const override;
virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override;
virtual TimeInterval getIntervalOnDataStrobe(Command) const override;

View File

@@ -85,8 +85,8 @@ public:
// Currents and Voltages:
// TODO: to be completed
virtual sc_time getRefreshIntervalPB() const override;
virtual sc_time getRefreshIntervalAB() const override;
virtual sc_time getRefreshIntervalPB() const override;
virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override;
virtual TimeInterval getIntervalOnDataStrobe(Command) const override;

View File

@@ -85,8 +85,8 @@ public:
// Currents and Voltages:
// TODO: to be completed
virtual sc_time getRefreshIntervalPB() const override;
virtual sc_time getRefreshIntervalAB() const override;
virtual sc_time getRefreshIntervalPB() const override;
virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override;
virtual TimeInterval getIntervalOnDataStrobe(Command) const override;

View File

@@ -87,8 +87,8 @@ public:
// Currents and Voltages:
// TODO: to be completed
virtual sc_time getRefreshIntervalPB() const override;
virtual sc_time getRefreshIntervalAB() const override;
virtual sc_time getRefreshIntervalPB() const override;
virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override;
virtual TimeInterval getIntervalOnDataStrobe(Command) const override;

View File

@@ -80,8 +80,8 @@ public:
// Currents and Voltages:
// TODO: to be completed
virtual sc_time getRefreshIntervalPB() const override;
virtual sc_time getRefreshIntervalAB() const override;
virtual sc_time getRefreshIntervalPB() const override;
virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override;
virtual TimeInterval getIntervalOnDataStrobe(Command) const override;

View File

@@ -80,8 +80,8 @@ public:
// Currents and Voltages:
// TODO: to be completed
virtual sc_time getRefreshIntervalPB() const override;
virtual sc_time getRefreshIntervalAB() const override;
virtual sc_time getRefreshIntervalPB() const override;
virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override;
virtual TimeInterval getIntervalOnDataStrobe(Command) const override;

View File

@@ -101,12 +101,6 @@ sc_time MemSpecWideIO::getRefreshIntervalAB() const
return tREFI;
}
sc_time MemSpecWideIO::getRefreshIntervalPB() const
{
SC_REPORT_FATAL("MemSpecWideIO", "Per bank refresh not supported");
return SC_ZERO_TIME;
}
// Returns the execution time for commands that have a fixed execution time
sc_time MemSpecWideIO::getExecutionTime(Command command, const tlm_generic_payload &) const
{

View File

@@ -93,7 +93,6 @@ public:
const double iDD62;
const double vDD2;
virtual sc_time getRefreshIntervalPB() const override;
virtual sc_time getRefreshIntervalAB() const override;
virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override;

View File

@@ -74,8 +74,8 @@ public:
// Currents and Voltages:
// TODO: to be completed
virtual sc_time getRefreshIntervalPB() const override;
virtual sc_time getRefreshIntervalAB() const override;
virtual sc_time getRefreshIntervalPB() const override;
virtual sc_time getExecutionTime(Command, const tlm::tlm_generic_payload &) const override;
virtual TimeInterval getIntervalOnDataStrobe(Command) const override;

View File

@@ -57,7 +57,7 @@ void BankMachine::updateState(Command command)
currentState = BmState::Activated;
currentRow = DramExtension::getRow(currentPayload);
break;
case Command::PRE: case Command::PREA:
case Command::PRE: case Command::PREA: case Command::PRESB:
currentState = BmState::Precharged;
break;
case Command::RD: case Command::WR:
@@ -70,7 +70,7 @@ void BankMachine::updateState(Command command)
case Command::PDEA: case Command::PDEP: case Command::SREFEN:
sleeping = true;
break;
case Command::REFA: case Command::REFB:
case Command::REFA: case Command::REFB: case Command::REFSB:
sleeping = false;
blocked = false;
break;

View File

@@ -54,9 +54,10 @@
#include "cmdmux/CmdMuxOldest.h"
#include "respqueue/RespQueueFifo.h"
#include "respqueue/RespQueueReorder.h"
#include "refresh/RefreshManagerRankwise.h"
#include "refresh/RefreshManagerDummy.h"
#include "refresh/RefreshManagerRankwise.h"
#include "refresh/RefreshManagerBankwise.h"
#include "refresh/RefreshManagerGroupwise.h"
#include "powerdown/PowerDownManagerStaggered.h"
#include "powerdown/PowerDownManagerDummy.h"
@@ -185,6 +186,15 @@ Controller::Controller(sc_module_name name) :
refreshManagers.push_back(manager);
}
}
else if (config.refreshPolicy == "Groupwise")
{
for (unsigned rankID = 0; rankID < memSpec->numberOfRanks; rankID++)
{
RefreshManagerIF *manager = new RefreshManagerGroupwise
(bankMachinesOnRank[rankID], powerDownManagers[rankID], Rank(rankID), checker);
refreshManagers.push_back(manager);
}
}
else if (config.refreshPolicy == "Bankwise")
{
for (unsigned rankID = 0; rankID < memSpec->numberOfRanks; rankID++)
@@ -271,28 +281,36 @@ void Controller::controllerMethod()
if (!readyCommands.empty())
{
commandTuple = cmdMux->selectCommand(readyCommands);
if (std::get<0>(commandTuple) != Command::NOP) // can happen with FIFO strict
Command selectedCommand = std::get<0>(commandTuple);
if (selectedCommand != Command::NOP) // can happen with FIFO strict
{
Rank rank = DramExtension::getRank(std::get<1>(commandTuple));
BankGroup bankgroup = DramExtension::getBankGroup(std::get<1>(commandTuple));
Bank bank = DramExtension::getBank(std::get<1>(commandTuple));
tlm_generic_payload *selectedPayload = std::get<1>(commandTuple);
Rank rank = DramExtension::getRank(selectedPayload);
BankGroup bankgroup = DramExtension::getBankGroup(selectedPayload);
Bank bank = DramExtension::getBank(selectedPayload);
if (isRankCommand(std::get<0>(commandTuple)))
if (isRankCommand(selectedCommand))
{
for (auto it : bankMachinesOnRank[rank.ID()])
it->updateState(std::get<0>(commandTuple));
it->updateState(selectedCommand);
}
else if (isGroupCommand(selectedCommand))
{
for (unsigned bankID = (bank.ID() % memSpec->banksPerGroup);
bankID < memSpec->banksPerRank; bankID += memSpec->banksPerGroup)
bankMachinesOnRank[rank.ID()][bankID]->updateState(selectedCommand);
}
else
bankMachines[bank.ID()]->updateState(std::get<0>(commandTuple));
bankMachines[bank.ID()]->updateState(selectedCommand);
refreshManagers[rank.ID()]->updateState(std::get<0>(commandTuple));
powerDownManagers[rank.ID()]->updateState(std::get<0>(commandTuple));
checker->insert(std::get<0>(commandTuple), rank, bankgroup, bank);
refreshManagers[rank.ID()]->updateState(selectedCommand);
powerDownManagers[rank.ID()]->updateState(selectedCommand);
checker->insert(selectedCommand, rank, bankgroup, bank);
if (isCasCommand(std::get<0>(commandTuple)))
if (isCasCommand(selectedCommand))
{
scheduler->removeRequest(std::get<1>(commandTuple));
respQueue->insertPayload(std::get<1>(commandTuple), memSpec->getIntervalOnDataStrobe(std::get<0>(commandTuple)).end);
scheduler->removeRequest(selectedPayload);
respQueue->insertPayload(selectedPayload, memSpec->getIntervalOnDataStrobe(selectedCommand).end);
sc_time triggerTime = respQueue->getTriggerTime();
if (triggerTime != sc_max_time())
@@ -303,7 +321,7 @@ void Controller::controllerMethod()
if (ranksNumberOfPayloads[rank.ID()] == 0)
powerDownManagers[rank.ID()]->triggerEntry();
sendToDram(std::get<0>(commandTuple), std::get<1>(commandTuple));
sendToDram(selectedCommand, selectedPayload);
}
else
readyCmdBlocked = true;

View File

@@ -53,6 +53,9 @@ CheckerDDR5::CheckerDDR5()
(numberOfCommands(), std::vector<sc_time>(memSpec->numberOfBanks));
lastScheduledByCommand = std::vector<sc_time>(numberOfCommands());
lastScheduledByCommandAndBankInGroup = std::vector<std::vector<sc_time>>
(numberOfCommands(), std::vector<sc_time>(memSpec->numberOfRanks * memSpec->banksPerGroup));
last4ActivatesLogical = std::vector<std::queue<sc_time>>(memSpec->numberOfLogicalRanks);
last4ActivatesPhysical = std::vector<std::queue<sc_time>>(memSpec->numberOfPhysicalRanks);
@@ -80,6 +83,8 @@ CheckerDDR5::CheckerDDR5()
tRDPDEN = memSpec->tRL + tRD_BURST + memSpec->tCK;
tWRPDEN = memSpec->tWL + tWR_BURST + memSpec->tWR + memSpec->tCK;
tWRAPDEN = memSpec->tWL + tWR_BURST + memSpec->tWR + memSpec->tCK;
// TODO: tRTP BL 32!!! (check LPDDR4)
}
sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGroup bankgroup, Bank bank) const
@@ -91,6 +96,8 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGr
Rank physicalrank = Rank(logicalrank.ID() / memSpec->logicalRanksPerPhysicalRank);
Rank dimmrank = Rank(physicalrank.ID() / memSpec->physicalRanksPerDIMMRank);
unsigned bankInGroupID = rank.ID() * memSpec->banksPerGroup + bank.ID() % memSpec->banksPerGroup;
if (command == Command::RD || command == Command::RDA)
{
lastCommandStart = lastScheduledByCommandAndBank[Command::ACT][bank.ID()];
@@ -304,9 +311,37 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGr
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP - memSpec->tCK);
lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::PRESB][bankInGroupID];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP - memSpec->tCK);
lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::REFA][logicalrank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC_slr);
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC_slr - memSpec->tCK);
// TODO: No tRFC_dlr and tRFC_dpr between REFA and ACT?
lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::REFSB][bankInGroupID];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCsb_slr - memSpec->tCK);
// TODO: No tRFCsb_dlr between REFSB and ACT?
lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::REFSB][logicalrank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tREFSBRD_slr - memSpec->tCK);
lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::REFSB][physicalrank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tREFSBRD_dlr - memSpec->tCK);
if (last4ActivatesLogical[logicalrank.ID()].size() >= 4)
earliestTimeToStart = std::max(earliestTimeToStart, last4ActivatesLogical[logicalrank.ID()].front()
+ memSpec->tFAW_slr - memSpec->tCK);
if (last4ActivatesPhysical[physicalrank.ID()].size() >= 4)
earliestTimeToStart = std::max(earliestTimeToStart, last4ActivatesPhysical[physicalrank.ID()].front()
+ memSpec->tFAW_dlr - memSpec->tCK);
}
else if (command == Command::PRE)
{
@@ -329,6 +364,10 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGr
lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::PREA][physicalrank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD);
lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::PRESB][physicalrank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD);
}
else if (command == Command::PREA)
{
@@ -359,6 +398,40 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGr
lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::PREA][physicalrank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD);
// PRESB tPPD
}
else if (command == Command::PRESB)
{
lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::ACT][bankInGroupID];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRAS + memSpec->tCK);
lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::RD][bankInGroupID];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tCK);
lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::RDA][bankInGroupID];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRTP + memSpec->tCK);
lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::WR][bankInGroupID];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + memSpec->tCK);
lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::WRA][bankInGroupID];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRPRE + memSpec->tCK);
lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::PRE][physicalrank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD);
// PREA tRP
lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::PRESB][physicalrank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tPPD);
}
else if (command == Command::REFA)
{
@@ -393,6 +466,67 @@ sc_time CheckerDDR5::timeToSatisfyConstraints(Command command, Rank rank, BankGr
lastCommandStart = lastScheduledByCommandAndDIMMRank[Command::REFA][dimmrank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC_dpr);
// REFSB tRFCsb
// PRESB tRP
}
else if (command == Command::REFSB)
{
lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::ACT][bankInGroupID];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRC + memSpec->tCK);
lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::ACT][logicalrank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRRD_L_slr + memSpec->tCK);
lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::RDA][bankInGroupID];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tRDAACT + memSpec->tCK);
lastCommandStart = lastScheduledByCommandAndBank[Command::WRA][bank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + tWRAACT + memSpec->tCK);
lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::PRE][bankInGroupID];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP);
// PREA tRP
lastCommandStart = lastScheduledByCommandAndBankInGroup[Command::PRESB][bankInGroupID];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRP);
lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::REFA][logicalrank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC_slr);
// TODO: check this
lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::REFA][physicalrank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC_dlr);
// TODO: check this
lastCommandStart = lastScheduledByCommandAndDIMMRank[Command::REFA][dimmrank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC_dpr);
lastCommandStart = lastScheduledByCommandAndLogicalRank[Command::REFSB][logicalrank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCsb_slr);
lastCommandStart = lastScheduledByCommandAndPhysicalRank[Command::REFSB][physicalrank.ID()];
if (lastCommandStart != SC_ZERO_TIME)
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFCsb_dlr);
if (last4ActivatesLogical[logicalrank.ID()].size() >= 4)
earliestTimeToStart = std::max(earliestTimeToStart,
last4ActivatesLogical[logicalrank.ID()].front() + memSpec->tFAW_slr);
if (last4ActivatesPhysical[physicalrank.ID()].size() >= 4)
earliestTimeToStart = std::max(earliestTimeToStart,
last4ActivatesPhysical[physicalrank.ID()].front() + memSpec->tFAW_dlr);
}
else
SC_REPORT_FATAL("CheckerDDR5", "Unknown command!");
@@ -420,7 +554,10 @@ void CheckerDDR5::insert(Command command, Rank rank, BankGroup bankgroup, Bank b
lastCommandOnBus = sc_time_stamp() + memSpec->getCommandLength(command) - memSpec->tCK;
if (command == Command::ACT)
lastScheduledByCommandAndBankInGroup[command][rank.ID() * memSpec->banksPerGroup
+ bank.ID() % memSpec->banksPerGroup] = sc_time_stamp();
if (command == Command::ACT || command == Command::REFSB)
{
if (last4ActivatesLogical[logicalrank.ID()].size() == 4)
last4ActivatesLogical[logicalrank.ID()].pop();

View File

@@ -59,6 +59,8 @@ private:
std::vector<sc_time> lastScheduledByCommand;
sc_time lastCommandOnBus;
std::vector<std::vector<sc_time>> lastScheduledByCommandAndBankInGroup;
std::vector<std::queue<sc_time>> last4ActivatesPhysical;
std::vector<std::queue<sc_time>> last4ActivatesLogical;

View File

@@ -39,9 +39,9 @@
using namespace tlm;
RefreshManagerBankwise::RefreshManagerBankwise(std::vector<BankMachine *> &bankMachines,
RefreshManagerBankwise::RefreshManagerBankwise(std::vector<BankMachine *> &bankMachinesOnRank,
PowerDownManagerIF *powerDownManager, Rank rank, CheckerIF *checker)
: bankMachinesOnRank(bankMachines), powerDownManager(powerDownManager), rank(rank), checker(checker)
: bankMachinesOnRank(bankMachinesOnRank), powerDownManager(powerDownManager), rank(rank), checker(checker)
{
Configuration &config = Configuration::getInstance();
memSpec = config.memSpec;
@@ -50,8 +50,9 @@ RefreshManagerBankwise::RefreshManagerBankwise(std::vector<BankMachine *> &bankM
refreshPayloads = std::vector<tlm_generic_payload>(memSpec->banksPerRank);
for (unsigned bankID = 0; bankID < memSpec->banksPerRank; bankID++)
{
setUpDummy(refreshPayloads[bankID], 0, rank, bankMachines[bankID]->getBankGroup(), bankMachines[bankID]->getBank());
allBankMachines.push_back(bankMachines[bankID]);
setUpDummy(refreshPayloads[bankID], 0, rank, bankMachinesOnRank[bankID]->getBankGroup(),
bankMachinesOnRank[bankID]->getBank());
allBankMachines.push_back(bankMachinesOnRank[bankID]);
}
remainingBankMachines = allBankMachines;
currentBankMachine = *remainingBankMachines.begin();

View File

@@ -0,0 +1,209 @@
/*
* 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 "RefreshManagerGroupwise.h"
#include "../../configuration/Configuration.h"
#include "../../common/utils.h"
#include "../../common/dramExtensions.h"
using namespace tlm;
RefreshManagerGroupwise::RefreshManagerGroupwise(std::vector<BankMachine *> &bankMachines,
PowerDownManagerIF *powerDownManager, Rank rank, CheckerIF *checker)
: bankMachinesOnRank(bankMachines), powerDownManager(powerDownManager), rank(rank), checker(checker)
{
Configuration &config = Configuration::getInstance();
memSpec = config.memSpec;
timeForNextTrigger = memSpec->getRefreshIntervalPB();
refreshPayloads = std::vector<tlm_generic_payload>(memSpec->banksPerRank);
for (unsigned bankID = 0; bankID < memSpec->banksPerRank; bankID++)
{
setUpDummy(refreshPayloads[bankID], 0, rank, bankMachines[bankID]->getBankGroup(), bankMachines[bankID]->getBank());
allBankMachines.push_back(bankMachines[bankID]);
}
remainingBankMachines = allBankMachines;
currentBankMachine = *remainingBankMachines.begin();
maxPostponed = config.refreshMaxPostponed * memSpec->banksPerRank;
maxPulledin = -(config.refreshMaxPulledin * memSpec->banksPerRank);
}
std::tuple<Command, tlm_generic_payload *, sc_time> RefreshManagerGroupwise::getNextCommand()
{
return std::tuple<Command, tlm_generic_payload *, sc_time>
(nextCommand, &refreshPayloads[currentBankMachine->getBank().ID() % memSpec->banksPerRank], timeToSchedule);
}
sc_time RefreshManagerGroupwise::start()
{
timeToSchedule = sc_max_time();
nextCommand = Command::NOP;
if (sc_time_stamp() >= timeForNextTrigger)
{
powerDownManager->triggerInterruption();
if (sleeping)
return timeToSchedule;
if (sc_time_stamp() >= timeForNextTrigger + memSpec->getRefreshIntervalPB())
{
timeForNextTrigger += memSpec->getRefreshIntervalPB();
state = RmState::Regular;
}
if (state == RmState::Regular)
{
bool forcedRefresh = (flexibilityCounter == maxPostponed);
bool allBanksBusy = true;
if (!skipSelection)
{
currentIterator = remainingBankMachines.begin();
currentBankMachine = *remainingBankMachines.begin();
for (auto it = remainingBankMachines.begin(); it != remainingBankMachines.end(); it++)
{
if ((*it)->isIdle())
{
currentIterator = it;
currentBankMachine = *it;
allBanksBusy = false;
break;
}
}
}
if (allBanksBusy && !forcedRefresh)
{
flexibilityCounter++;
timeForNextTrigger += memSpec->getRefreshIntervalPB();
return timeForNextTrigger;
}
else
{
if (currentBankMachine->getState() == BmState::Activated)
nextCommand = Command::PRE;
else
{
nextCommand = Command::REFB;
if (forcedRefresh)
{
currentBankMachine->block();
skipSelection = true;
}
}
timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank,
currentBankMachine->getBankGroup(), currentBankMachine->getBank());
return timeToSchedule;
}
}
else // if (state == RmState::Pulledin)
{
bool allBanksBusy = true;
for (auto it = remainingBankMachines.begin(); it != remainingBankMachines.end(); it++)
{
if ((*it)->isIdle())
{
currentIterator = it;
currentBankMachine = *it;
allBanksBusy = false;
break;
}
}
if (allBanksBusy)
{
state = RmState::Regular;
timeForNextTrigger += memSpec->getRefreshIntervalPB();
return timeForNextTrigger;
}
else
{
if (currentBankMachine->getState() == BmState::Activated)
nextCommand = Command::PRE;
else
nextCommand = Command::REFB;
timeToSchedule = checker->timeToSatisfyConstraints(nextCommand, rank,
currentBankMachine->getBankGroup(), currentBankMachine->getBank());
return timeToSchedule;
}
}
}
else
return timeForNextTrigger;
}
void RefreshManagerGroupwise::updateState(Command command)
{
switch (command)
{
case Command::REFB:
skipSelection = false;
remainingBankMachines.erase(currentIterator);
if (remainingBankMachines.empty())
remainingBankMachines = allBankMachines;
if (state == RmState::Pulledin)
flexibilityCounter--;
else
state = RmState::Pulledin;
if (flexibilityCounter == maxPulledin)
{
state = RmState::Regular;
timeForNextTrigger += memSpec->getRefreshIntervalPB();
}
break;
case Command::REFA:
// Refresh command after SREFEX
state = RmState::Regular; // TODO: check if this assignment is necessary
timeForNextTrigger = sc_time_stamp() + memSpec->getRefreshIntervalPB();
sleeping = false;
break;
case Command::PDEA: case Command::PDEP:
sleeping = true;
break;
case Command::SREFEN:
sleeping = true;
timeForNextTrigger = sc_max_time();
break;
case Command::PDXA: case Command::PDXP:
sleeping = false;
break;
}
}

View File

@@ -0,0 +1,80 @@
/*
* 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 REFRESHMANAGERGROUPWISE_H
#define REFRESHMANAGERGROUPWISE_H
#include "RefreshManagerIF.h"
#include "../../configuration/memspec/MemSpec.h"
#include "../BankMachine.h"
#include "../powerdown/PowerDownManagerIF.h"
#include <vector>
#include <utility>
#include <list>
class RefreshManagerGroupwise final : public RefreshManagerIF
{
public:
RefreshManagerGroupwise(std::vector<BankMachine *> &, PowerDownManagerIF *, Rank, CheckerIF *);
virtual std::tuple<Command, tlm::tlm_generic_payload *, sc_time> getNextCommand() override;
virtual sc_time start() override;
virtual void updateState(Command) override;
private:
enum class RmState {Regular, Pulledin} state = RmState::Regular;
const MemSpec *memSpec;
std::vector<BankMachine *> &bankMachinesOnRank;
PowerDownManagerIF *powerDownManager;
std::vector<tlm::tlm_generic_payload> refreshPayloads;
sc_time timeForNextTrigger = sc_max_time();
sc_time timeToSchedule = sc_max_time();
Rank rank;
CheckerIF *checker;
Command nextCommand = Command::NOP;
std::list<BankMachine *> remainingBankMachines;
std::list<BankMachine *> allBankMachines;
std::list<BankMachine *>::iterator currentIterator;
BankMachine *currentBankMachine;
int flexibilityCounter = 0;
int maxPostponed = 0;
int maxPulledin = 0;
bool sleeping = false;
bool skipSelection = false;
};
#endif // REFRESHMANAGERGROUPWISE_H

View File

@@ -39,9 +39,9 @@
using namespace tlm;
RefreshManagerRankwise::RefreshManagerRankwise(std::vector<BankMachine *> &bankMachines,
RefreshManagerRankwise::RefreshManagerRankwise(std::vector<BankMachine *> &bankMachinesOnRank,
PowerDownManagerIF *powerDownManager, Rank rank, CheckerIF *checker)
: bankMachinesOnRank(bankMachines), powerDownManager(powerDownManager), rank(rank), checker(checker)
: bankMachinesOnRank(bankMachinesOnRank), powerDownManager(powerDownManager), rank(rank), checker(checker)
{
Configuration &config = Configuration::getInstance();
memSpec = config.memSpec;