summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mem/dram_ctrl.cc56
-rw-r--r--src/mem/dram_ctrl.hh15
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: