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

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 */