171 lines
4.1 KiB
C++
171 lines
4.1 KiB
C++
/*
|
|
* PowerDownManager.cpp
|
|
*
|
|
* Created on: Apr 1, 2014
|
|
* Author: jonny
|
|
*/
|
|
|
|
#include <algorithm>
|
|
#include <string>
|
|
#include "PowerDownManagerGrouped.h"
|
|
#include "../ControllerCore.h"
|
|
#include "../utils/Utils.h"
|
|
#include "../../common/DebugManager.h"
|
|
#include <algorithm>
|
|
|
|
using namespace tlm;
|
|
using namespace std;
|
|
|
|
namespace core {
|
|
|
|
PowerDownManagerGrouped::~PowerDownManagerGrouped()
|
|
{
|
|
|
|
}
|
|
|
|
void PowerDownManagerGrouped::sleep(Bank bank, sc_time time)
|
|
{
|
|
assert(!isInPowerDown());//cause nobody calls sleep if already sleeping on all banks
|
|
|
|
//all banks can sleep and no pending refresh
|
|
if (!canSleep() || (controller.state.getLastCommand(Command::AutoRefresh).getEnd() > time))
|
|
return;
|
|
|
|
PowerDownState state = getPowerDownState();
|
|
if (state == PowerDownState::Awake)//coming from active
|
|
{
|
|
if (controller.state.bankStates.allRowBuffersAreClosed())
|
|
setState(PowerDownState::PDNPrecharge);
|
|
else
|
|
setState(PowerDownState::PDNActive);
|
|
|
|
sendPowerDownPayload(time, getSleepCommand(getPowerDownState()));
|
|
}
|
|
else if (state == PowerDownState::AwakeForRefresh)//coming from refresh interrupting power down
|
|
{
|
|
//last running refresh triggers sleep
|
|
if (controller.state.getLastCommand(Command::PDNA).getStart()
|
|
> controller.state.getLastCommand(Command::PDNP).getStart())
|
|
setState(PowerDownState::PDNPrecharge);
|
|
else
|
|
setState(PowerDownState::PDNSelfRefresh);
|
|
|
|
sendPowerDownPayload(time, getSleepCommand(getPowerDownState()));
|
|
}
|
|
else
|
|
{
|
|
SC_REPORT_FATAL("PowerDownManagerGrouped", "Sleep triggered even though already in sleep");
|
|
}
|
|
}
|
|
|
|
void PowerDownManagerGrouped::wakeUp(Bank bank, sc_time time)
|
|
{
|
|
if (isAwakeForRefresh())//Request enters system during Refresh
|
|
{
|
|
//power down already waked up and payload sent
|
|
setState(PowerDownState::Awake);
|
|
}
|
|
else if(isInPowerDown())//Request wakes up power down
|
|
{
|
|
sc_time delay(SC_ZERO_TIME);
|
|
switch (getPowerDownState())
|
|
{
|
|
case PowerDownState::PDNActive:
|
|
break;
|
|
case PowerDownState::PDNPrecharge:
|
|
break;
|
|
case PowerDownState::PDNSelfRefresh:
|
|
delay = getDelayToMeetConstraint(
|
|
controller.state.getLastCommand(Command::SREF).getStart(), time,
|
|
controller.config.Timings.tCKESR);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (delay == SC_ZERO_TIME)
|
|
{
|
|
sendPowerDownPayload(time, getWakeUpCommand(getPowerDownState()));
|
|
setState(PowerDownState::Awake);
|
|
}
|
|
else
|
|
{
|
|
tlm_generic_payload& p = getPayload(bank);
|
|
controller.wrapper.send(WakeUpTrigger, time + delay, p);
|
|
}
|
|
}
|
|
}
|
|
|
|
void PowerDownManagerGrouped::wakeUpForRefresh(Bank bank, sc_time time)
|
|
{
|
|
wakeUpAllForRefresh(time);
|
|
}
|
|
|
|
void PowerDownManagerGrouped::wakeUpAllForRefresh(sc_time time)
|
|
{
|
|
if(isInPowerDown())
|
|
{
|
|
for (Bank bank : controller.getBanks())
|
|
{
|
|
sendPowerDownPayload(time, getWakeUpCommand(getPowerDownState()));
|
|
}
|
|
setState(PowerDownState::AwakeForRefresh);
|
|
}
|
|
|
|
}
|
|
|
|
void PowerDownManagerGrouped::sendPowerDownPayload(sc_time time, Command cmd)
|
|
{
|
|
time = clkAlign(time, controller.config.Timings.clk);
|
|
|
|
//just to find slot
|
|
tlm_generic_payload& payload = getPayload(Bank(0));
|
|
ScheduledCommand pdn(cmd, time, SC_ZERO_TIME, DramExtension::getExtension(payload));
|
|
controller.state.bus.moveCommandToNextFreeSlot(pdn);
|
|
|
|
|
|
for (Bank bank : controller.getBanks())
|
|
{
|
|
tlm_generic_payload& payloadToSend = getPayload(bank);
|
|
ScheduledCommand pdnToSend(cmd, pdn.getStart(), SC_ZERO_TIME, DramExtension::getExtension(payloadToSend));
|
|
controller.state.change(pdnToSend);
|
|
controller.wrapper.send(pdnToSend, payloadToSend);
|
|
}
|
|
}
|
|
|
|
void PowerDownManagerGrouped::setState(PowerDownState state)
|
|
{
|
|
for (Bank bank : controller.getBanks())
|
|
{
|
|
PowerDownManager::setState(state, bank);
|
|
}
|
|
}
|
|
|
|
bool PowerDownManagerGrouped::isInPowerDown()
|
|
{
|
|
return PowerDownManager::isInPowerDown(Bank(0));
|
|
}
|
|
|
|
bool PowerDownManagerGrouped::canSleep()
|
|
{
|
|
for (Bank bank : controller.getBanks())
|
|
{
|
|
if (!PowerDownManager::canSleep(bank))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
PowerDownState PowerDownManagerGrouped::getPowerDownState()
|
|
{
|
|
return PowerDownManager::getPowerDownState(Bank(0));
|
|
}
|
|
|
|
bool PowerDownManagerGrouped::isAwakeForRefresh()
|
|
{
|
|
return PowerDownManager::isAwakeForRefresh(Bank(0));
|
|
}
|
|
|
|
} /* namespace core */
|
|
|