diff -r daf33013a68c -r 55df9c2b1128 src/sim/eventq.hh --- a/src/sim/eventq.hh Sun Apr 18 22:35:00 2010 -0700 +++ b/src/sim/eventq.hh Sun Apr 18 22:37:48 2010 -0700 @@ -133,6 +133,30 @@ Tick whenScheduled; //!< time scheduled #endif + static const unsigned cache_size_bits = 8; + static const unsigned cache_size = 1 << cache_size_bits; + static const unsigned cache_size_mask = cache_size - 1; + + unsigned + hash() const + { + unsigned hash = 0; + + // Just add in the time and priority (I've tried adding in + // other bits as well, but the cache hit rate is not any + // higher). + hash += _when; + hash += _priority; + + // Mask to make direct mapped + hash &= cache_size_mask; + + // Sanity check + assert(hash >= 0 && hash < cache_size); + + return hash; + } + void setWhen(Tick when, EventQueue *q) { @@ -371,7 +395,9 @@ private: std::string objName; Event *head; + Event *cache[Event::cache_size]; + void insertCached(Event *event); bool insert(Event *event, Event *hint); void insert(Event *event); void remove(Event *event); @@ -433,10 +459,14 @@ Stats::Scalar descheduled; Stats::Scalar rescheduled; Stats::Scalar squashed; + Stats::Scalar cache_hit; + Stats::Scalar cache_miss; Stats::Formula deschedule_rate; Stats::Formula reschedule_rate; Stats::Formula squash_rate; + Stats::Formula cache_accesses; + Stats::Formula cache_hit_rate; #endif // EVENTQ_STATS #endif // SWIG }; @@ -501,6 +531,24 @@ } }; +inline void +EventQueue::insertCached(Event *event) +{ + uint8_t hash = event->hash(); + Event *hint = cache[hash]; + + bool hit = insert(event, hint); + if (!hit) + cache[hash] = event; + +#ifdef EVENTQ_STATS + if (hit) + cache_hit++; + else + cache_miss++; +#endif +} + inline bool EventQueue::insert(Event *event, Event *hint) { @@ -523,7 +571,7 @@ assert(event->initialized()); event->setWhen(when, this); - insert(event); + insertCached(event); event->flags.set(Event::Scheduled); if (this == &mainEventQueue) event->flags.set(Event::IsMainQueue); @@ -567,11 +615,18 @@ assert(always || event->scheduled()); assert(event->initialized()); - if (event->scheduled()) + if (event->scheduled()) { remove(event); + + // We need to mark this event as not being scheduled anymore + // because we might pull this event from the cache (because it + // was scheduled in the past). By marking it as no longer + // scheduled, it will not hit in the cache. + event->flags.clear(Event::Scheduled); + } event->setWhen(when, this); - insert(event); + insertCached(event); event->flags.clear(Event::Squashed); event->flags.set(Event::Scheduled); if (this == &mainEventQueue) diff -r daf33013a68c -r 55df9c2b1128 src/sim/eventq.cc --- a/src/sim/eventq.cc Sun Apr 18 22:35:00 2010 -0700 +++ b/src/sim/eventq.cc Sun Apr 18 22:37:48 2010 -0700 @@ -414,7 +414,9 @@ EventQueue::EventQueue(const string &n) : objName(n), head(NULL) -{} +{ + memset(cache, 0, sizeof(cache)); +} void EventQueue::regStats() @@ -440,6 +442,16 @@ .desc("Total number of events squashed from processing") ; + cache_hit + .name(name() + ".cache_hit") + .desc("Total number of event cache hits") + ; + + cache_miss + .name(name() + ".cache_miss") + .desc("Total number of event cache misses") + ; + deschedule_rate .name(name() + ".deschedule_rate") .desc("Rate of total deschedules to total schedules") @@ -455,8 +467,20 @@ .desc("Rate of events squashed from processing to scheduled events") ; + cache_accesses + .name(name() + ".cache_accesses") + .desc("Total number of event cache accesses") + ; + + cache_hit_rate + .name(name() + ".cache_hit_rate") + .desc("Fraction of event cache hits") + ; + deschedule_rate = descheduled / scheduled; reschedule_rate = rescheduled / scheduled; squash_rate = squashed / scheduled; + cache_accesses = cache_hit + cache_miss; + cache_hit_rate = cache_hit / cache_accesses; #endif // EVENTQ_STATS }