Files
DRAMSys/dram/src/core/powerdown/PowerDownManager.cpp
2014-04-12 12:05:04 +02:00

175 lines
4.6 KiB
C++

/*
* PowerDownManager.cpp
*
* Created on: Apr 1, 2014
* Author: jonny
*/
#include <algorithm>
#include <string>
#include "PowerDownManager.h"
#include "../ControllerCore.h"
#include "../TimingCalculation.h"
#include "../../common/DebugManager.h"
#include <algorithm>
#include "../../common/Utils.h"
using namespace tlm;
using namespace std;
namespace core {
PowerDownManager::PowerDownManager(ControllerCore& controller) :
controller(controller)
{
powerDownState = PowerDownState::Awake;
for (Bank bank : controller.getBanks())
{
setUpDummy(powerDownPayloads[bank], bank);
}
}
PowerDownManager::~PowerDownManager()
{
}
void PowerDownManager::sleep(Bank bank, sc_time time)
{
if (!canSleep() || isInPowerDown())
return;
PowerDownState state = powerDownState;
if (state == PowerDownState::Awake) //coming from active
{
state = controller.state.bankStates.allRowBuffersAreClosed() ? PowerDownState::PDNPrecharge : PowerDownState::PDNActive;
}
else if (state == PowerDownState::AwakeForRefresh) //coming from refresh interrupting power down
{
sc_assert(controller.state.bankStates.allRowBuffersAreClosed());
if (controller.state.getLastCommand(Command::PDNA).getStart()
>= controller.state.getLastCommand(Command::PDNP).getStart())
state = PowerDownState::PDNPrecharge;
else
{
state = PowerDownState::PDNSelfRefresh;
}
}
ScheduledCommand pdn(IPowerDownManager::getSleepCommand(state), time,
getMinimalExecutionTime(IPowerDownManager::getSleepCommand(state), powerDownPayloads[bank]),
DramExtension::getExtension(powerDownPayloads[bank]));
controller.state.bus.moveCommandToNextFreeSlot(pdn);
if (state != PowerDownState::PDNSelfRefresh && controller.refreshManager->hasCollision(pdn))
{
return;
}
else
{
setState(state);
sendPowerDownPayloads(pdn);
}
}
void PowerDownManager::wakeUp(Bank bank, sc_time time)
{
if (isAwakeForRefresh()) //Request enters system during Refresh
{
setState(PowerDownState::Awake);
}
else if (isInPowerDown()) //Request wakes up power down
{
sc_time startOfExitCommand(SC_ZERO_TIME);
switch (powerDownState)
{
case PowerDownState::PDNActive:
startOfExitCommand = max(time, controller.state.getLastCommand(Command::PDNA).getEnd());
break;
case PowerDownState::PDNPrecharge:
startOfExitCommand = max(time, controller.state.getLastCommand(Command::PDNP).getEnd());
break;
case PowerDownState::PDNSelfRefresh:
startOfExitCommand = max(time, controller.state.getLastCommand(Command::SREF).getEnd());
controller.refreshManager->reInitialize(bank,
startOfExitCommand + getMinimalExecutionTime(Command::SREFX, powerDownPayloads[bank]));
break;
default:
break;
}
Command cmd = IPowerDownManager::getWakeUpCommand(powerDownState);
ScheduledCommand pdn(cmd, startOfExitCommand, getMinimalExecutionTime(cmd, powerDownPayloads[bank]),
DramExtension::getExtension(powerDownPayloads[bank]));
setState(PowerDownState::Awake);
sendPowerDownPayloads(pdn);
}
}
void PowerDownManager::wakeUpForRefresh(Bank bank, sc_time time)
{
if (isInPowerDown())
{
Command cmd = IPowerDownManager::getWakeUpCommand(powerDownState);
ScheduledCommand pdn(cmd, time, getMinimalExecutionTime(cmd, powerDownPayloads[bank]),
DramExtension::getExtension(powerDownPayloads[bank]));
setState(PowerDownState::AwakeForRefresh);
sendPowerDownPayloads(pdn);
}
}
void PowerDownManager::sendPowerDownPayloads(ScheduledCommand& cmd)
{
controller.state.bus.moveCommandToNextFreeSlot(cmd);
for (Bank bank : controller.getBanks())
{
tlm_generic_payload& payloadToSend = powerDownPayloads[bank];
ScheduledCommand pdnToSend(cmd.getCommand(), cmd.getStart(), cmd.getExecutionTime(),
DramExtension::getExtension(payloadToSend));
controller.state.change(pdnToSend);
controller.wrapper.send(pdnToSend, payloadToSend);
}
}
void PowerDownManager::setState(PowerDownState state)
{
powerDownState = state;
DebugManager::getInstance().printDebugMessage(PowerDownManagerBankwise::senderName,
"Is now in state " + powerDownStateToString(powerDownState) + " on all banks");
}
bool PowerDownManager::isInPowerDown()
{
return (powerDownState == PowerDownState::PDNActive || powerDownState == PowerDownState::PDNPrecharge
|| powerDownState == PowerDownState::PDNSelfRefresh);
}
bool PowerDownManager::canSleep()
{
for (Bank bank : controller.getBanks())
{
if (!controller.numberOfPayloads[bank] == 0)
return false;
}
return true;
}
bool PowerDownManager::isInSelfRefresh(Bank bank)
{
return powerDownState == PowerDownState::PDNSelfRefresh;
}
bool PowerDownManager::isAwakeForRefresh()
{
return powerDownState == PowerDownState::AwakeForRefresh;
}
} /* namespace core */