First version of power down working, added some helper functions for enum Command.

This commit is contained in:
Lukas Steiner
2019-11-20 00:30:27 +01:00
parent bddec3022a
commit 6e6d839bd1
17 changed files with 450 additions and 59 deletions

View File

@@ -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)

View File

@@ -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",

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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();

View File

@@ -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!");

View File

@@ -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);

View 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;
}
}

View 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

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -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

View File

@@ -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