eventq.hh revision 512
16145Snate@binkert.org/* 26145Snate@binkert.org * Copyright (c) 2003 The Regents of The University of Michigan 36145Snate@binkert.org * All rights reserved. 46145Snate@binkert.org * 56145Snate@binkert.org * Redistribution and use in source and binary forms, with or without 66145Snate@binkert.org * modification, are permitted provided that the following conditions are 76145Snate@binkert.org * met: redistributions of source code must retain the above copyright 86145Snate@binkert.org * notice, this list of conditions and the following disclaimer; 96145Snate@binkert.org * redistributions in binary form must reproduce the above copyright 106145Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 116145Snate@binkert.org * documentation and/or other materials provided with the distribution; 126145Snate@binkert.org * neither the name of the copyright holders nor the names of its 136145Snate@binkert.org * contributors may be used to endorse or promote products derived from 146145Snate@binkert.org * this software without specific prior written permission. 156145Snate@binkert.org * 166145Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176145Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186145Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196145Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206145Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216145Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226145Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236145Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246145Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256145Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266145Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276145Snate@binkert.org */ 286145Snate@binkert.org 298229Snate@binkert.org/* @file 307056Snate@binkert.org * EventQueue interfaces 318615Snilay@cs.wisc.edu */ 328615Snilay@cs.wisc.edu 338615Snilay@cs.wisc.edu#ifndef __EVENTQ_HH__ 348615Snilay@cs.wisc.edu#define __EVENTQ_HH__ 357632SBrad.Beckmann@amd.com 368232Snate@binkert.org#include <assert.h> 378232Snate@binkert.org 388615Snilay@cs.wisc.edu#include <algorithm> 399104Shestness@cs.utexas.edu#include <map> 408615Snilay@cs.wisc.edu#include <string> 418615Snilay@cs.wisc.edu#include <vector> 427039Snate@binkert.org 437039Snate@binkert.org#include "sim/host.hh" // for Tick 447039Snate@binkert.org 458229Snate@binkert.org#include "base/fast_alloc.hh" 466154Snate@binkert.org#include "sim/serialize.hh" 476154Snate@binkert.org#include "base/trace.hh" 487550SBrad.Beckmann@amd.com 496876Ssteve.reinhardt@amd.comclass EventQueue; // forward declaration 507055Snate@binkert.org 517055Snate@binkert.org/* 526876Ssteve.reinhardt@amd.com * An item on an event queue. The action caused by a given 536876Ssteve.reinhardt@amd.com * event is specified by deriving a subclass and overriding the 546285Snate@binkert.org * process() member function. 556876Ssteve.reinhardt@amd.com */ 566285Snate@binkert.orgclass Event : public Serializable, public FastAlloc 577039Snate@binkert.org{ 586876Ssteve.reinhardt@amd.com friend class EventQueue; 596886SBrad.Beckmann@amd.com 606876Ssteve.reinhardt@amd.com private: 616876Ssteve.reinhardt@amd.com /// queue to which this event belongs (though it may or may not be 626876Ssteve.reinhardt@amd.com /// scheduled on this queue yet) 636876Ssteve.reinhardt@amd.com EventQueue *queue; 646876Ssteve.reinhardt@amd.com 657039Snate@binkert.org Event *next; 666876Ssteve.reinhardt@amd.com 676285Snate@binkert.org Tick _when; //!< timestamp when event should be processed 686876Ssteve.reinhardt@amd.com int _priority; //!< event priority 696876Ssteve.reinhardt@amd.com char _flags; 706876Ssteve.reinhardt@amd.com 716876Ssteve.reinhardt@amd.com protected: 726899SBrad.Beckmann@amd.com enum Flags { 736876Ssteve.reinhardt@amd.com None = 0x0, 746876Ssteve.reinhardt@amd.com Squashed = 0x1, 756876Ssteve.reinhardt@amd.com Scheduled = 0x2, 766876Ssteve.reinhardt@amd.com AutoDelete = 0x4, 778171Stushar@csail.mit.edu AutoSerialize = 0x8 788171Stushar@csail.mit.edu }; 796145Snate@binkert.org 806145Snate@binkert.org bool getFlags(Flags f) const { return (_flags & f) == f; } 817039Snate@binkert.org void setFlags(Flags f) { _flags |= f; } 827039Snate@binkert.org void clearFlags(Flags f) { _flags &= ~f; } 836145Snate@binkert.org 846145Snate@binkert.org protected: 857039Snate@binkert.org EventQueue *theQueue() const { return queue; } 867039Snate@binkert.org 877039Snate@binkert.org#if TRACING_ON 889342SAndreas.Sandberg@arm.com Tick when_created; //!< Keep track of creation time For debugging 899245Shestness@cs.wisc.edu Tick when_scheduled; //!< Keep track of creation time For debugging 907039Snate@binkert.org 919501Snilay@cs.wisc.edu virtual void trace(const char *action); //!< trace event activity 926145Snate@binkert.org#else 937039Snate@binkert.org void trace(const char *) {} 947039Snate@binkert.org#endif 956285Snate@binkert.org 967455Snate@binkert.org unsigned annotated_value; 977455Snate@binkert.org 987455Snate@binkert.org public: 997455Snate@binkert.org 1007455Snate@binkert.org /// Event priorities, to provide tie-breakers for events scheduled 1017455Snate@binkert.org /// at the same cycle. Most events are scheduled at the default 1027455Snate@binkert.org /// priority; these values are used to control events that need to 1037805Snilay@cs.wisc.edu /// be ordered within a cycle. 1047921SBrad.Beckmann@amd.com enum Priority { 1057805Snilay@cs.wisc.edu /// Breakpoints should happen before anything else, so we 1068615Snilay@cs.wisc.edu /// don't miss any action when debugging. 1079467Smalek.musleh@gmail.com Debug_Break_Pri = -100, 1089467Smalek.musleh@gmail.com 1096145Snate@binkert.org /// For some reason "delayed" inter-cluster writebacks are 1106145Snate@binkert.org /// scheduled before regular writebacks (which have default 1117455Snate@binkert.org /// priority). Steve? 1127455Snate@binkert.org Delayed_Writeback_Pri = -1, 1137455Snate@binkert.org 1147455Snate@binkert.org /// Default is zero for historical reasons. 1157455Snate@binkert.org Default_Pri = 0, 1167455Snate@binkert.org 1177455Snate@binkert.org /// CPU switches schedule the new CPU's tick event for the 1187805Snilay@cs.wisc.edu /// same cycle (after unscheduling the old CPU's tick event). 1197921SBrad.Beckmann@amd.com /// The switch needs to come before any tick events to make 1207805Snilay@cs.wisc.edu /// sure we don't tick both CPUs in the same cycle. 1218615Snilay@cs.wisc.edu CPU_Switch_Pri = 31, 1229467Smalek.musleh@gmail.com 1239467Smalek.musleh@gmail.com /// Serailization needs to occur before tick events also, so 1246145Snate@binkert.org /// that a serialize/unserialize is identical to an on-line 1256285Snate@binkert.org /// CPU switch. 1267039Snate@binkert.org Serialize_Pri = 32, 1277039Snate@binkert.org 1286145Snate@binkert.org /// CPU ticks must come after other associated CPU events 1297039Snate@binkert.org /// (such as writebacks). 1307039Snate@binkert.org CPU_Tick_Pri = 50, 1317039Snate@binkert.org 1327039Snate@binkert.org /// Statistics events (dump, reset, etc.) come after 1339465Snilay@cs.wisc.edu /// everything else, but before exit. 1347039Snate@binkert.org Stat_Event_Pri = 90, 1356145Snate@binkert.org 1366145Snate@binkert.org /// If we want to exit on this cycle, it's the very last thing 1377039Snate@binkert.org /// we do. 1387039Snate@binkert.org Sim_Exit_Pri = 100 1397039Snate@binkert.org }; 1407039Snate@binkert.org 1417039Snate@binkert.org /* 1427039Snate@binkert.org * Event constructor 1437039Snate@binkert.org * @param queue that the event gets scheduled on 1447039Snate@binkert.org */ 1457039Snate@binkert.org Event(EventQueue *q, Priority p = Default_Pri) 1467039Snate@binkert.org : queue(q), next(NULL), _priority(p), _flags(None), 1477039Snate@binkert.org#if TRACING_ON 1487039Snate@binkert.org when_created(curTick), when_scheduled(0), 1496859Sdrh5@cs.wisc.edu#endif 1506859Sdrh5@cs.wisc.edu annotated_value(0) 1517039Snate@binkert.org { 1527039Snate@binkert.org } 1537039Snate@binkert.org 1547039Snate@binkert.org ~Event() {} 1557039Snate@binkert.org 1567039Snate@binkert.org virtual const std::string name() const { 1579171Snilay@cs.wisc.edu return csprintf("Event_%x", (uintptr_t)this); 1587039Snate@binkert.org } 1597039Snate@binkert.org 1606145Snate@binkert.org /// Determine if the current event is scheduled 1617455Snate@binkert.org bool scheduled() const { return getFlags(Scheduled); } 1627455Snate@binkert.org 1636145Snate@binkert.org /// Schedule the event with the current priority or default priority 1647039Snate@binkert.org void schedule(Tick t); 1657455Snate@binkert.org 1667455Snate@binkert.org /// Reschedule the event with the current priority 1677455Snate@binkert.org void reschedule(Tick t); 1687455Snate@binkert.org 1697039Snate@binkert.org /// Remove the event from the current schedule 1707039Snate@binkert.org void deschedule(); 1717039Snate@binkert.org 1727039Snate@binkert.org /// Return a C string describing the event. This string should 1736145Snate@binkert.org /// *not* be dynamically allocated; just a const char array 1747039Snate@binkert.org /// describing the event class. 1756145Snate@binkert.org virtual const char *description(); 1767455Snate@binkert.org 1777455Snate@binkert.org /// Dump the current event data 1786285Snate@binkert.org void dump(); 1797039Snate@binkert.org 1807455Snate@binkert.org /* 1817455Snate@binkert.org * This member function is invoked when the event is processed 1827455Snate@binkert.org * (occurs). There is no default implementation; each subclass 1837455Snate@binkert.org * must provide its own implementation. The event is not 1847039Snate@binkert.org * automatically deleted after it is processed (to allow for 1857039Snate@binkert.org * statically allocated event objects). 1867039Snate@binkert.org * 1877039Snate@binkert.org * If the AutoDestroy flag is set, the object is deleted once it 1887039Snate@binkert.org * is processed. 1897039Snate@binkert.org */ 1907039Snate@binkert.org virtual void process() = 0; 1917039Snate@binkert.org 1927039Snate@binkert.org void annotate(unsigned value) { annotated_value = value; }; 1937039Snate@binkert.org unsigned annotation() { return annotated_value; } 1947039Snate@binkert.org 1957039Snate@binkert.org /// Squash the current event 1967039Snate@binkert.org void squash() { setFlags(Squashed); } 1977039Snate@binkert.org 1987039Snate@binkert.org /// Check whether the event is squashed 1997039Snate@binkert.org bool squashed() { return getFlags(Squashed); } 2006145Snate@binkert.org 2016145Snate@binkert.org /// Get the time that the event is scheduled 2026145Snate@binkert.org Tick when() const { return _when; } 2036145Snate@binkert.org 2048615Snilay@cs.wisc.edu /// Get the event priority 2058615Snilay@cs.wisc.edu int priority() const { return _priority; } 2067039Snate@binkert.org 2078641Snate@binkert.org struct priority_compare : 2088641Snate@binkert.org public std::binary_function<Event *, Event *, bool> 2096145Snate@binkert.org { 2107039Snate@binkert.org bool operator()(const Event *l, const Event *r) const { 2119342SAndreas.Sandberg@arm.com return l->when() >= r->when() || l->priority() >= r->priority(); 2129342SAndreas.Sandberg@arm.com } 2139465Snilay@cs.wisc.edu }; 2147039Snate@binkert.org 2156145Snate@binkert.org virtual void serialize(std::ostream &os); 2168615Snilay@cs.wisc.edu virtual void unserialize(Checkpoint *cp, const std::string §ion); 2177039Snate@binkert.org}; 2189224Sandreas.hansson@arm.com 2199224Sandreas.hansson@arm.comtemplate <class T, void (T::* F)()> 2209224Sandreas.hansson@arm.comvoid 2219224Sandreas.hansson@arm.comDelayFunction(Tick when, T *object) 2229224Sandreas.hansson@arm.com{ 2238615Snilay@cs.wisc.edu class DelayEvent : public Event 2248615Snilay@cs.wisc.edu { 2258615Snilay@cs.wisc.edu private: 2268615Snilay@cs.wisc.edu T *object; 2278615Snilay@cs.wisc.edu 2288615Snilay@cs.wisc.edu public: 2298615Snilay@cs.wisc.edu DelayEvent(Tick when, T *o) 2308615Snilay@cs.wisc.edu : Event(&mainEventQueue), object(o) 2318615Snilay@cs.wisc.edu { setFlags(AutoDestroy); schedule(when); } 2328615Snilay@cs.wisc.edu void process() { (object->*F)(); } 2338615Snilay@cs.wisc.edu const char *description() { return "delay"; } 2348615Snilay@cs.wisc.edu }; 2358615Snilay@cs.wisc.edu 2368615Snilay@cs.wisc.edu new DelayEvent(when, object); 2378615Snilay@cs.wisc.edu} 2388615Snilay@cs.wisc.edu 2397455Snate@binkert.org/* 2409224Sandreas.hansson@arm.com * Queue of events sorted in time order 2418615Snilay@cs.wisc.edu */ 2428615Snilay@cs.wisc.educlass EventQueue : public Serializable 2439465Snilay@cs.wisc.edu{ 2448615Snilay@cs.wisc.edu protected: 2458615Snilay@cs.wisc.edu std::string objName; 2468615Snilay@cs.wisc.edu 2478615Snilay@cs.wisc.edu private: 2488615Snilay@cs.wisc.edu Event *head; 2498615Snilay@cs.wisc.edu 2508615Snilay@cs.wisc.edu void insert(Event *event); 2518615Snilay@cs.wisc.edu void remove(Event *event); 2528615Snilay@cs.wisc.edu 2538615Snilay@cs.wisc.edu public: 2548615Snilay@cs.wisc.edu 2558615Snilay@cs.wisc.edu // constructor 2568615Snilay@cs.wisc.edu EventQueue(const std::string &n) 2577039Snate@binkert.org : objName(n), head(NULL) 2587455Snate@binkert.org {} 2599224Sandreas.hansson@arm.com 2607039Snate@binkert.org virtual const std::string name() const { return objName; } 2618615Snilay@cs.wisc.edu 2628615Snilay@cs.wisc.edu // schedule the given event on this queue 2639465Snilay@cs.wisc.edu void schedule(Event *ev); 2648615Snilay@cs.wisc.edu void deschedule(Event *ev); 2658615Snilay@cs.wisc.edu void reschedule(Event *ev); 2668615Snilay@cs.wisc.edu 2678615Snilay@cs.wisc.edu Tick nextTick() { return head->when(); } 2688615Snilay@cs.wisc.edu void serviceOne(); 2697039Snate@binkert.org 2706145Snate@binkert.org // process all events up to the given timestamp. we inline a 2716145Snate@binkert.org // quick test to see if there are any events to process; if so, 2727039Snate@binkert.org // call the internal out-of-line version to process them all. 2738641Snate@binkert.org void serviceEvents(Tick when) { 2748641Snate@binkert.org while (!empty()) { 2756145Snate@binkert.org if (nextTick() > when) 2768615Snilay@cs.wisc.edu break; 2776145Snate@binkert.org 2786145Snate@binkert.org assert(head->when() >= when && "event scheduled in the past"); 2797039Snate@binkert.org serviceOne(); 2807455Snate@binkert.org } 2817455Snate@binkert.org } 2827455Snate@binkert.org 2837455Snate@binkert.org // default: process all events up to 'now' (curTick) 2847455Snate@binkert.org void serviceEvents() { serviceEvents(curTick); } 2857455Snate@binkert.org 2867455Snate@binkert.org // return true if no events are queued 2877455Snate@binkert.org bool empty() { return head == NULL; } 2887039Snate@binkert.org 2897039Snate@binkert.org void dump(); 2907039Snate@binkert.org 2917039Snate@binkert.org Tick nextEventTime() { return empty() ? curTick : head->when(); } 2926145Snate@binkert.org 2938615Snilay@cs.wisc.edu virtual void serialize(std::ostream &os); 2947039Snate@binkert.org virtual void unserialize(Checkpoint *cp, const std::string §ion); 2958615Snilay@cs.wisc.edu}; 2968615Snilay@cs.wisc.edu 2978615Snilay@cs.wisc.edu 2988615Snilay@cs.wisc.edu////////////////////// 2998615Snilay@cs.wisc.edu// 3008615Snilay@cs.wisc.edu// inline functions 3018615Snilay@cs.wisc.edu// 3027455Snate@binkert.org// can't put these inside declaration due to circular dependence 3037039Snate@binkert.org// between Event and EventQueue classes. 3047455Snate@binkert.org// 3057039Snate@binkert.org////////////////////// 3066285Snate@binkert.org 3077455Snate@binkert.org// schedule at specified time (place on event queue specified via 3086145Snate@binkert.org// constructor) 3096145Snate@binkert.orginline void 3107560SBrad.Beckmann@amd.comEvent::schedule(Tick t) 3117560SBrad.Beckmann@amd.com{ 3127550SBrad.Beckmann@amd.com assert(!scheduled()); 3137560SBrad.Beckmann@amd.com setFlags(Scheduled); 3147560SBrad.Beckmann@amd.com#if TRACING_ON 3157560SBrad.Beckmann@amd.com when_scheduled = curTick; 3167560SBrad.Beckmann@amd.com#endif 3177560SBrad.Beckmann@amd.com _when = t; 3187560SBrad.Beckmann@amd.com queue->schedule(this); 3198615Snilay@cs.wisc.edu} 3207550SBrad.Beckmann@amd.com 3217550SBrad.Beckmann@amd.cominline void 3227550SBrad.Beckmann@amd.comEvent::deschedule() 3237550SBrad.Beckmann@amd.com{ 3247550SBrad.Beckmann@amd.com assert(scheduled()); 3258615Snilay@cs.wisc.edu 3267560SBrad.Beckmann@amd.com clearFlags(Squashed); 3277550SBrad.Beckmann@amd.com clearFlags(Scheduled); 3287550SBrad.Beckmann@amd.com queue->deschedule(this); 3297550SBrad.Beckmann@amd.com} 3307550SBrad.Beckmann@amd.com 3317550SBrad.Beckmann@amd.cominline void 3328615Snilay@cs.wisc.eduEvent::reschedule(Tick t) 3337550SBrad.Beckmann@amd.com{ 3347560SBrad.Beckmann@amd.com assert(scheduled()); 3357560SBrad.Beckmann@amd.com clearFlags(Squashed); 3367560SBrad.Beckmann@amd.com 3377550SBrad.Beckmann@amd.com#if TRACING_ON 3388615Snilay@cs.wisc.edu when_scheduled = curTick; 3397550SBrad.Beckmann@amd.com#endif 3407550SBrad.Beckmann@amd.com _when = t; 3417550SBrad.Beckmann@amd.com queue->reschedule(this); 3427550SBrad.Beckmann@amd.com} 3437550SBrad.Beckmann@amd.com 3448615Snilay@cs.wisc.eduinline void 3458615Snilay@cs.wisc.eduEventQueue::schedule(Event *event) 3467550SBrad.Beckmann@amd.com{ 3477550SBrad.Beckmann@amd.com insert(event); 3487550SBrad.Beckmann@amd.com if (DTRACE(Event)) 3497550SBrad.Beckmann@amd.com event->trace("scheduled"); 3507550SBrad.Beckmann@amd.com} 3517560SBrad.Beckmann@amd.com 3527550SBrad.Beckmann@amd.cominline void 3537550SBrad.Beckmann@amd.comEventQueue::deschedule(Event *event) 3547550SBrad.Beckmann@amd.com{ 3557039Snate@binkert.org remove(event); 3567039Snate@binkert.org if (DTRACE(Event)) 3577546SBrad.Beckmann@amd.com event->trace("descheduled"); 3587546SBrad.Beckmann@amd.com} 3597546SBrad.Beckmann@amd.com 3607546SBrad.Beckmann@amd.cominline void 3617546SBrad.Beckmann@amd.comEventQueue::reschedule(Event *event) 3627546SBrad.Beckmann@amd.com{ 3637546SBrad.Beckmann@amd.com remove(event); 3647546SBrad.Beckmann@amd.com insert(event); 3657565SBrad.Beckmann@amd.com if (DTRACE(Event)) 3667565SBrad.Beckmann@amd.com event->trace("rescheduled"); 3677565SBrad.Beckmann@amd.com} 3687565SBrad.Beckmann@amd.com 3697565SBrad.Beckmann@amd.com 3707565SBrad.Beckmann@amd.com////////////////////// 3717565SBrad.Beckmann@amd.com// 3727565SBrad.Beckmann@amd.com// Main Event Queue 3737565SBrad.Beckmann@amd.com// 3747565SBrad.Beckmann@amd.com// Events on this queue are processed at the *beginning* of each 3757565SBrad.Beckmann@amd.com// cycle, before the pipeline simulation is performed. 3767039Snate@binkert.org// 3777455Snate@binkert.org// defined in eventq.cc 3786145Snate@binkert.org// 3797455Snate@binkert.org////////////////////// 3807455Snate@binkert.orgextern EventQueue mainEventQueue; 3817455Snate@binkert.org 3826145Snate@binkert.org#endif // __EVENTQ_HH__ 3837455Snate@binkert.org