diff options
-rw-r--r-- | src/mem/dram_ctrl.cc | 56 | ||||
-rw-r--r-- | src/mem/dram_ctrl.hh | 15 |
2 files changed, 56 insertions, 15 deletions
diff --git a/src/mem/dram_ctrl.cc b/src/mem/dram_ctrl.cc index eec4706a6..42abc63a8 100644 --- a/src/mem/dram_ctrl.cc +++ b/src/mem/dram_ctrl.cc @@ -57,7 +57,7 @@ using namespace Data; DRAMCtrl::DRAMCtrl(const DRAMCtrlParams* p) : AbstractMemory(p), - port(name() + ".port", *this), + port(name() + ".port", *this), isTimingMode(false), retryRdReq(false), retryWrReq(false), busState(READ), nextReqEvent(this), respondEvent(this), @@ -239,20 +239,25 @@ DRAMCtrl::init() void DRAMCtrl::startup() { - // timestamp offset should be in clock cycles for DRAMPower - timeStampOffset = divCeil(curTick(), tCK); + // remember the memory system mode of operation + isTimingMode = system()->isTimingMode(); - // update the start tick for the precharge accounting to the - // current tick - for (auto r : ranks) { - r->startup(curTick() + tREFI - tRP); - } + if (isTimingMode) { + // timestamp offset should be in clock cycles for DRAMPower + timeStampOffset = divCeil(curTick(), tCK); + + // update the start tick for the precharge accounting to the + // current tick + for (auto r : ranks) { + r->startup(curTick() + tREFI - tRP); + } - // shift the bus busy time sufficiently far ahead that we never - // have to worry about negative values when computing the time for - // the next request, this will add an insignificant bubble at the - // start of simulation - busBusyUntil = curTick() + tRP + tRCD + tCL; + // shift the bus busy time sufficiently far ahead that we never + // have to worry about negative values when computing the time for + // the next request, this will add an insignificant bubble at the + // start of simulation + busBusyUntil = curTick() + tRP + tRCD + tCL; + } } Tick @@ -1555,6 +1560,12 @@ DRAMCtrl::Rank::startup(Tick ref_tick) } void +DRAMCtrl::Rank::suspend() +{ + deschedule(refreshEvent); +} + +void DRAMCtrl::Rank::checkDrainDone() { // if this rank was waiting to drain it is now able to proceed to @@ -2197,6 +2208,25 @@ DRAMCtrl::drain(DrainManager *dm) return count; } +void +DRAMCtrl::drainResume() +{ + if (!isTimingMode && system()->isTimingMode()) { + // if we switched to timing mode, kick things into action, + // and behave as if we restored from a checkpoint + startup(); + } else if (isTimingMode && !system()->isTimingMode()) { + // if we switch from timing mode, stop the refresh events to + // not cause issues with KVM + for (auto r : ranks) { + r->suspend(); + } + } + + // update the mode + isTimingMode = system()->isTimingMode(); +} + DRAMCtrl::MemoryPort::MemoryPort(const std::string& name, DRAMCtrl& _memory) : QueuedSlavePort(name, &_memory, queue), queue(_memory, *this), memory(_memory) diff --git a/src/mem/dram_ctrl.hh b/src/mem/dram_ctrl.hh index ade717695..3aa06feac 100644 --- a/src/mem/dram_ctrl.hh +++ b/src/mem/dram_ctrl.hh @@ -121,6 +121,11 @@ class DRAMCtrl : public AbstractMemory MemoryPort port; /** + * Remeber if the memory system is in timing mode + */ + bool isTimingMode; + + /** * Remember if we have to retry a request when available. */ bool retryRdReq; @@ -340,6 +345,11 @@ class DRAMCtrl : public AbstractMemory void startup(Tick ref_tick); /** + * Stop the refresh events. + */ + void suspend(); + + /** * Check if the current rank is available for scheduling. * * @param Return true if the rank is idle from a refresh point of view @@ -855,8 +865,9 @@ class DRAMCtrl : public AbstractMemory virtual BaseSlavePort& getSlavePort(const std::string& if_name, PortID idx = InvalidPortID); - virtual void init(); - virtual void startup(); + virtual void init() M5_ATTR_OVERRIDE; + virtual void startup() M5_ATTR_OVERRIDE; + virtual void drainResume() M5_ATTR_OVERRIDE; protected: |