First version of power down working, added some helper functions for enum Command.
This commit is contained in:
@@ -90,17 +90,12 @@ SOURCES += \
|
||||
src/common/TlmRecorder.cpp \
|
||||
src/common/DebugManager.cpp \
|
||||
src/configuration/Configuration.cpp \
|
||||
src/controller/core/powerdown/PowerDownManagerTimeout.cpp \
|
||||
src/controller/core/powerdown/PowerDownManagerBankwise.cpp \
|
||||
src/controller/core/powerdown/PowerDownManager.cpp \
|
||||
src/simulation/MemoryManager.cpp \
|
||||
src/simulation/TemperatureController.cpp \
|
||||
src/configuration/ConfigurationLoader.cpp \
|
||||
src/controller/core/powerdown/NoPowerDown.cpp \
|
||||
src/controller/Command.cpp \
|
||||
src/error/errormodel.cpp \
|
||||
src/simulation/TracePlayer.cpp \
|
||||
src/controller/core/powerdown/PowerDownManagerTimeoutBankwise.cpp \
|
||||
src/simulation/TraceSetup.cpp \
|
||||
src/simulation/DRAMSys.cpp \
|
||||
src/simulation/Setup.cpp \
|
||||
@@ -155,7 +150,8 @@ SOURCES += \
|
||||
src/controller/checker/CheckerGDDR6.cpp \
|
||||
src/simulation/dram/DramGDDR5.cpp \
|
||||
src/simulation/dram/DramGDDR5X.cpp \
|
||||
src/simulation/dram/DramGDDR6.cpp
|
||||
src/simulation/dram/DramGDDR6.cpp \
|
||||
src/controller/powerdown/PowerDownManager.cpp
|
||||
|
||||
HEADERS += \
|
||||
src/common/third_party/tinyxml2/tinyxml2.h \
|
||||
@@ -164,9 +160,6 @@ HEADERS += \
|
||||
src/common/protocol.h \
|
||||
src/common/DebugManager.h \
|
||||
src/configuration/Configuration.h \
|
||||
src/controller/core/powerdown/PowerDownManagerTimeout.h \
|
||||
src/controller/core/powerdown/PowerDownManagerBankwise.h \
|
||||
src/controller/core/powerdown/PowerDownManager.h \
|
||||
src/simulation/TracePlayer.h \
|
||||
src/simulation/MemoryManager.h \
|
||||
src/simulation/dram/Dram.h \
|
||||
@@ -178,13 +171,10 @@ HEADERS += \
|
||||
src/simulation/TracePlayerListener.h \
|
||||
src/simulation/TraceGenerator.h \
|
||||
src/simulation/TemperatureController.h \
|
||||
src/controller/core/powerdown/NoPowerDown.h \
|
||||
src/controller/Command.h \
|
||||
src/controller/core/powerdown/IPowerDownManager.h \
|
||||
src/configuration/ConfigurationLoader.h \
|
||||
src/error/errormodel.h \
|
||||
src/simulation/ExampleInitiator.h \
|
||||
src/controller/core/powerdown/PowerDownManagerTimeoutBankwise.h \
|
||||
src/simulation/TraceSetup.h \
|
||||
src/simulation/DRAMSys.h \
|
||||
src/simulation/Setup.h \
|
||||
@@ -244,7 +234,8 @@ HEADERS += \
|
||||
src/controller/checker/CheckerGDDR6.h \
|
||||
src/simulation/dram/DramGDDR5.h \
|
||||
src/simulation/dram/DramGDDR5X.h \
|
||||
src/simulation/dram/DramGDDR6.h
|
||||
src/simulation/dram/DramGDDR6.h \
|
||||
src/controller/powerdown/PowerDownManager.h
|
||||
#src/common/third_party/json/include/nlohmann/json.hpp \
|
||||
|
||||
thermalsim = $$(THERMALSIM)
|
||||
|
||||
@@ -61,6 +61,8 @@ sc_time MemSpecDDR3::getExecutionTime(Command command, const tlm_generic_payload
|
||||
return tRFC;
|
||||
else if (command == Command::REFB)
|
||||
return tRFC;
|
||||
else if (command == Command::PDXA || command == Command::PDXP || command == Command::SREFEX)
|
||||
return clk;
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL("getExecutionTime",
|
||||
|
||||
@@ -66,6 +66,8 @@ void BankMachine::updateState(Command command)
|
||||
currentState = BmState::Precharged;
|
||||
currentPayload = nullptr;
|
||||
}
|
||||
else if (command == Command::PDEA || command == Command::PDEP)
|
||||
blocked = true;
|
||||
else if (command == Command::REFA || command == Command::REFB
|
||||
|| command == Command::PDXA || command == Command::PDXP)
|
||||
blocked = false;
|
||||
|
||||
@@ -103,15 +103,15 @@ std::string commandToString(Command command)
|
||||
const std::vector<Command> &getAllCommands()
|
||||
{
|
||||
static std::vector<Command> allCommands( { Command::NOP,
|
||||
Command::PRE,
|
||||
Command::PREA,
|
||||
Command::ACT,
|
||||
Command::RD,
|
||||
Command::WR,
|
||||
Command::RDA,
|
||||
Command::WRA,
|
||||
Command::REFA,
|
||||
Command::PRE,
|
||||
Command::ACT,
|
||||
Command::REFB,
|
||||
Command::PREA,
|
||||
Command::REFA,
|
||||
Command::PDEA,
|
||||
Command::PDXA,
|
||||
Command::PDEP,
|
||||
@@ -137,18 +137,38 @@ bool commandIsIn(Command command, std::vector<Command> commands)
|
||||
}
|
||||
|
||||
std::array<tlm_phase, 16> phaseOfCommand = {UNINITIALIZED_PHASE,
|
||||
BEGIN_PRE,
|
||||
BEGIN_PREA,
|
||||
BEGIN_ACT,
|
||||
BEGIN_RD,
|
||||
BEGIN_WR,
|
||||
BEGIN_RDA,
|
||||
BEGIN_WRA,
|
||||
BEGIN_REFA,
|
||||
BEGIN_PRE,
|
||||
BEGIN_ACT,
|
||||
BEGIN_REFB,
|
||||
BEGIN_PREA,
|
||||
BEGIN_REFA,
|
||||
BEGIN_PDNA,
|
||||
END_PDNA,
|
||||
BEGIN_PDNP,
|
||||
END_PDNP,
|
||||
BEGIN_SREF,
|
||||
END_SREF};
|
||||
|
||||
bool isBankCommand(Command command)
|
||||
{
|
||||
return (command <= 7);
|
||||
}
|
||||
|
||||
bool isRankCommand(Command command)
|
||||
{
|
||||
return (command >= 8);
|
||||
}
|
||||
|
||||
bool isCasCommand(Command command)
|
||||
{
|
||||
return (command <= 4);
|
||||
}
|
||||
|
||||
bool isRasCommand(Command command)
|
||||
{
|
||||
return (command >= 5);
|
||||
}
|
||||
|
||||
@@ -47,15 +47,15 @@ using namespace tlm;
|
||||
enum Command
|
||||
{
|
||||
NOP,
|
||||
PRE,
|
||||
PREA,
|
||||
ACT,
|
||||
RD,
|
||||
WR,
|
||||
RDA,
|
||||
WRA,
|
||||
REFA,
|
||||
PRE,
|
||||
ACT,
|
||||
REFB,
|
||||
PREA,
|
||||
REFA,
|
||||
PDEA,
|
||||
PDXA,
|
||||
PDEP,
|
||||
@@ -68,6 +68,10 @@ std::string commandToString(Command command);
|
||||
const std::vector<Command> &getAllCommands();
|
||||
unsigned numberOfCommands();
|
||||
bool commandIsIn(Command command, std::vector<Command> commands);
|
||||
bool isBankCommand(Command command);
|
||||
bool isRankCommand(Command command);
|
||||
bool isCasCommand(Command command);
|
||||
bool isRasCommand(Command command);
|
||||
|
||||
extern std::array<tlm_phase, 16> phaseOfCommand;
|
||||
|
||||
|
||||
@@ -133,6 +133,14 @@ Controller::Controller(sc_module_name name) :
|
||||
bankMachines.begin() + (rankID + 1) * memSpec->BanksPerRank));
|
||||
}
|
||||
|
||||
for (unsigned rankID = 0; rankID < memSpec->NumberOfRanks; rankID++)
|
||||
{
|
||||
PowerDownManager *manager = new PowerDownManager(bankMachinesOnRank[rankID], Rank(rankID), checker);
|
||||
powerDownManagers.push_back(manager);
|
||||
manager->triggerEntry();
|
||||
controllerEvent.notify(manager->start());
|
||||
}
|
||||
|
||||
if (config.ControllerCoreRefDisable)
|
||||
{
|
||||
for (unsigned rankID = 0; rankID < memSpec->NumberOfRanks; rankID++)
|
||||
@@ -143,7 +151,7 @@ Controller::Controller(sc_module_name name) :
|
||||
for (unsigned rankID = 0; rankID < memSpec->NumberOfRanks; rankID++)
|
||||
{
|
||||
RefreshManagerIF *manager = new RefreshManagerBankwise
|
||||
(bankMachinesOnRank[rankID], Rank(rankID), checker);
|
||||
(bankMachinesOnRank[rankID], powerDownManagers[rankID], Rank(rankID), checker);
|
||||
refreshManagers.push_back(manager);
|
||||
controllerEvent.notify(manager->start());
|
||||
}
|
||||
@@ -153,7 +161,7 @@ Controller::Controller(sc_module_name name) :
|
||||
for (unsigned rankID = 0; rankID < memSpec->NumberOfRanks; rankID++)
|
||||
{
|
||||
RefreshManagerIF *manager = new RefreshManager
|
||||
(bankMachinesOnRank[rankID], Rank(rankID), checker);
|
||||
(bankMachinesOnRank[rankID], powerDownManagers[rankID], Rank(rankID), checker);
|
||||
refreshManagers.push_back(manager);
|
||||
controllerEvent.notify(manager->start());
|
||||
}
|
||||
@@ -211,11 +219,14 @@ void Controller::controllerMethod()
|
||||
// (4) Start refresh managers to issue requests for the current time
|
||||
for (auto it : refreshManagers)
|
||||
it->start();
|
||||
for (auto it : powerDownManagers)
|
||||
it->start();
|
||||
|
||||
// (5) Choose one request and send it to DRAM
|
||||
std::pair<Command, tlm_generic_payload *> commandPair;
|
||||
std::vector<std::pair<Command, tlm_generic_payload *>> readyCommands;
|
||||
bool readyCmdBlocked = false;
|
||||
// TODO: check if all parts have to be called
|
||||
// (5.1) Check for bank commands (PRE, ACT, RD/RDA or WR/WRA)
|
||||
for (auto it : bankMachines)
|
||||
{
|
||||
@@ -230,13 +241,21 @@ void Controller::controllerMethod()
|
||||
if (commandPair.second != nullptr)
|
||||
readyCommands.push_back(commandPair);
|
||||
}
|
||||
// (5.3) Check for power-down commands (...TODO)
|
||||
for (auto it : powerDownManagers)
|
||||
{
|
||||
commandPair = it->getNextCommand();
|
||||
if (commandPair.second != nullptr)
|
||||
readyCommands.push_back(commandPair);
|
||||
}
|
||||
|
||||
if (!readyCommands.empty())
|
||||
{
|
||||
commandPair = commandMux->selectCommand(readyCommands);
|
||||
if (commandPair.second != nullptr) // can happen with FIFO strict
|
||||
{
|
||||
Rank rank = DramExtension::getRank(commandPair.second);
|
||||
if (commandPair.first == Command::PREA || commandPair.first == Command::REFA)
|
||||
if (isRankCommand(commandPair.first))
|
||||
{
|
||||
for (auto it : bankMachinesOnRank[rank.ID()])
|
||||
it->updateState(commandPair.first);
|
||||
@@ -247,6 +266,7 @@ void Controller::controllerMethod()
|
||||
bankMachines[bank.ID()]->updateState(commandPair.first);
|
||||
}
|
||||
refreshManagers[rank.ID()]->updateState(commandPair.first, commandPair.second);
|
||||
powerDownManagers[rank.ID()]->updateState(commandPair.first);
|
||||
sendToDram(commandPair.first, commandPair.second);
|
||||
}
|
||||
else
|
||||
@@ -254,6 +274,7 @@ void Controller::controllerMethod()
|
||||
}
|
||||
|
||||
// (6) Restart bank machines and refresh managers to issue new requests for the future
|
||||
// TODO: check if all calls are necessary
|
||||
for (auto it : bankMachines)
|
||||
{
|
||||
sc_time delay = it->start();
|
||||
@@ -262,6 +283,8 @@ void Controller::controllerMethod()
|
||||
}
|
||||
for (auto it : refreshManagers)
|
||||
controllerEvent.notify(it->start());
|
||||
for (auto it : powerDownManagers)
|
||||
controllerEvent.notify(it->start());
|
||||
}
|
||||
|
||||
tlm_sync_enum Controller::nb_transport_fw(tlm_generic_payload &trans,
|
||||
@@ -317,15 +340,21 @@ void Controller::releasePayload()
|
||||
uint64_t id __attribute__((unused)) = DramExtension::getPayloadID(payloadToRelease);
|
||||
PRINTDEBUGMESSAGE(name(), "Payload " + std::to_string(id) + " left system.");
|
||||
|
||||
totalNumberOfPayloads--;
|
||||
ranksNumberOfPayloads[DramExtension::getRank(payloadToRelease).ID()]--;
|
||||
Rank rank = DramExtension::getRank(payloadToRelease);
|
||||
|
||||
payloadToRelease->release();
|
||||
payloadToRelease = nullptr;
|
||||
timeToRelease = sc_max_time();
|
||||
numberOfTransactionsServed++;
|
||||
|
||||
totalNumberOfPayloads--;
|
||||
ranksNumberOfPayloads[rank.ID()]--;
|
||||
|
||||
if (totalNumberOfPayloads == 0)
|
||||
startBandwidthIdleCollector();
|
||||
|
||||
if (ranksNumberOfPayloads[rank.ID()] == 0)
|
||||
powerDownManagers[rank.ID()]->triggerEntry();
|
||||
}
|
||||
|
||||
void Controller::acquirePayload()
|
||||
@@ -333,13 +362,19 @@ void Controller::acquirePayload()
|
||||
uint64_t id __attribute__((unused)) = DramExtension::getPayloadID(payloadToAcquire);
|
||||
PRINTDEBUGMESSAGE(name(), "Payload " + std::to_string(id) + " entered system.");
|
||||
|
||||
Rank rank = DramExtension::getRank(payloadToAcquire);
|
||||
|
||||
if (totalNumberOfPayloads == 0)
|
||||
endBandwithIdleCollector();
|
||||
|
||||
if(ranksNumberOfPayloads[rank.ID()] == 0)
|
||||
powerDownManagers[rank.ID()]->triggerExit();
|
||||
|
||||
totalNumberOfPayloads++;
|
||||
ranksNumberOfPayloads[rank.ID()]++;
|
||||
|
||||
scheduler->storeRequest(payloadToAcquire);
|
||||
payloadToAcquire->acquire();
|
||||
totalNumberOfPayloads++;
|
||||
ranksNumberOfPayloads[DramExtension::getRank(payloadToAcquire).ID()]++;
|
||||
payloadToAcquire->set_response_status(TLM_OK_RESPONSE);
|
||||
sendToFrontend(payloadToAcquire, END_REQ);
|
||||
payloadToAcquire = nullptr;
|
||||
|
||||
@@ -50,11 +50,13 @@
|
||||
#include "../common/DebugManager.h"
|
||||
#include "checker/CheckerIF.h"
|
||||
#include "refresh/RefreshManagerIF.h"
|
||||
#include "powerdown/PowerDownManager.h"
|
||||
|
||||
using namespace tlm;
|
||||
|
||||
class BankMachine;
|
||||
class SchedulerIF;
|
||||
class PowerDownManager;
|
||||
|
||||
class Controller : public GenericController
|
||||
{
|
||||
@@ -87,6 +89,7 @@ private:
|
||||
SchedulerIF *scheduler;
|
||||
CheckerIF *checker;
|
||||
std::vector<RefreshManagerIF *> refreshManagers;
|
||||
std::vector<PowerDownManager *> powerDownManagers;
|
||||
|
||||
void releasePayload();
|
||||
void acquirePayload();
|
||||
|
||||
@@ -92,6 +92,18 @@ sc_time CheckerDDR3::delayToSatisfyConstraints(Command command, Rank rank, BankG
|
||||
// if (lastCommandStart != SC_ZERO_TIME)
|
||||
// earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::PDXP][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXS);
|
||||
|
||||
if (lastActivates[rank.ID()].size() >= 4)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastActivates[rank.ID()].front() + memSpec->tFAW);
|
||||
}
|
||||
@@ -125,6 +137,14 @@ sc_time CheckerDDR3::delayToSatisfyConstraints(Command command, Rank rank, BankG
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
|
||||
+ memSpec->tWL + burstClocks + memSpec->tWTR);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXSDLL);
|
||||
}
|
||||
else if (command == Command::WR || command == Command::WRA)
|
||||
{
|
||||
@@ -148,6 +168,14 @@ sc_time CheckerDDR3::delayToSatisfyConstraints(Command command, Rank rank, BankG
|
||||
lastCommandStart = lastScheduledByCommand[Command::WRA];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCCD);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXSDLL);
|
||||
}
|
||||
else if (command == Command::PRE)
|
||||
{
|
||||
@@ -162,6 +190,10 @@ sc_time CheckerDDR3::delayToSatisfyConstraints(Command command, Rank rank, BankG
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
|
||||
+ memSpec->tWL + burstClocks + memSpec->tWR);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP);
|
||||
}
|
||||
else if (command == Command::PREA)
|
||||
{
|
||||
@@ -185,6 +217,10 @@ sc_time CheckerDDR3::delayToSatisfyConstraints(Command command, Rank rank, BankG
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
|
||||
+ memSpec->tWL + burstClocks + memSpec->tWR);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP);
|
||||
}
|
||||
else if (command == Command::REFA)
|
||||
{
|
||||
@@ -212,6 +248,115 @@ sc_time CheckerDDR3::delayToSatisfyConstraints(Command command, Rank rank, BankG
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::PDXP][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXS);
|
||||
}
|
||||
else if (command == Command::PDEA)
|
||||
{
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
|
||||
+ memSpec->tRL + 5 * memSpec->clk);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
|
||||
+ memSpec->tRL + 5 * memSpec->clk);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::WR][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
|
||||
+ memSpec->tWL + 4 * memSpec->clk + memSpec->tWR);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
|
||||
+ memSpec->tWL + 5 * memSpec->clk + memSpec->tWR);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::PDXA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCKE);
|
||||
}
|
||||
else if (command == Command::PDXA)
|
||||
{
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::PDEA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCKE);
|
||||
}
|
||||
else if (command == Command::PDEP)
|
||||
{
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::RD][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
|
||||
+ memSpec->tRL + 5 * memSpec->clk);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
|
||||
+ memSpec->tRL + 5 * memSpec->clk);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
|
||||
+ memSpec->tWL + 5 * memSpec->clk + memSpec->tWR);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::PDXP][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCKE);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXS);
|
||||
}
|
||||
else if (command == Command::PDXP)
|
||||
{
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::PDEP][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCKE);
|
||||
}
|
||||
else if (command == Command::SREFEN)
|
||||
{
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::RDA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
|
||||
+ std::max(memSpec->tRL + 5 * memSpec->clk, memSpec->tAL + memSpec->tRTP + memSpec->tRP));
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::WRA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart
|
||||
+ std::max(memSpec->tWL + 5 * memSpec->clk + memSpec->tWR, 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::PDXP][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXP);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::REFA][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tRFC);
|
||||
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEX][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tXS);
|
||||
}
|
||||
else if (command == Command::SREFEX)
|
||||
{
|
||||
lastCommandStart = lastScheduledByCommandAndRank[Command::SREFEN][rank.ID()];
|
||||
if (lastCommandStart != SC_ZERO_TIME)
|
||||
earliestTimeToStart = std::max(earliestTimeToStart, lastCommandStart + memSpec->tCKESR);
|
||||
}
|
||||
else
|
||||
reportFatal("CheckerDDR3", "Unknown command!");
|
||||
|
||||
@@ -41,7 +41,7 @@ CmdMuxStrict::selectCommand(std::vector<std::pair<Command, tlm_generic_payload *
|
||||
{
|
||||
for (auto it : readyCommands)
|
||||
{
|
||||
if (commandIsIn(it.first, {Command::RD, Command::RDA, Command::WR, Command::WRA}))
|
||||
if (isCasCommand(it.first))
|
||||
{
|
||||
if (DramExtension::getPayloadID(it.second) == nextPayloadID)
|
||||
{
|
||||
@@ -52,8 +52,7 @@ CmdMuxStrict::selectCommand(std::vector<std::pair<Command, tlm_generic_payload *
|
||||
}
|
||||
for (auto it : readyCommands)
|
||||
{
|
||||
if (commandIsIn(it.first, {Command::ACT, Command::PRE,
|
||||
Command::PREA, Command::REFA, Command::REFB}))
|
||||
if (isRasCommand(it.first))
|
||||
return it;
|
||||
}
|
||||
return std::pair<Command, tlm_generic_payload *>(Command::NOP, nullptr);
|
||||
|
||||
114
DRAMSys/library/src/controller/powerdown/PowerDownManager.cpp
Normal file
114
DRAMSys/library/src/controller/powerdown/PowerDownManager.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2019, University of 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 "PowerDownManager.h"
|
||||
#include "../../common/utils.h"
|
||||
|
||||
PowerDownManager::PowerDownManager(std::vector<BankMachine *> &bankMachines, Rank rank, CheckerIF *checker)
|
||||
: bankMachines(bankMachines), rank(rank), checker(checker)
|
||||
{
|
||||
setUpDummy(powerDownPayload, rank);
|
||||
}
|
||||
|
||||
void PowerDownManager::triggerEntry()
|
||||
{
|
||||
if (state == PdmState::Idle)
|
||||
triggered = true;
|
||||
}
|
||||
|
||||
void PowerDownManager::triggerExit()
|
||||
{
|
||||
if (state == PdmState::Idle)
|
||||
triggered = false;
|
||||
else
|
||||
triggered = true;
|
||||
}
|
||||
|
||||
std::pair<Command, tlm_generic_payload *> PowerDownManager::getNextCommand()
|
||||
{
|
||||
if (sc_time_stamp() == timeToSchedule)
|
||||
return std::pair<Command, tlm_generic_payload *>(nextCommand, &powerDownPayload);
|
||||
else
|
||||
return std::pair<Command, tlm_generic_payload *>(Command::NOP, nullptr);
|
||||
}
|
||||
|
||||
sc_time PowerDownManager::start()
|
||||
{
|
||||
timeToSchedule = sc_max_time();
|
||||
sc_time delay = sc_max_time() - sc_time_stamp();
|
||||
|
||||
if (triggered)
|
||||
{
|
||||
if (state == PdmState::Idle)
|
||||
{
|
||||
nextCommand = Command::PDEP;
|
||||
for (auto it : bankMachines)
|
||||
{
|
||||
if(it->getState() == BmState::Activated)
|
||||
{
|
||||
nextCommand = Command::PDEA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (state == PdmState::ActivePd)
|
||||
nextCommand = Command::PDXA;
|
||||
else if (state == PdmState::PrechargePd)
|
||||
nextCommand = Command::PDXP;
|
||||
// TODO: add self refresh
|
||||
delay = checker->delayToSatisfyConstraints(nextCommand, rank, BankGroup(0), Bank(0));
|
||||
timeToSchedule = sc_time_stamp() + delay;
|
||||
}
|
||||
|
||||
return delay;
|
||||
}
|
||||
|
||||
void PowerDownManager::updateState(Command command)
|
||||
{
|
||||
if (command == Command::PDEA)
|
||||
{
|
||||
state = PdmState::ActivePd;
|
||||
triggered = false;
|
||||
}
|
||||
else if (command == Command::PDEP)
|
||||
{
|
||||
state = PdmState::PrechargePd;
|
||||
triggered = false;
|
||||
}
|
||||
else if (command == Command::PDXA || command == Command::PDXP)
|
||||
{
|
||||
state = PdmState::Idle;
|
||||
triggered = false;
|
||||
}
|
||||
}
|
||||
69
DRAMSys/library/src/controller/powerdown/PowerDownManager.h
Normal file
69
DRAMSys/library/src/controller/powerdown/PowerDownManager.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2019, University of 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 POWERDOWNMANAGER_H
|
||||
#define POWERDOWNMANAGER_H
|
||||
|
||||
#include "../BankMachine.h"
|
||||
#include "../checker/CheckerIF.h"
|
||||
|
||||
using namespace tlm;
|
||||
|
||||
class BankMachine;
|
||||
|
||||
class PowerDownManager
|
||||
{
|
||||
public:
|
||||
PowerDownManager(std::vector<BankMachine *> &, Rank, CheckerIF *);
|
||||
|
||||
void triggerEntry();
|
||||
void triggerExit();
|
||||
|
||||
std::pair<Command, tlm_generic_payload *> getNextCommand();
|
||||
void updateState(Command);
|
||||
sc_time start();
|
||||
|
||||
private:
|
||||
enum class PdmState {Idle, ActivePd, PrechargePd, SelfRefresh} state = PdmState::Idle;
|
||||
bool triggered = false;
|
||||
std::vector<BankMachine *> &bankMachines;
|
||||
tlm_generic_payload powerDownPayload;
|
||||
Rank rank;
|
||||
CheckerIF *checker;
|
||||
|
||||
sc_time timeToSchedule;
|
||||
Command nextCommand;
|
||||
};
|
||||
|
||||
#endif // POWERDOWNMANAGER_H
|
||||
@@ -37,8 +37,9 @@
|
||||
#include "../../configuration/Configuration.h"
|
||||
#include "../../common/utils.h"
|
||||
|
||||
RefreshManager::RefreshManager(std::vector<BankMachine *> &bankMachines, Rank rank, CheckerIF *checker)
|
||||
: bankMachines(bankMachines), rank(rank), checker(checker)
|
||||
RefreshManager::RefreshManager(std::vector<BankMachine *> &bankMachines,
|
||||
PowerDownManager *powerDownManager, Rank rank, CheckerIF *checker)
|
||||
: bankMachines(bankMachines), powerDownManager(powerDownManager), rank(rank), checker(checker)
|
||||
{
|
||||
Configuration &config = Configuration::getInstance();
|
||||
memSpec = config.memSpec;
|
||||
@@ -53,23 +54,22 @@ RefreshManager::RefreshManager(std::vector<BankMachine *> &bankMachines, Rank ra
|
||||
|
||||
std::pair<Command, tlm_generic_payload *> RefreshManager::getNextCommand()
|
||||
{
|
||||
if (sc_time_stamp() == timeToSchedule)
|
||||
if (sc_time_stamp() == timeToSchedule && !blocked)
|
||||
return std::pair<Command, tlm_generic_payload *>(nextCommand, &refreshPayload);
|
||||
else
|
||||
return std::pair<Command, tlm_generic_payload *>(Command::NOP, nullptr);
|
||||
}
|
||||
|
||||
void RefreshManager::block()
|
||||
{
|
||||
blocked = true;
|
||||
}
|
||||
|
||||
sc_time RefreshManager::start()
|
||||
{
|
||||
timeToSchedule = sc_max_time();
|
||||
|
||||
if (sc_time_stamp() >= timeForNextTrigger)
|
||||
{
|
||||
powerDownManager->triggerExit();
|
||||
if (blocked)
|
||||
return sc_max_time() - sc_time_stamp();
|
||||
|
||||
if (sc_time_stamp() >= timeForNextTrigger + memSpec->getRefreshIntervalAB())
|
||||
{
|
||||
timeForNextTrigger += memSpec->getRefreshIntervalAB();
|
||||
@@ -121,7 +121,7 @@ sc_time RefreshManager::start()
|
||||
{
|
||||
for (auto it : bankMachines)
|
||||
{
|
||||
if (!it->isIdle()) // at least one bank is active -> abort pulling in
|
||||
if (!it->isIdle()) // at least one bank has a payload -> abort pulling in
|
||||
{
|
||||
state = RmState::Regular;
|
||||
timeForNextTrigger += memSpec->getRefreshIntervalAB();
|
||||
@@ -158,6 +158,8 @@ void RefreshManager::updateState(Command command, tlm_generic_payload *)
|
||||
{
|
||||
state = RmState::Regular;
|
||||
timeForNextTrigger += memSpec->getRefreshIntervalAB();
|
||||
// TODO: is only allowed if all banks are still idle
|
||||
//powerDownManager->triggerEntry();
|
||||
}
|
||||
}
|
||||
else if (command == Command::PREA)
|
||||
@@ -165,6 +167,11 @@ void RefreshManager::updateState(Command command, tlm_generic_payload *)
|
||||
// if PREA was successful we will do the refresh in any case
|
||||
for (auto it : bankMachines)
|
||||
it->block();
|
||||
// TODO: remove for and insert blocking directly into BM
|
||||
state = RmState::Precharged;
|
||||
}
|
||||
else if (command == Command::PDEA || command == Command::PDEP)
|
||||
blocked = true;
|
||||
else if (command == Command::PDXA || command == Command::PDXP)
|
||||
blocked = false;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "RefreshManagerIF.h"
|
||||
#include "../../configuration/memspec/MemSpec.h"
|
||||
#include "../BankMachine.h"
|
||||
#include "../powerdown/PowerDownManager.h"
|
||||
#include "../checker/CheckerIF.h"
|
||||
|
||||
using namespace tlm;
|
||||
@@ -45,17 +46,17 @@ using namespace tlm;
|
||||
class RefreshManager final : public RefreshManagerIF
|
||||
{
|
||||
public:
|
||||
RefreshManager(std::vector<BankMachine *> &, Rank, CheckerIF *);
|
||||
RefreshManager(std::vector<BankMachine *> &, PowerDownManager *, Rank, CheckerIF *);
|
||||
|
||||
std::pair<Command, tlm_generic_payload *> getNextCommand();
|
||||
sc_time start();
|
||||
void updateState(Command, tlm_generic_payload *);
|
||||
void block();
|
||||
|
||||
private:
|
||||
enum class RmState {Regular, Precharged, Pulledin} state = RmState::Regular;
|
||||
const MemSpec *memSpec;
|
||||
std::vector<BankMachine *> bankMachines;
|
||||
std::vector<BankMachine *> &bankMachines;
|
||||
PowerDownManager *powerDownManager;
|
||||
tlm_generic_payload refreshPayload;
|
||||
sc_time timeForNextTrigger = sc_max_time();
|
||||
sc_time timeToSchedule = sc_max_time();
|
||||
|
||||
@@ -37,8 +37,9 @@
|
||||
#include "../../common/utils.h"
|
||||
#include "../../common/dramExtensions.h"
|
||||
|
||||
RefreshManagerBankwise::RefreshManagerBankwise(std::vector<BankMachine *> &bankMachines, Rank rank, CheckerIF *checker)
|
||||
: bankMachines(bankMachines), rank(rank), checker(checker)
|
||||
RefreshManagerBankwise::RefreshManagerBankwise(std::vector<BankMachine *> &bankMachines,
|
||||
PowerDownManager *powerDownManager, Rank rank, CheckerIF *checker)
|
||||
: bankMachines(bankMachines), powerDownManager(powerDownManager), rank(rank), checker(checker)
|
||||
{
|
||||
Configuration &config = Configuration::getInstance();
|
||||
memSpec = config.memSpec;
|
||||
@@ -66,11 +67,6 @@ std::pair<Command, tlm_generic_payload *> RefreshManagerBankwise::getNextCommand
|
||||
return std::pair<Command, tlm_generic_payload *>(Command::NOP, nullptr);
|
||||
}
|
||||
|
||||
void RefreshManagerBankwise::block()
|
||||
{
|
||||
blocked = true;
|
||||
}
|
||||
|
||||
sc_time RefreshManagerBankwise::start()
|
||||
{
|
||||
timeToSchedule = sc_max_time();
|
||||
@@ -213,4 +209,8 @@ void RefreshManagerBankwise::updateState(Command command, tlm_generic_payload *p
|
||||
state = RmState::Precharged;
|
||||
}
|
||||
}
|
||||
else if (command == Command::PDEA || command == Command::PDEP)
|
||||
blocked = true;
|
||||
else if (command == Command::PDXA || command == Command::PDXP)
|
||||
blocked = false;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "RefreshManagerIF.h"
|
||||
#include "../../configuration/memspec/MemSpec.h"
|
||||
#include "../BankMachine.h"
|
||||
#include "../powerdown/PowerDownManager.h"
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <list>
|
||||
@@ -47,17 +48,17 @@ using namespace tlm;
|
||||
class RefreshManagerBankwise final : public RefreshManagerIF
|
||||
{
|
||||
public:
|
||||
RefreshManagerBankwise(std::vector<BankMachine *> &, Rank, CheckerIF *);
|
||||
RefreshManagerBankwise(std::vector<BankMachine *> &, PowerDownManager *, Rank, CheckerIF *);
|
||||
|
||||
std::pair<Command, tlm_generic_payload *> getNextCommand();
|
||||
sc_time start();
|
||||
void updateState(Command, tlm_generic_payload *);
|
||||
void block();
|
||||
|
||||
private:
|
||||
enum class RmState {Regular, Precharged, Pulledin} state = RmState::Regular;
|
||||
const MemSpec *memSpec;
|
||||
std::vector<BankMachine *> bankMachines;
|
||||
std::vector<BankMachine *> &bankMachines;
|
||||
PowerDownManager *powerDownManager;
|
||||
std::vector<tlm_generic_payload> refreshPayloads;
|
||||
sc_time timeForNextTrigger = sc_max_time();
|
||||
sc_time timeToSchedule = sc_max_time();
|
||||
|
||||
@@ -49,7 +49,6 @@ public:
|
||||
std::pair<Command, tlm_generic_payload *> getNextCommand();
|
||||
sc_time start();
|
||||
void updateState(Command, tlm_generic_payload *) {}
|
||||
void block() {}
|
||||
};
|
||||
|
||||
#endif // REFRESHMANAGERDUMMY_H
|
||||
|
||||
@@ -50,7 +50,6 @@ public:
|
||||
virtual std::pair<Command, tlm_generic_payload *> getNextCommand() = 0;
|
||||
virtual sc_time start() = 0;
|
||||
virtual void updateState(Command, tlm_generic_payload *) = 0;
|
||||
virtual void block() = 0;
|
||||
};
|
||||
|
||||
#endif // REFRESHMANAGERIF_H
|
||||
|
||||
Reference in New Issue
Block a user