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),
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
schedule(refreshEvent, ref_tick);
}
+void
+DRAMCtrl::Rank::suspend()
+{
+ deschedule(refreshEvent);
+}
+
void
DRAMCtrl::Rank::checkDrainDone()
{
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)
*/
MemoryPort port;
+ /**
+ * Remeber if the memory system is in timing mode
+ */
+ bool isTimingMode;
+
/**
* Remember if we have to retry a request when available.
*/
*/
void startup(Tick ref_tick);
+ /**
+ * Stop the refresh events.
+ */
+ void suspend();
+
/**
* Check if the current rank is available for scheduling.
*
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: