167 lines
4.2 KiB
C++
167 lines
4.2 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;
|
|
}
|
|
}
|
|
|
|
Command cmd = IPowerDownManager::getSleepCommand(state);
|
|
ScheduledCommand pdn(cmd, time, getMinimalExecutionTime(cmd, powerDownPayloads[bank]),
|
|
DramExtension::getExtension(powerDownPayloads[bank]));
|
|
|
|
controller.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
|
|
|
|
if (state != PowerDownState::PDNSelfRefresh && controller.refreshManager->hasCollision(pdn))
|
|
{
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
setPowerDownState(state);
|
|
sendPowerDownPayloads(pdn);
|
|
}
|
|
}
|
|
|
|
void PowerDownManager::wakeUp(Bank bank, sc_time time)
|
|
{
|
|
if (isAwakeForRefresh()) //Request enters system during Refresh
|
|
{
|
|
setPowerDownState(PowerDownState::Awake);
|
|
}
|
|
else if (isInPowerDown()) //Request wakes up power down
|
|
{
|
|
Command cmd = IPowerDownManager::getWakeUpCommand(powerDownState);
|
|
ScheduledCommand pdn(cmd, time, getExecutionTime(cmd, powerDownPayloads[bank]),
|
|
DramExtension::getExtension(powerDownPayloads[bank]));
|
|
controller.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
|
|
|
|
if (cmd == Command::SREFX)
|
|
controller.refreshManager->reInitialize(bank, pdn.getEnd());
|
|
|
|
setPowerDownState(PowerDownState::Awake);
|
|
sendPowerDownPayloads(pdn);
|
|
}
|
|
}
|
|
|
|
void PowerDownManager::wakeUpForRefresh(Bank bank, sc_time time)
|
|
{
|
|
if (isInPowerDown())
|
|
{
|
|
Command cmd = IPowerDownManager::getWakeUpCommand(powerDownState);
|
|
ScheduledCommand pdn(cmd, time, getExecutionTime(cmd, powerDownPayloads[bank]),
|
|
DramExtension::getExtension(powerDownPayloads[bank]));
|
|
|
|
setPowerDownState(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::setPowerDownState(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;
|
|
}
|
|
|
|
void PowerDownManager::triggerSleep(Bank bank, sc_time time)
|
|
{
|
|
sleep(bank, time);
|
|
}
|
|
|
|
} /* namespace core */
|
|
|
|
|