/* * PowerDownManager.cpp * * Created on: Apr 1, 2014 * Author: jonny */ #include #include #include "PowerDownManagerGrouped.h" #include "../ControllerCore.h" #include "../utils/Utils.h" #include "../../common/DebugManager.h" #include 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 */