From 283be34a992401f07d62e274d501c4185fca8377 Mon Sep 17 00:00:00 2001 From: Brad Beckmann Date: Fri, 20 Aug 2010 11:46:13 -0700 Subject: devices: Fixed periodic interrupts to work with draining Added drain functions to the RTC and 8254 timer so that periodic interrupts stop when the system is draining. This patch is needed to checkpoint in timing mode. Otherwise under certain situations, the event queue will never be completely empty. --- src/dev/alpha/tsunami_io.cc | 11 +++++++++++ src/dev/alpha/tsunami_io.hh | 6 ++++++ src/dev/intel_8254_timer.cc | 29 ++++++++++++++++++++++++----- src/dev/intel_8254_timer.hh | 12 ++++++++++++ src/dev/mc146818.cc | 25 +++++++++++++++++++++---- src/dev/mc146818.hh | 6 ++++++ 6 files changed, 80 insertions(+), 9 deletions(-) diff --git a/src/dev/alpha/tsunami_io.cc b/src/dev/alpha/tsunami_io.cc index c90f06b5a..1a76c2c32 100644 --- a/src/dev/alpha/tsunami_io.cc +++ b/src/dev/alpha/tsunami_io.cc @@ -249,6 +249,17 @@ TsunamiIO::clearPIC(uint8_t bitvector) } } +unsigned int +TsunamiIO::drain(Event *de) +{ + unsigned int count = 0; + count += pitimer.drain(de); + count += rtc.drain(de); + assert(count == 0); + changeState(SimObject::Drained); + return count; +} + void TsunamiIO::serialize(ostream &os) { diff --git a/src/dev/alpha/tsunami_io.hh b/src/dev/alpha/tsunami_io.hh index b6d63322b..f649247e2 100644 --- a/src/dev/alpha/tsunami_io.hh +++ b/src/dev/alpha/tsunami_io.hh @@ -140,6 +140,12 @@ class TsunamiIO : public BasicPioDevice */ void clearPIC(uint8_t bitvector); + /** + * Drain the io state including all associated events. + * @param drainEvent + */ + unsigned int drain(Event *de); + /** * Serialize this object to the given output stream. * @param os The stream to serialize to. diff --git a/src/dev/intel_8254_timer.cc b/src/dev/intel_8254_timer.cc index 9e507b968..b61aa7c56 100644 --- a/src/dev/intel_8254_timer.cc +++ b/src/dev/intel_8254_timer.cc @@ -32,6 +32,7 @@ #include "base/misc.hh" #include "dev/intel_8254_timer.hh" +#include "sim/sim_object.hh" using namespace std; @@ -69,6 +70,17 @@ Intel8254Timer::writeControl(const CtrlReg data) } } +unsigned int +Intel8254Timer::drain(Event *de) +{ + unsigned int count = 0; + count += counter[0]->drain(de); + count += counter[1]->drain(de); + count += counter[2]->drain(de); + assert(count == 0); + return count; +} + void Intel8254Timer::serialize(const string &base, ostream &os) { @@ -216,6 +228,18 @@ Intel8254Timer::Counter::outputHigh() return output_high; } +unsigned int +Intel8254Timer::Counter::drain(Event *de) +{ + if (event.scheduled()) { + event_tick = event.when(); + parent->deschedule(event); + } else { + event_tick = 0; + } + return 0; +} + void Intel8254Timer::Counter::serialize(const string &base, ostream &os) { @@ -227,10 +251,6 @@ Intel8254Timer::Counter::serialize(const string &base, ostream &os) paramOut(os, base + ".latch_on", latch_on); paramOut(os, base + ".read_byte", read_byte); paramOut(os, base + ".write_byte", write_byte); - - Tick event_tick = 0; - if (event.scheduled()) - event_tick = event.when(); paramOut(os, base + ".event_tick", event_tick); } @@ -247,7 +267,6 @@ Intel8254Timer::Counter::unserialize(const string &base, Checkpoint *cp, paramIn(cp, section, base + ".read_byte", read_byte); paramIn(cp, section, base + ".write_byte", write_byte); - Tick event_tick; paramIn(cp, section, base + ".event_tick", event_tick); if (event_tick) parent->schedule(event, event_tick); diff --git a/src/dev/intel_8254_timer.hh b/src/dev/intel_8254_timer.hh index 30ddc7bca..26ea0687e 100644 --- a/src/dev/intel_8254_timer.hh +++ b/src/dev/intel_8254_timer.hh @@ -137,6 +137,10 @@ class Intel8254Timer : public EventManager /** Pointer to container */ Intel8254Timer *parent; + /** if non-zero, the scheduled tick of an event used for drain + serialization coordination */ + Tick event_tick; + public: Counter(Intel8254Timer *p, const std::string &name, unsigned int num); @@ -164,6 +168,12 @@ class Intel8254Timer : public EventManager /** Is the output high? */ bool outputHigh(); + /** + * Drain all associated events. + * @param drainEvent + */ + unsigned int drain(Event *de); + /** * Serialize this object to the given output stream. * @param base The base name of the counter object. @@ -229,6 +239,8 @@ class Intel8254Timer : public EventManager return counter[num]->outputHigh(); } + unsigned int drain(Event *de); + /** * Serialize this object to the given output stream. * @param base The base name of the counter object. diff --git a/src/dev/mc146818.cc b/src/dev/mc146818.cc index 16ed58e46..fd70b503b 100644 --- a/src/dev/mc146818.cc +++ b/src/dev/mc146818.cc @@ -40,6 +40,7 @@ #include "base/trace.hh" #include "dev/mc146818.hh" #include "dev/rtcreg.h" +#include "sim/sim_object.hh" using namespace std; @@ -105,8 +106,12 @@ MC146818::MC146818(EventManager *em, const string &n, const struct tm time, MC146818::~MC146818() { - deschedule(tickEvent); - deschedule(event); + if (tickEvent.scheduled()) { + deschedule(tickEvent); + } + if (event.scheduled()) { + deschedule(event); + } } void @@ -203,6 +208,20 @@ MC146818::tickClock() setTime(*gmtime(&calTime)); } +unsigned int +MC146818::drain(Event *de) +{ + if (event.scheduled()) { + rtcTimerInterruptTickOffset = event.when() - curTick; + rtcClockTickOffset = event.when() - curTick; + deschedule(event); + } + if (tickEvent.scheduled()) { + deschedule(tickEvent); + } + return 0; +} + void MC146818::serialize(const string &base, ostream &os) { @@ -214,9 +233,7 @@ MC146818::serialize(const string &base, ostream &os) // save the timer tick and rtc clock tick values to correctly reschedule // them during unserialize // - Tick rtcTimerInterruptTickOffset = event.when() - curTick; SERIALIZE_SCALAR(rtcTimerInterruptTickOffset); - Tick rtcClockTickOffset = event.when() - curTick; SERIALIZE_SCALAR(rtcClockTickOffset); } diff --git a/src/dev/mc146818.hh b/src/dev/mc146818.hh index 699785199..507abab5a 100644 --- a/src/dev/mc146818.hh +++ b/src/dev/mc146818.hh @@ -119,6 +119,10 @@ class MC146818 : public EventManager /** RTC status register B */ uint8_t stat_regB; + /** RTC event times for drain and serialization coordination */ + Tick rtcTimerInterruptTickOffset; + Tick rtcClockTickOffset; + public: MC146818(EventManager *em, const std::string &name, const struct tm time, bool bcd, Tick frequency); @@ -132,6 +136,8 @@ class MC146818 : public EventManager void tickClock(); + unsigned int drain(Event *de); + /** * Serialize this object to the given output stream. * @param base The base name of the counter object. -- cgit v1.2.3