175 lines
4.6 KiB
C++
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 */
|
|
|