43a44
> * Wendy Elsasser
62a64
> busStateNext(READ),
483a486,488
> // increment read entries of the rank
> ++dram_pkt->rankRef.readEntries;
>
546a552,554
>
> // increment write entries of the rank
> ++dram_pkt->rankRef.writeEntries;
658a667,707
> // if a read has reached its ready-time, decrement the number of reads
> // At this point the packet has been handled and there is a possibility
> // to switch to low-power mode if no other packet is available
> --dram_pkt->rankRef.readEntries;
> DPRINTF(DRAM, "number of read entries for rank %d is %d\n",
> dram_pkt->rank, dram_pkt->rankRef.readEntries);
>
> // counter should at least indicate one outstanding request
> // for this read
> assert(dram_pkt->rankRef.outstandingEvents > 0);
> // read response received, decrement count
> --dram_pkt->rankRef.outstandingEvents;
>
> // at this moment should be either ACT or IDLE depending on
> // if PRE has occurred to close all banks
> assert((dram_pkt->rankRef.pwrState == PWR_ACT) ||
> (dram_pkt->rankRef.pwrState == PWR_IDLE));
>
> // track if this is the last packet before idling
> // and that there are no outstanding commands to this rank
> if (dram_pkt->rankRef.lowPowerEntryReady()) {
> // verify that there are no events scheduled
> assert(!dram_pkt->rankRef.activateEvent.scheduled());
> assert(!dram_pkt->rankRef.prechargeEvent.scheduled());
> assert(dram_pkt->rankRef.refreshState == REF_IDLE);
>
> // if coming from active state, schedule power event to
> // active power-down else go to precharge power-down
> DPRINTF(DRAMState, "Rank %d sleep at tick %d; current power state is "
> "%d\n", dram_pkt->rank, curTick(), dram_pkt->rankRef.pwrState);
>
> // default to ACT power-down unless already in IDLE state
> // could be in IDLE if PRE issued before data returned
> PowerState next_pwr_state = PWR_ACT_PDN;
> if (dram_pkt->rankRef.pwrState == PWR_IDLE) {
> next_pwr_state = PWR_PRE_PDN;
> }
>
> dram_pkt->rankRef.powerDownSleep(next_pwr_state, curTick());
> }
>
1015c1064
< if (!rank_ref.prechargeEvent.scheduled())
---
> if (!rank_ref.prechargeEvent.scheduled()) {
1017c1066,1068
< else if (rank_ref.prechargeEvent.when() < pre_done_at)
---
> // New event, increment count
> ++rank_ref.outstandingEvents;
> } else if (rank_ref.prechargeEvent.when() < pre_done_at) {
1018a1070
> }
1029a1082,1089
> // are we in or transitioning to a low-power state and have not scheduled
> // a power-up event?
> // if so, wake up from power down to issue RD/WR burst
> if (rank.inLowPowerState) {
> assert(rank.pwrState != PWR_SREF);
> rank.scheduleWakeUpEvent(tXP);
> }
>
1232,1233c1292,1295
< // rank is busy refreshing
< busyRanks++;
---
> if (r->pwrState != PWR_SREF) {
> // rank is busy refreshing
> DPRINTF(DRAMState, "Rank %d is not available\n", r->rank);
> busyRanks++;
1235,1237c1297,1318
< // let the rank know that if it was waiting to drain, it
< // is now done and ready to proceed
< r->checkDrainDone();
---
> // let the rank know that if it was waiting to drain, it
> // is now done and ready to proceed
> r->checkDrainDone();
> }
>
> // check if we were in self-refresh and haven't started
> // to transition out
> if ((r->pwrState == PWR_SREF) && r->inLowPowerState) {
> DPRINTF(DRAMState, "Rank %d is in self-refresh\n", r->rank);
> // if we have commands queued to this rank and we don't have
> // a minimum number of active commands enqueued,
> // exit self-refresh
> if (r->forceSelfRefreshExit()) {
> DPRINTF(DRAMState, "rank %d was in self refresh and"
> " should wake up\n", r->rank);
> //wake up from self-refresh
> r->scheduleWakeUpEvent(tXS);
> // things are brought back into action once a refresh is
> // performed after self-refresh
> // continue with selection for other ranks
> }
> }
1248,1249c1329,1330
< // pre-emptively set to false. Overwrite if in READ_TO_WRITE
< // or WRITE_TO_READ state
---
> // pre-emptively set to false. Overwrite if in transitioning to
> // a new state
1251,1253c1332,1335
< if (busState == READ_TO_WRITE) {
< DPRINTF(DRAM, "Switching to writes after %d reads with %d reads "
< "waiting\n", readsThisTime, readQueue.size());
---
> if (busState != busStateNext) {
> if (busState == READ) {
> DPRINTF(DRAM, "Switching to writes after %d reads with %d reads "
> "waiting\n", readsThisTime, readQueue.size());
1255,1258c1337,1340
< // sample and reset the read-related stats as we are now
< // transitioning to writes, and all reads are done
< rdPerTurnAround.sample(readsThisTime);
< readsThisTime = 0;
---
> // sample and reset the read-related stats as we are now
> // transitioning to writes, and all reads are done
> rdPerTurnAround.sample(readsThisTime);
> readsThisTime = 0;
1260,1265c1342,1346
< // now proceed to do the actual writes
< busState = WRITE;
< switched_cmd_type = true;
< } else if (busState == WRITE_TO_READ) {
< DPRINTF(DRAM, "Switching to reads after %d writes with %d writes "
< "waiting\n", writesThisTime, writeQueue.size());
---
> // now proceed to do the actual writes
> switched_cmd_type = true;
> } else {
> DPRINTF(DRAM, "Switching to reads after %d writes with %d writes "
> "waiting\n", writesThisTime, writeQueue.size());
1267,1268c1348,1349
< wrPerTurnAround.sample(writesThisTime);
< writesThisTime = 0;
---
> wrPerTurnAround.sample(writesThisTime);
> writesThisTime = 0;
1270,1271c1351,1354
< busState = READ;
< switched_cmd_type = true;
---
> switched_cmd_type = true;
> }
> // update busState to match next state until next transition
> busState = busStateNext;
1325a1409
>
1339a1424,1426
> // Every respQueue which will generate an event, increment count
> ++dram_pkt->rankRef.outstandingEvents;
>
1367c1454
< busState = READ_TO_WRITE;
---
> busStateNext = WRITE;
1400a1488,1507
>
> // removed write from queue, decrement count
> --dram_pkt->rankRef.writeEntries;
>
> // Schedule write done event to decrement event count
> // after the readyTime has been reached
> // Only schedule latest write event to minimize events
> // required; only need to ensure that final event scheduled covers
> // the time that writes are outstanding and bus is active
> // to holdoff power-down entry events
> if (!dram_pkt->rankRef.writeDoneEvent.scheduled()) {
> schedule(dram_pkt->rankRef.writeDoneEvent, dram_pkt->readyTime);
> // New event, increment count
> ++dram_pkt->rankRef.outstandingEvents;
>
> } else if (dram_pkt->rankRef.writeDoneEvent.when() <
> dram_pkt-> readyTime) {
> reschedule(dram_pkt->rankRef.writeDoneEvent, dram_pkt->readyTime);
> }
>
1413c1520
< busState = WRITE_TO_READ;
---
> busStateNext = READ;
1521,1525c1628,1634
< pwrStateTrans(PWR_IDLE), pwrState(PWR_IDLE), pwrStateTick(0),
< refreshState(REF_IDLE), refreshDueAt(0),
< power(_p, false), numBanksActive(0),
< activateEvent(*this), prechargeEvent(*this),
< refreshEvent(*this), powerEvent(*this)
---
> pwrStateTrans(PWR_IDLE), pwrStatePostRefresh(PWR_IDLE),
> pwrStateTick(0), refreshDueAt(0), pwrState(PWR_IDLE),
> refreshState(REF_IDLE), inLowPowerState(false), rank(0),
> readEntries(0), writeEntries(0), outstandingEvents(0),
> wakeUpAllowedAt(0), power(_p, false), numBanksActive(0),
> writeDoneEvent(*this), activateEvent(*this), prechargeEvent(*this),
> refreshEvent(*this), powerEvent(*this), wakeUpEvent(*this)
1546a1656,1658
>
> // don't automatically transition back to LP state after next REF
> pwrStatePostRefresh = PWR_IDLE;
1548a1661,1678
> bool
> DRAMCtrl::Rank::lowPowerEntryReady() const
> {
> bool no_queued_cmds = ((memory.busStateNext == READ) && (readEntries == 0))
> || ((memory.busStateNext == WRITE) &&
> (writeEntries == 0));
>
> if (refreshState == REF_RUN) {
> // have not decremented outstandingEvents for refresh command
> // still check if there are no commands queued to force PD
> // entry after refresh completes
> return no_queued_cmds;
> } else {
> // ensure no commands in Q and no commands scheduled
> return (no_queued_cmds && (outstandingEvents == 0));
> }
> }
>
1557c1687
< refreshState = REF_PRE;
---
> refreshState = REF_PD_EXIT;
1604a1735,1740
> // counter should at least indicate one outstanding request
> // for this precharge
> assert(outstandingEvents > 0);
> // precharge complete, decrement count
> --outstandingEvents;
>
1608,1610c1744,1758
< // we should transition to the idle state when the last bank
< // is precharged
< schedulePowerEvent(PWR_IDLE, curTick());
---
> // no reads to this rank in the Q and no pending
> // RD/WR or refresh commands
> if (lowPowerEntryReady()) {
> // should still be in ACT state since bank still open
> assert(pwrState == PWR_ACT);
>
> // All banks closed - switch to precharge power down state.
> DPRINTF(DRAMState, "Rank %d sleep at tick %d\n",
> rank, curTick());
> powerDownSleep(PWR_PRE_PDN, curTick());
> } else {
> // we should transition to the idle state when the last bank
> // is precharged
> schedulePowerEvent(PWR_IDLE, curTick());
> }
1614a1763,1773
> DRAMCtrl::Rank::processWriteDoneEvent()
> {
> // counter should at least indicate one outstanding request
> // for this write
> assert(outstandingEvents > 0);
> // Write transfer on bus has completed
> // decrement per rank counter
> --outstandingEvents;
> }
>
> void
1618c1777
< if (refreshState == REF_IDLE) {
---
> if ((refreshState == REF_IDLE) || (refreshState == REF_SREF_EXIT)) {
1624a1784,1787
> // make nonzero while refresh is pending to ensure
> // power down and self-refresh are not entered
> ++outstandingEvents;
>
1641a1805,1818
> refreshState = REF_PD_EXIT;
> }
> }
>
> // at this point, ensure that rank is not in a power-down state
> if (refreshState == REF_PD_EXIT) {
> // if rank was sleeping and we have't started exit process,
> // wake-up for refresh
> if (inLowPowerState) {
> DPRINTF(DRAM, "Wake Up for refresh\n");
> // save state and return after refresh completes
> scheduleWakeUpEvent(memory.tXP);
> return;
> } else {
1648,1650c1825,1826
< // precharge any active bank if we are not already in the idle
< // state
< if (pwrState != PWR_IDLE) {
---
> // precharge any active bank
> if (numBanksActive != 0) {
1684c1860,1862
< } else {
---
> } else if ((pwrState == PWR_IDLE) && (outstandingEvents == 1)) {
> // Banks are closed, have transitioned to IDLE state, and
> // no outstanding ACT,RD/WR,Auto-PRE sequence scheduled
1687c1865
< // go ahead and kick the power state machine into gear if
---
> // go ahead and kick the power state machine into gear since
1689a1868,1873
> } else {
> // banks state is closed but haven't transitioned pwrState to IDLE
> // or have outstanding ACT,RD/WR,Auto-PRE sequence scheduled
> // should have outstanding precharge event in this case
> assert(prechargeEvent.scheduled());
> // will start refresh when pwrState transitions to IDLE
1692d1875
< refreshState = REF_RUN;
1703c1886
< if (refreshState == REF_RUN) {
---
> if (refreshState == REF_START) {
1722a1906,1908
> // Update for next refresh
> refreshDueAt += memory.tREFI;
>
1725c1911
< if (refreshDueAt + memory.tREFI < ref_done_at) {
---
> if (refreshDueAt < ref_done_at) {
1729,1731c1915,1920
< // compensate for the delay in actually performing the refresh
< // when scheduling the next one
< schedule(refreshEvent, refreshDueAt + memory.tREFI - memory.tRP);
---
> // Run the refresh and schedule event to transition power states
> // when refresh completes
> refreshState = REF_RUN;
> schedule(refreshEvent, ref_done_at);
> return;
> }
1732a1922,1926
> if (refreshState == REF_RUN) {
> // should never get here with any banks active
> assert(numBanksActive == 0);
> assert(pwrState == PWR_REF);
>
1735,1738c1929,1943
< // move to the idle power state once the refresh is done, this
< // will also move the refresh state machine to the refresh
< // idle state
< schedulePowerEvent(PWR_IDLE, ref_done_at);
---
> if ((memory.drainState() == DrainState::Draining) ||
> (memory.drainState() == DrainState::Drained)) {
> // if draining, do not re-enter low-power mode.
> // simply go to IDLE and wait
> schedulePowerEvent(PWR_IDLE, curTick());
> } else {
> // At the moment, we sleep when the refresh ends and wait to be
> // woken up again if previously in a low-power state.
> if (pwrStatePostRefresh != PWR_IDLE) {
> // power State should be power Refresh
> assert(pwrState == PWR_REF);
> DPRINTF(DRAMState, "Rank %d sleeping after refresh and was in "
> "power state %d before refreshing\n", rank,
> pwrStatePostRefresh);
> powerDownSleep(pwrState, curTick());
1740,1741c1945,1969
< DPRINTF(DRAMState, "Refresh done at %llu and next refresh at %llu\n",
< ref_done_at, refreshDueAt + memory.tREFI);
---
> // Force PRE power-down if there are no outstanding commands
> // in Q after refresh.
> } else if (lowPowerEntryReady()) {
> DPRINTF(DRAMState, "Rank %d sleeping after refresh but was NOT"
> " in a low power state before refreshing\n", rank);
> powerDownSleep(PWR_PRE_PDN, curTick());
>
> } else {
> // move to the idle power state once the refresh is done, this
> // will also move the refresh state machine to the refresh
> // idle state
> schedulePowerEvent(PWR_IDLE, curTick());
> }
> }
>
> // if transitioning to self refresh do not schedule a new refresh;
> // when waking from self refresh, a refresh is scheduled again.
> if (pwrStateTrans != PWR_SREF) {
> // compensate for the delay in actually performing the refresh
> // when scheduling the next one
> schedule(refreshEvent, refreshDueAt - memory.tRP);
>
> DPRINTF(DRAMState, "Refresh done at %llu and next refresh"
> " at %llu\n", curTick(), refreshDueAt);
> }
1766a1995,2117
> DRAMCtrl::Rank::powerDownSleep(PowerState pwr_state, Tick tick)
> {
> // if low power state is active low, schedule to active low power state.
> // in reality tCKE is needed to enter active low power. This is neglected
> // here and could be added in the future.
> if (pwr_state == PWR_ACT_PDN) {
> schedulePowerEvent(pwr_state, tick);
> // push command to DRAMPower
> cmdList.push_back(Command(MemCommand::PDN_F_ACT, 0, tick));
> DPRINTF(DRAMPower, "%llu,PDN_F_ACT,0,%d\n", divCeil(tick,
> memory.tCK) - memory.timeStampOffset, rank);
> } else if (pwr_state == PWR_PRE_PDN) {
> // if low power state is precharge low, schedule to precharge low
> // power state. In reality tCKE is needed to enter active low power.
> // This is neglected here.
> schedulePowerEvent(pwr_state, tick);
> //push Command to DRAMPower
> cmdList.push_back(Command(MemCommand::PDN_F_PRE, 0, tick));
> DPRINTF(DRAMPower, "%llu,PDN_F_PRE,0,%d\n", divCeil(tick,
> memory.tCK) - memory.timeStampOffset, rank);
> } else if (pwr_state == PWR_REF) {
> // if a refresh just occured
> // transition to PRE_PDN now that all banks are closed
> // do not transition to SREF if commands are in Q; stay in PRE_PDN
> if (pwrStatePostRefresh == PWR_ACT_PDN || !lowPowerEntryReady()) {
> // prechage power down requires tCKE to enter. For simplicity
> // this is not considered.
> schedulePowerEvent(PWR_PRE_PDN, tick);
> //push Command to DRAMPower
> cmdList.push_back(Command(MemCommand::PDN_F_PRE, 0, tick));
> DPRINTF(DRAMPower, "%llu,PDN_F_PRE,0,%d\n", divCeil(tick,
> memory.tCK) - memory.timeStampOffset, rank);
> } else {
> // last low power State was power precharge
> assert(pwrStatePostRefresh == PWR_PRE_PDN);
> // self refresh requires time tCKESR to enter. For simplicity,
> // this is not considered.
> schedulePowerEvent(PWR_SREF, tick);
> // push Command to DRAMPower
> cmdList.push_back(Command(MemCommand::SREN, 0, tick));
> DPRINTF(DRAMPower, "%llu,SREN,0,%d\n", divCeil(tick,
> memory.tCK) - memory.timeStampOffset, rank);
> }
> }
> // Ensure that we don't power-down and back up in same tick
> // Once we commit to PD entry, do it and wait for at least 1tCK
> // This could be replaced with tCKE if/when that is added to the model
> wakeUpAllowedAt = tick + memory.tCK;
>
> // Transitioning to a low power state, set flag
> inLowPowerState = true;
> }
>
> void
> DRAMCtrl::Rank::scheduleWakeUpEvent(Tick exit_delay)
> {
> Tick wake_up_tick = std::max(curTick(), wakeUpAllowedAt);
>
> DPRINTF(DRAMState, "Scheduling wake-up for rank %d at tick %d\n",
> rank, wake_up_tick);
>
> // if waking for refresh, hold previous state
> // else reset state back to IDLE
> if (refreshState == REF_PD_EXIT) {
> pwrStatePostRefresh = pwrState;
> } else {
> // don't automatically transition back to LP state after next REF
> pwrStatePostRefresh = PWR_IDLE;
> }
>
> // schedule wake-up with event to ensure entry has completed before
> // we try to wake-up
> schedule(wakeUpEvent, wake_up_tick);
>
> for (auto &b : banks) {
> // respect both causality and any existing bank
> // constraints, some banks could already have a
> // (auto) precharge scheduled
> b.colAllowedAt = std::max(wake_up_tick + exit_delay, b.colAllowedAt);
> b.preAllowedAt = std::max(wake_up_tick + exit_delay, b.preAllowedAt);
> b.actAllowedAt = std::max(wake_up_tick + exit_delay, b.actAllowedAt);
> }
> // Transitioning out of low power state, clear flag
> inLowPowerState = false;
>
> // push to DRAMPower
> // use pwrStateTrans for cases where we have a power event scheduled
> // to enter low power that has not yet been processed
> if (pwrStateTrans == PWR_ACT_PDN) {
> cmdList.push_back(Command(MemCommand::PUP_ACT, 0, wake_up_tick));
> DPRINTF(DRAMPower, "%llu,PUP_ACT,0,%d\n", divCeil(wake_up_tick,
> memory.tCK) - memory.timeStampOffset, rank);
>
> } else if (pwrStateTrans == PWR_PRE_PDN) {
> cmdList.push_back(Command(MemCommand::PUP_PRE, 0, wake_up_tick));
> DPRINTF(DRAMPower, "%llu,PUP_PRE,0,%d\n", divCeil(wake_up_tick,
> memory.tCK) - memory.timeStampOffset, rank);
> } else if (pwrStateTrans == PWR_SREF) {
> cmdList.push_back(Command(MemCommand::SREX, 0, wake_up_tick));
> DPRINTF(DRAMPower, "%llu,SREX,0,%d\n", divCeil(wake_up_tick,
> memory.tCK) - memory.timeStampOffset, rank);
> }
> }
>
> void
> DRAMCtrl::Rank::processWakeUpEvent()
> {
> // Should be in a power-down or self-refresh state
> assert((pwrState == PWR_ACT_PDN) || (pwrState == PWR_PRE_PDN) ||
> (pwrState == PWR_SREF));
>
> // Check current state to determine transition state
> if (pwrState == PWR_ACT_PDN) {
> // banks still open, transition to PWR_ACT
> schedulePowerEvent(PWR_ACT, curTick());
> } else {
> // transitioning from a precharge power-down or self-refresh state
> // banks are closed - transition to PWR_IDLE
> schedulePowerEvent(PWR_IDLE, curTick());
> }
> }
>
> void
1768a2120
> assert(curTick() >= pwrStateTick);
1775a2128,2133
> // track to total idle time
> if ((prev_state == PWR_PRE_PDN) || (prev_state == PWR_ACT_PDN) ||
> (prev_state == PWR_SREF)) {
> totalIdleTime += duration;
> }
>
1779,1780c2137,2143
< if (pwrState == PWR_IDLE) {
< DPRINTF(DRAMState, "All banks precharged\n");
---
> // if rank was refreshing, make sure to start scheduling requests again
> if (prev_state == PWR_REF) {
> // bus IDLED prior to REF
> // counter should be one for refresh command only
> assert(outstandingEvents == 1);
> // REF complete, decrement count
> --outstandingEvents;
1782,1787c2145,2154
< // if we were refreshing, make sure we start scheduling requests again
< if (prev_state == PWR_REF) {
< DPRINTF(DRAMState, "Was refreshing for %llu ticks\n", duration);
< assert(pwrState == PWR_IDLE);
<
< // kick things into action again
---
> DPRINTF(DRAMState, "Was refreshing for %llu ticks\n", duration);
> // if sleeping after refresh
> if (pwrState != PWR_IDLE) {
> assert((pwrState == PWR_PRE_PDN) || (pwrState == PWR_SREF));
> DPRINTF(DRAMState, "Switching to power down state after refreshing"
> " rank %d at %llu tick\n", rank, curTick());
> }
> if (pwrState != PWR_SREF) {
> // rank is not available in SREF
> // don't transition to IDLE in this case
1789,1794c2156,2167
< // a request event could be already scheduled by the state
< // machine of the other rank
< if (!memory.nextReqEvent.scheduled())
< schedule(memory.nextReqEvent, curTick());
< } else {
< assert(prev_state == PWR_ACT);
---
> }
> // a request event could be already scheduled by the state
> // machine of the other rank
> if (!memory.nextReqEvent.scheduled()) {
> DPRINTF(DRAM, "Scheduling next request after refreshing rank %d\n",
> rank);
> schedule(memory.nextReqEvent, curTick());
> }
> } else if (pwrState == PWR_ACT) {
> if (refreshState == REF_PD_EXIT) {
> // kick the refresh event loop into action again
> assert(prev_state == PWR_ACT_PDN);
1795a2169,2182
> // go back to REF event and close banks
> refreshState = REF_PRE;
> schedule(refreshEvent, curTick());
> }
> } else if (pwrState == PWR_IDLE) {
> DPRINTF(DRAMState, "All banks precharged\n");
> if (prev_state == PWR_SREF) {
> // set refresh state to REF_SREF_EXIT, ensuring isAvailable
> // continues to return false during tXS after SREF exit
> // Schedule a refresh which kicks things back into action
> // when it finishes
> refreshState = REF_SREF_EXIT;
> schedule(refreshEvent, curTick() + memory.tXS);
> } else {
1797,1803c2184,2199
< // the idle state, direclty transition to a refresh
< if (refreshState == REF_RUN) {
< // there should be nothing waiting at this point
< assert(!powerEvent.scheduled());
<
< // update the state in zero time and proceed below
< pwrState = PWR_REF;
---
> // the idle state, directly transition to a refresh
> if ((refreshState == REF_PRE) || (refreshState == REF_PD_EXIT)) {
> // ensure refresh is restarted only after final PRE command.
> // do not restart refresh if controller is in an intermediate
> // state, after PRE_PDN exit, when banks are IDLE but an
> // ACT is scheduled.
> if (!activateEvent.scheduled()) {
> // there should be nothing waiting at this point
> assert(!powerEvent.scheduled());
> // update the state in zero time and proceed below
> pwrState = PWR_REF;
> } else {
> // must have PRE scheduled to transition back to IDLE
> // and re-kick off refresh
> assert(prechargeEvent.scheduled());
> }
1805c2201
< }
---
> }
1812a2209
> assert(refreshState == REF_PRE || refreshState == REF_PD_EXIT);
1813a2211
>
1817,1818c2215,2222
< assert(refreshState == REF_RUN);
< processRefreshEvent();
---
> if (refreshState == REF_PD_EXIT) {
> // Wait for PD exit timing to complete before issuing REF
> schedule(refreshEvent, curTick() + memory.tXP);
> } else {
> schedule(refreshEvent, curTick());
> }
> // Banks transitioned to IDLE, start REF
> refreshState = REF_START;
1854a2259,2261
> actPowerDownEnergy = energy.f_act_pd_energy * memory.devicesPerRank;
> prePowerDownEnergy = energy.f_pre_pd_energy * memory.devicesPerRank;
> selfRefreshEnergy = energy.sref_energy * memory.devicesPerRank;
1883c2290
< .init(5)
---
> .init(6)
1888,1890c2295,2298
< pwrStateTime.subname(2, "PRE_PDN");
< pwrStateTime.subname(3, "ACT");
< pwrStateTime.subname(4, "ACT_PDN");
---
> pwrStateTime.subname(2, "SREF");
> pwrStateTime.subname(3, "PRE_PDN");
> pwrStateTime.subname(4, "ACT");
> pwrStateTime.subname(5, "ACT_PDN");
1919a2328,2339
> actPowerDownEnergy
> .name(name() + ".actPowerDownEnergy")
> .desc("Energy for active power-down per rank (pJ)");
>
> prePowerDownEnergy
> .name(name() + ".prePowerDownEnergy")
> .desc("Energy for precharge power-down per rank (pJ)");
>
> selfRefreshEnergy
> .name(name() + ".selfRefreshEnergy")
> .desc("Energy for self refresh per rank (pJ)");
>
1927a2348,2351
> totalIdleTime
> .name(name() + ".totalIdleTime")
> .desc("Total Idle time Per DRAM Rank");
>
2218c2642
< // the only part that is not drained automatically over time
---
> // the only queue that is not drained automatically over time
2222a2647,2657
>
> // also need to kick off events to exit self-refresh
> for (auto r : ranks) {
> // force self-refresh exit, which in turn will issue auto-refresh
> if (r->pwrState == PWR_SREF) {
> DPRINTF(DRAM,"Rank%d: Forcing self-refresh wakeup in drain\n",
> r->rank);
> r->scheduleWakeUpEvent(tXS);
> }
> }
>