eventq.hh revision 7005
14104Ssaidi@eecs.umich.edu/* 24104Ssaidi@eecs.umich.edu * Copyright (c) 2000-2005 The Regents of The University of Michigan 34104Ssaidi@eecs.umich.edu * All rights reserved. 44104Ssaidi@eecs.umich.edu * 54104Ssaidi@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 64104Ssaidi@eecs.umich.edu * modification, are permitted provided that the following conditions are 74104Ssaidi@eecs.umich.edu * met: redistributions of source code must retain the above copyright 84104Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 94104Ssaidi@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 104104Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 114104Ssaidi@eecs.umich.edu * documentation and/or other materials provided with the distribution; 124104Ssaidi@eecs.umich.edu * neither the name of the copyright holders nor the names of its 134104Ssaidi@eecs.umich.edu * contributors may be used to endorse or promote products derived from 144104Ssaidi@eecs.umich.edu * this software without specific prior written permission. 154104Ssaidi@eecs.umich.edu * 164104Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 174104Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 184104Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 194104Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 204104Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 214104Ssaidi@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 224104Ssaidi@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 234104Ssaidi@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 244104Ssaidi@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 254104Ssaidi@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 264104Ssaidi@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 274104Ssaidi@eecs.umich.edu * 284104Ssaidi@eecs.umich.edu * Authors: Steve Reinhardt 294104Ssaidi@eecs.umich.edu * Nathan Binkert 304104Ssaidi@eecs.umich.edu */ 314104Ssaidi@eecs.umich.edu 324104Ssaidi@eecs.umich.edu/* @file 334104Ssaidi@eecs.umich.edu * EventQueue interfaces 344104Ssaidi@eecs.umich.edu */ 354104Ssaidi@eecs.umich.edu 364104Ssaidi@eecs.umich.edu#ifndef __SIM_EVENTQ_HH__ 374104Ssaidi@eecs.umich.edu#define __SIM_EVENTQ_HH__ 384104Ssaidi@eecs.umich.edu 394104Ssaidi@eecs.umich.edu#include <algorithm> 408229Snate@binkert.org#include <cassert> 414104Ssaidi@eecs.umich.edu#include <climits> 427723SAli.Saidi@ARM.com#include <iosfwd> 434104Ssaidi@eecs.umich.edu#include <string> 444104Ssaidi@eecs.umich.edu 458232Snate@binkert.org#include "base/fast_alloc.hh" 464104Ssaidi@eecs.umich.edu#include "base/flags.hh" 474104Ssaidi@eecs.umich.edu#include "base/misc.hh" 488229Snate@binkert.org#include "base/trace.hh" 494104Ssaidi@eecs.umich.edu#include "base/types.hh" 504194Ssaidi@eecs.umich.edu#include "sim/serialize.hh" 514104Ssaidi@eecs.umich.edu 524104Ssaidi@eecs.umich.educlass EventQueue; // forward declaration 534762Snate@binkert.org 544104Ssaidi@eecs.umich.eduextern EventQueue mainEventQueue; 554104Ssaidi@eecs.umich.edu 564104Ssaidi@eecs.umich.edu/* 574104Ssaidi@eecs.umich.edu * An item on an event queue. The action caused by a given 584104Ssaidi@eecs.umich.edu * event is specified by deriving a subclass and overriding the 594104Ssaidi@eecs.umich.edu * process() member function. 604104Ssaidi@eecs.umich.edu * 615103Ssaidi@eecs.umich.edu * Caution, the order of members is chosen to maximize data packing. 625103Ssaidi@eecs.umich.edu */ 635103Ssaidi@eecs.umich.educlass Event : public Serializable, public FastAlloc 644104Ssaidi@eecs.umich.edu{ 654104Ssaidi@eecs.umich.edu friend class EventQueue; 664104Ssaidi@eecs.umich.edu 674104Ssaidi@eecs.umich.edu protected: 684104Ssaidi@eecs.umich.edu typedef short FlagsType; 694104Ssaidi@eecs.umich.edu typedef ::Flags<FlagsType> Flags; 704104Ssaidi@eecs.umich.edu 714104Ssaidi@eecs.umich.edu static const FlagsType PublicRead = 0x003f; 724104Ssaidi@eecs.umich.edu static const FlagsType PublicWrite = 0x001d; 734104Ssaidi@eecs.umich.edu static const FlagsType Squashed = 0x0001; 744104Ssaidi@eecs.umich.edu static const FlagsType Scheduled = 0x0002; 754104Ssaidi@eecs.umich.edu static const FlagsType AutoDelete = 0x0004; 764104Ssaidi@eecs.umich.edu static const FlagsType AutoSerialize = 0x0008; 774104Ssaidi@eecs.umich.edu static const FlagsType IsExitEvent = 0x0010; 784104Ssaidi@eecs.umich.edu static const FlagsType IsMainQueue = 0x0020; 794104Ssaidi@eecs.umich.edu#ifdef EVENTQ_DEBUG 804104Ssaidi@eecs.umich.edu static const FlagsType Initialized = 0xf000; 814104Ssaidi@eecs.umich.edu#endif 824104Ssaidi@eecs.umich.edu 834104Ssaidi@eecs.umich.edu private: 844104Ssaidi@eecs.umich.edu // The event queue is now a linked list of linked lists. The 854104Ssaidi@eecs.umich.edu // 'nextBin' pointer is to find the bin, where a bin is defined as 864104Ssaidi@eecs.umich.edu // when+priority. All events in the same bin will be stored in a 874870Sstever@eecs.umich.edu // second linked list (a stack) maintained by the 'nextInBin' 884104Ssaidi@eecs.umich.edu // pointer. The list will be accessed in LIFO order. The end 894104Ssaidi@eecs.umich.edu // result is that the insert/removal in 'nextBin' is 904104Ssaidi@eecs.umich.edu // linear/constant, and the lookup/removal in 'nextInBin' is 914104Ssaidi@eecs.umich.edu // constant/constant. Hopefully this is a significant improvement 924104Ssaidi@eecs.umich.edu // over the current fully linear insertion. 934104Ssaidi@eecs.umich.edu Event *nextBin; 944104Ssaidi@eecs.umich.edu Event *nextInBin; 954104Ssaidi@eecs.umich.edu 964104Ssaidi@eecs.umich.edu static Event *insertBefore(Event *event, Event *curr); 976712Snate@binkert.org static Event *removeItem(Event *event, Event *last); 986712Snate@binkert.org 994104Ssaidi@eecs.umich.edu Tick _when; //!< timestamp when event should be processed 1004104Ssaidi@eecs.umich.edu short _priority; //!< event priority 1014104Ssaidi@eecs.umich.edu Flags flags; 1024104Ssaidi@eecs.umich.edu 1034104Ssaidi@eecs.umich.edu#ifndef NDEBUG 1046712Snate@binkert.org /// Global counter to generate unique IDs for Event instances 1056712Snate@binkert.org static Counter instanceCounter; 1066712Snate@binkert.org 1074104Ssaidi@eecs.umich.edu /// This event's unique ID. We can also use pointer values for 1084104Ssaidi@eecs.umich.edu /// this but they're not consistent across runs making debugging 1094104Ssaidi@eecs.umich.edu /// more difficult. Thus we use a global counter value when 1104104Ssaidi@eecs.umich.edu /// debugging. 1114104Ssaidi@eecs.umich.edu Counter instance; 1124104Ssaidi@eecs.umich.edu 1134104Ssaidi@eecs.umich.edu /// queue to which this event belongs (though it may or may not be 1144104Ssaidi@eecs.umich.edu /// scheduled on this queue yet) 1154104Ssaidi@eecs.umich.edu EventQueue *queue; 1164104Ssaidi@eecs.umich.edu#endif 1174104Ssaidi@eecs.umich.edu 1184104Ssaidi@eecs.umich.edu#ifdef EVENTQ_DEBUG 1194104Ssaidi@eecs.umich.edu Tick whenCreated; //!< time created 1204104Ssaidi@eecs.umich.edu Tick whenScheduled; //!< time scheduled 1214104Ssaidi@eecs.umich.edu#endif 1224104Ssaidi@eecs.umich.edu 1235714Shsul@eecs.umich.edu void 1244104Ssaidi@eecs.umich.edu setWhen(Tick when, EventQueue *q) 1254104Ssaidi@eecs.umich.edu { 1264104Ssaidi@eecs.umich.edu _when = when; 1274104Ssaidi@eecs.umich.edu#ifndef NDEBUG 1284104Ssaidi@eecs.umich.edu queue = q; 1294104Ssaidi@eecs.umich.edu#endif 1304104Ssaidi@eecs.umich.edu#ifdef EVENTQ_DEBUG 1314104Ssaidi@eecs.umich.edu whenScheduled = curTick; 1324104Ssaidi@eecs.umich.edu#endif 1334104Ssaidi@eecs.umich.edu } 1344104Ssaidi@eecs.umich.edu 1354104Ssaidi@eecs.umich.edu protected: 1364104Ssaidi@eecs.umich.edu /// Accessor for flags. 1374104Ssaidi@eecs.umich.edu Flags 1384104Ssaidi@eecs.umich.edu getFlags() const 1394104Ssaidi@eecs.umich.edu { 1404104Ssaidi@eecs.umich.edu return flags & PublicRead; 1414104Ssaidi@eecs.umich.edu } 1424104Ssaidi@eecs.umich.edu 1434104Ssaidi@eecs.umich.edu Flags 1444104Ssaidi@eecs.umich.edu getFlags(Flags _flags) const 1454104Ssaidi@eecs.umich.edu { 1464104Ssaidi@eecs.umich.edu assert(flags.noneSet(~PublicRead)); 1474104Ssaidi@eecs.umich.edu return flags.isSet(_flags); 1484104Ssaidi@eecs.umich.edu } 1494104Ssaidi@eecs.umich.edu 1504104Ssaidi@eecs.umich.edu Flags 1514104Ssaidi@eecs.umich.edu allFlags(Flags _flags) const 1524104Ssaidi@eecs.umich.edu { 1534104Ssaidi@eecs.umich.edu assert(_flags.noneSet(~PublicRead)); 1544104Ssaidi@eecs.umich.edu return flags.allSet(_flags); 1554104Ssaidi@eecs.umich.edu } 1564104Ssaidi@eecs.umich.edu 1574104Ssaidi@eecs.umich.edu /// Accessor for flags. 1584104Ssaidi@eecs.umich.edu void 1594104Ssaidi@eecs.umich.edu setFlags(Flags _flags) 1604104Ssaidi@eecs.umich.edu { 1614104Ssaidi@eecs.umich.edu assert(_flags.noneSet(~PublicWrite)); 1624104Ssaidi@eecs.umich.edu flags.set(_flags); 1634104Ssaidi@eecs.umich.edu } 1644104Ssaidi@eecs.umich.edu 1654104Ssaidi@eecs.umich.edu void 1664104Ssaidi@eecs.umich.edu clearFlags(Flags _flags) 1674104Ssaidi@eecs.umich.edu { 1684104Ssaidi@eecs.umich.edu assert(_flags.noneSet(~PublicWrite)); 1694104Ssaidi@eecs.umich.edu flags.clear(_flags); 1704104Ssaidi@eecs.umich.edu } 1714104Ssaidi@eecs.umich.edu 1724104Ssaidi@eecs.umich.edu void 1734104Ssaidi@eecs.umich.edu clearFlags() 1744104Ssaidi@eecs.umich.edu { 1754104Ssaidi@eecs.umich.edu flags.clear(PublicWrite); 1764104Ssaidi@eecs.umich.edu } 1774104Ssaidi@eecs.umich.edu 1784104Ssaidi@eecs.umich.edu // This function isn't really useful if TRACING_ON is not defined 1794104Ssaidi@eecs.umich.edu virtual void trace(const char *action); //!< trace event activity 1804870Sstever@eecs.umich.edu 1814104Ssaidi@eecs.umich.edu public: 1824104Ssaidi@eecs.umich.edu /// Event priorities, to provide tie-breakers for events scheduled 1834104Ssaidi@eecs.umich.edu /// at the same cycle. Most events are scheduled at the default 1844104Ssaidi@eecs.umich.edu /// priority; these values are used to control events that need to 1854104Ssaidi@eecs.umich.edu /// be ordered within a cycle. 1864104Ssaidi@eecs.umich.edu enum Priority { 1874104Ssaidi@eecs.umich.edu /// Minimum priority 1884104Ssaidi@eecs.umich.edu Minimum_Pri = SHRT_MIN, 1894104Ssaidi@eecs.umich.edu 1904104Ssaidi@eecs.umich.edu /// If we enable tracing on a particular cycle, do that as the 1914104Ssaidi@eecs.umich.edu /// very first thing so we don't miss any of the events on 1924104Ssaidi@eecs.umich.edu /// that cycle (even if we enter the debugger). 1934104Ssaidi@eecs.umich.edu Trace_Enable_Pri = -101, 1944104Ssaidi@eecs.umich.edu 1954104Ssaidi@eecs.umich.edu /// Breakpoints should happen before anything else (except 1964216Ssaidi@eecs.umich.edu /// enabling trace output), so we don't miss any action when 1974216Ssaidi@eecs.umich.edu /// debugging. 1984104Ssaidi@eecs.umich.edu Debug_Break_Pri = -100, 1994104Ssaidi@eecs.umich.edu 2004104Ssaidi@eecs.umich.edu /// CPU switches schedule the new CPU's tick event for the 2014104Ssaidi@eecs.umich.edu /// same cycle (after unscheduling the old CPU's tick event). 2026712Snate@binkert.org /// The switch needs to come before any tick events to make 2034104Ssaidi@eecs.umich.edu /// sure we don't tick both CPUs in the same cycle. 2044104Ssaidi@eecs.umich.edu CPU_Switch_Pri = -31, 2054104Ssaidi@eecs.umich.edu 2064104Ssaidi@eecs.umich.edu /// For some reason "delayed" inter-cluster writebacks are 2074216Ssaidi@eecs.umich.edu /// scheduled before regular writebacks (which have default 2084216Ssaidi@eecs.umich.edu /// priority). Steve? 2094104Ssaidi@eecs.umich.edu Delayed_Writeback_Pri = -1, 2104104Ssaidi@eecs.umich.edu 2114104Ssaidi@eecs.umich.edu /// Default is zero for historical reasons. 2124104Ssaidi@eecs.umich.edu Default_Pri = 0, 2134104Ssaidi@eecs.umich.edu 2144216Ssaidi@eecs.umich.edu /// Serailization needs to occur before tick events also, so 2154104Ssaidi@eecs.umich.edu /// that a serialize/unserialize is identical to an on-line 2164104Ssaidi@eecs.umich.edu /// CPU switch. 2174104Ssaidi@eecs.umich.edu Serialize_Pri = 32, 2184104Ssaidi@eecs.umich.edu 2194104Ssaidi@eecs.umich.edu /// CPU ticks must come after other associated CPU events 2204104Ssaidi@eecs.umich.edu /// (such as writebacks). 2214104Ssaidi@eecs.umich.edu CPU_Tick_Pri = 50, 2224104Ssaidi@eecs.umich.edu 2234104Ssaidi@eecs.umich.edu /// Statistics events (dump, reset, etc.) come after 2244104Ssaidi@eecs.umich.edu /// everything else, but before exit. 2254104Ssaidi@eecs.umich.edu Stat_Event_Pri = 90, 2264104Ssaidi@eecs.umich.edu 2274104Ssaidi@eecs.umich.edu /// Progress events come at the end. 2284104Ssaidi@eecs.umich.edu Progress_Event_Pri = 95, 2294104Ssaidi@eecs.umich.edu 2304104Ssaidi@eecs.umich.edu /// If we want to exit on this cycle, it's the very last thing 2314104Ssaidi@eecs.umich.edu /// we do. 2324104Ssaidi@eecs.umich.edu Sim_Exit_Pri = 100, 2334104Ssaidi@eecs.umich.edu 2344104Ssaidi@eecs.umich.edu /// Maximum priority 2354104Ssaidi@eecs.umich.edu Maximum_Pri = SHRT_MAX 2364104Ssaidi@eecs.umich.edu }; 2374104Ssaidi@eecs.umich.edu 2385714Shsul@eecs.umich.edu /* 2394104Ssaidi@eecs.umich.edu * Event constructor 2404104Ssaidi@eecs.umich.edu * @param queue that the event gets scheduled on 2414104Ssaidi@eecs.umich.edu */ 2424104Ssaidi@eecs.umich.edu Event(Priority p = Default_Pri) 2434104Ssaidi@eecs.umich.edu : nextBin(NULL), nextInBin(NULL), _priority(p) 2444104Ssaidi@eecs.umich.edu { 2454104Ssaidi@eecs.umich.edu#ifndef NDEBUG 2464216Ssaidi@eecs.umich.edu instance = ++instanceCounter; 2474216Ssaidi@eecs.umich.edu queue = NULL; 2484104Ssaidi@eecs.umich.edu#endif 2494104Ssaidi@eecs.umich.edu#ifdef EVENTQ_DEBUG 2504104Ssaidi@eecs.umich.edu flags.set(Initialized); 2514104Ssaidi@eecs.umich.edu whenCreated = curTick; 2524104Ssaidi@eecs.umich.edu whenScheduled = 0; 2534216Ssaidi@eecs.umich.edu#endif 2544216Ssaidi@eecs.umich.edu } 2554104Ssaidi@eecs.umich.edu 2564104Ssaidi@eecs.umich.edu virtual ~Event(); 2574104Ssaidi@eecs.umich.edu virtual const std::string name() const; 2584104Ssaidi@eecs.umich.edu 2594104Ssaidi@eecs.umich.edu /// Return a C string describing the event. This string should 2604104Ssaidi@eecs.umich.edu /// *not* be dynamically allocated; just a const char array 2614104Ssaidi@eecs.umich.edu /// describing the event class. 2624104Ssaidi@eecs.umich.edu virtual const char *description() const; 2634104Ssaidi@eecs.umich.edu 2644104Ssaidi@eecs.umich.edu /// Dump the current event data 2654104Ssaidi@eecs.umich.edu void dump() const; 2664104Ssaidi@eecs.umich.edu 2674104Ssaidi@eecs.umich.edu public: 2684104Ssaidi@eecs.umich.edu /* 2694216Ssaidi@eecs.umich.edu * This member function is invoked when the event is processed 2704216Ssaidi@eecs.umich.edu * (occurs). There is no default implementation; each subclass 2714104Ssaidi@eecs.umich.edu * must provide its own implementation. The event is not 2724104Ssaidi@eecs.umich.edu * automatically deleted after it is processed (to allow for 2734104Ssaidi@eecs.umich.edu * statically allocated event objects). 2744104Ssaidi@eecs.umich.edu * 2754104Ssaidi@eecs.umich.edu * If the AutoDestroy flag is set, the object is deleted once it 2764104Ssaidi@eecs.umich.edu * is processed. 2774104Ssaidi@eecs.umich.edu */ 2784194Ssaidi@eecs.umich.edu virtual void process() = 0; 2795719Shsul@eecs.umich.edu 2804104Ssaidi@eecs.umich.edu /// Determine if the current event is scheduled 2814130Ssaidi@eecs.umich.edu bool scheduled() const { return flags.isSet(Scheduled); } 2824194Ssaidi@eecs.umich.edu 2834194Ssaidi@eecs.umich.edu /// Squash the current event 2844216Ssaidi@eecs.umich.edu void squash() { flags.set(Squashed); } 2854216Ssaidi@eecs.umich.edu 2864194Ssaidi@eecs.umich.edu /// Check whether the event is squashed 2874194Ssaidi@eecs.umich.edu bool squashed() const { return flags.isSet(Squashed); } 2884194Ssaidi@eecs.umich.edu 2894194Ssaidi@eecs.umich.edu /// See if this is a SimExitEvent (without resorting to RTTI) 2904194Ssaidi@eecs.umich.edu bool isExitEvent() const { return flags.isSet(IsExitEvent); } 2914194Ssaidi@eecs.umich.edu 2924194Ssaidi@eecs.umich.edu /// Get the time that the event is scheduled 2934194Ssaidi@eecs.umich.edu Tick when() const { return _when; } 2944194Ssaidi@eecs.umich.edu 2954194Ssaidi@eecs.umich.edu /// Get the event priority 2964216Ssaidi@eecs.umich.edu int priority() const { return _priority; } 2974194Ssaidi@eecs.umich.edu 2984194Ssaidi@eecs.umich.edu#ifndef SWIG 2994194Ssaidi@eecs.umich.edu struct priority_compare 3004216Ssaidi@eecs.umich.edu : public std::binary_function<Event *, Event *, bool> 3014194Ssaidi@eecs.umich.edu { 3024194Ssaidi@eecs.umich.edu bool 3034194Ssaidi@eecs.umich.edu operator()(const Event *l, const Event *r) const 3044194Ssaidi@eecs.umich.edu { 3054194Ssaidi@eecs.umich.edu return l->when() >= r->when() || l->priority() >= r->priority(); 3064104Ssaidi@eecs.umich.edu } 3074104Ssaidi@eecs.umich.edu }; 3084104Ssaidi@eecs.umich.edu 3094104Ssaidi@eecs.umich.edu virtual void serialize(std::ostream &os); 3104104Ssaidi@eecs.umich.edu virtual void unserialize(Checkpoint *cp, const std::string §ion); 3114104Ssaidi@eecs.umich.edu#endif 3124104Ssaidi@eecs.umich.edu}; 3134104Ssaidi@eecs.umich.edu 3144104Ssaidi@eecs.umich.edu#ifndef SWIG 3154104Ssaidi@eecs.umich.eduinline bool 3164216Ssaidi@eecs.umich.eduoperator<(const Event &l, const Event &r) 3174216Ssaidi@eecs.umich.edu{ 3184216Ssaidi@eecs.umich.edu return l.when() < r.when() || 3194104Ssaidi@eecs.umich.edu (l.when() == r.when() && l.priority() < r.priority()); 3204104Ssaidi@eecs.umich.edu} 3214104Ssaidi@eecs.umich.edu 3224104Ssaidi@eecs.umich.eduinline bool 3234104Ssaidi@eecs.umich.eduoperator>(const Event &l, const Event &r) 3244104Ssaidi@eecs.umich.edu{ 3254104Ssaidi@eecs.umich.edu return l.when() > r.when() || 3264104Ssaidi@eecs.umich.edu (l.when() == r.when() && l.priority() > r.priority()); 3274104Ssaidi@eecs.umich.edu} 3288711Sandreas.hansson@arm.com 3298711Sandreas.hansson@arm.cominline bool 3304104Ssaidi@eecs.umich.eduoperator<=(const Event &l, const Event &r) 3318711Sandreas.hansson@arm.com{ 3328711Sandreas.hansson@arm.com return l.when() < r.when() || 3338711Sandreas.hansson@arm.com (l.when() == r.when() && l.priority() <= r.priority()); 3348711Sandreas.hansson@arm.com} 3354104Ssaidi@eecs.umich.eduinline bool 3364104Ssaidi@eecs.umich.eduoperator>=(const Event &l, const Event &r) 3374104Ssaidi@eecs.umich.edu{ 3384104Ssaidi@eecs.umich.edu return l.when() > r.when() || 3394104Ssaidi@eecs.umich.edu (l.when() == r.when() && l.priority() >= r.priority()); 3404104Ssaidi@eecs.umich.edu} 3414104Ssaidi@eecs.umich.edu 3424104Ssaidi@eecs.umich.eduinline bool 3434104Ssaidi@eecs.umich.eduoperator==(const Event &l, const Event &r) 3444104Ssaidi@eecs.umich.edu{ 3454104Ssaidi@eecs.umich.edu return l.when() == r.when() && l.priority() == r.priority(); 3464104Ssaidi@eecs.umich.edu} 3474104Ssaidi@eecs.umich.edu 3484104Ssaidi@eecs.umich.eduinline bool 3494104Ssaidi@eecs.umich.eduoperator!=(const Event &l, const Event &r) 3504104Ssaidi@eecs.umich.edu{ 3514104Ssaidi@eecs.umich.edu return l.when() != r.when() || l.priority() != r.priority(); 3524104Ssaidi@eecs.umich.edu} 3534104Ssaidi@eecs.umich.edu#endif 3544104Ssaidi@eecs.umich.edu 3554104Ssaidi@eecs.umich.edu/* 3564104Ssaidi@eecs.umich.edu * Queue of events sorted in time order 3574104Ssaidi@eecs.umich.edu */ 3584104Ssaidi@eecs.umich.educlass EventQueue : public Serializable 3594104Ssaidi@eecs.umich.edu{ 3604104Ssaidi@eecs.umich.edu private: 3614104Ssaidi@eecs.umich.edu std::string objName; 3624104Ssaidi@eecs.umich.edu Event *head; 3634104Ssaidi@eecs.umich.edu 3644104Ssaidi@eecs.umich.edu void insert(Event *event); 3654104Ssaidi@eecs.umich.edu void remove(Event *event); 3664104Ssaidi@eecs.umich.edu 3674104Ssaidi@eecs.umich.edu public: 3684104Ssaidi@eecs.umich.edu EventQueue(const std::string &n) 3694104Ssaidi@eecs.umich.edu : objName(n), head(NULL) 3704104Ssaidi@eecs.umich.edu {} 3714104Ssaidi@eecs.umich.edu 3724104Ssaidi@eecs.umich.edu virtual const std::string name() const { return objName; } 3734104Ssaidi@eecs.umich.edu 3744104Ssaidi@eecs.umich.edu // schedule the given event on this queue 3754104Ssaidi@eecs.umich.edu void schedule(Event *event, Tick when); 3764104Ssaidi@eecs.umich.edu void deschedule(Event *event); 3774762Snate@binkert.org void reschedule(Event *event, Tick when, bool always = false); 3784762Snate@binkert.org 3794104Ssaidi@eecs.umich.edu Tick nextTick() const { return head->when(); } 3804762Snate@binkert.org Event *serviceOne(); 3814104Ssaidi@eecs.umich.edu 382 // process all events up to the given timestamp. we inline a 383 // quick test to see if there are any events to process; if so, 384 // call the internal out-of-line version to process them all. 385 void 386 serviceEvents(Tick when) 387 { 388 while (!empty()) { 389 if (nextTick() > when) 390 break; 391 392 /** 393 * @todo this assert is a good bug catcher. I need to 394 * make it true again. 395 */ 396 //assert(head->when() >= when && "event scheduled in the past"); 397 serviceOne(); 398 } 399 } 400 401 // default: process all events up to 'now' (curTick) 402 void serviceEvents() { serviceEvents(curTick); } 403 404 // return true if no events are queued 405 bool empty() const { return head == NULL; } 406 407 void dump() const; 408 409 Tick nextEventTime() { return empty() ? curTick : head->when(); } 410 411 bool debugVerify() const; 412 413#ifndef SWIG 414 virtual void serialize(std::ostream &os); 415 virtual void unserialize(Checkpoint *cp, const std::string §ion); 416#endif 417}; 418 419#ifndef SWIG 420class EventManager 421{ 422 protected: 423 /** A pointer to this object's event queue */ 424 EventQueue *eventq; 425 426 public: 427 EventManager(EventManager &em) : eventq(em.queue()) {} 428 EventManager(EventManager *em) : eventq(em ? em->queue() : NULL) {} 429 EventManager(EventQueue *eq) : eventq(eq) {} 430 431 EventQueue * 432 queue() const 433 { 434 return eventq; 435 } 436 437 void 438 schedule(Event &event, Tick when) 439 { 440 eventq->schedule(&event, when); 441 } 442 443 void 444 deschedule(Event &event) 445 { 446 eventq->deschedule(&event); 447 } 448 449 void 450 reschedule(Event &event, Tick when, bool always = false) 451 { 452 eventq->reschedule(&event, when, always); 453 } 454 455 void 456 schedule(Event *event, Tick when) 457 { 458 eventq->schedule(event, when); 459 } 460 461 void 462 deschedule(Event *event) 463 { 464 eventq->deschedule(event); 465 } 466 467 void 468 reschedule(Event *event, Tick when, bool always = false) 469 { 470 eventq->reschedule(event, when, always); 471 } 472}; 473 474inline void 475EventQueue::schedule(Event *event, Tick when) 476{ 477 assert((UTick)when >= (UTick)curTick); 478 assert(!event->scheduled()); 479#ifdef EVENTQ_DEBUG 480 assert((event->flags & Event::Initialized) == Event::Initialized); 481#endif 482 483 event->setWhen(when, this); 484 insert(event); 485 event->flags.set(Event::Scheduled); 486 if (this == &mainEventQueue) 487 event->flags.set(Event::IsMainQueue); 488 else 489 event->flags.clear(Event::IsMainQueue); 490 491 if (DTRACE(Event)) 492 event->trace("scheduled"); 493} 494 495inline void 496EventQueue::deschedule(Event *event) 497{ 498 assert(event->scheduled()); 499#ifdef EVENTQ_DEBUG 500 assert((event->flags & Event::Initialized) == Event::Initialized); 501#endif 502 503 remove(event); 504 505 event->flags.clear(Event::Squashed); 506 event->flags.clear(Event::Scheduled); 507 508 if (event->flags.isSet(Event::AutoDelete)) 509 delete event; 510 511 if (DTRACE(Event)) 512 event->trace("descheduled"); 513} 514 515inline void 516EventQueue::reschedule(Event *event, Tick when, bool always) 517{ 518 assert(when >= curTick); 519 assert(always || event->scheduled()); 520#ifdef EVENTQ_DEBUG 521 assert((event->flags & Event::Initialized) == Event::Initialized); 522#endif 523 524 if (event->scheduled()) 525 remove(event); 526 527 event->setWhen(when, this); 528 insert(event); 529 event->flags.clear(Event::Squashed); 530 event->flags.set(Event::Scheduled); 531 if (this == &mainEventQueue) 532 event->flags.set(Event::IsMainQueue); 533 else 534 event->flags.clear(Event::IsMainQueue); 535 536 if (DTRACE(Event)) 537 event->trace("rescheduled"); 538} 539 540template <class T, void (T::* F)()> 541void 542DelayFunction(EventQueue *eventq, Tick when, T *object) 543{ 544 class DelayEvent : public Event 545 { 546 private: 547 T *object; 548 549 public: 550 DelayEvent(T *o) 551 : object(o) 552 { this->setFlags(AutoDelete); } 553 void process() { (object->*F)(); } 554 const char *description() const { return "delay"; } 555 }; 556 557 eventq->schedule(new DelayEvent(object), when); 558} 559 560template <class T, void (T::* F)()> 561class EventWrapper : public Event 562{ 563 private: 564 T *object; 565 566 public: 567 EventWrapper(T *obj, bool del = false, Priority p = Default_Pri) 568 : Event(p), object(obj) 569 { 570 if (del) 571 setFlags(AutoDelete); 572 } 573 574 void process() { (object->*F)(); } 575 576 const std::string 577 name() const 578 { 579 return object->name() + ".wrapped_event"; 580 } 581 582 const char *description() const { return "EventWrapped"; } 583}; 584#endif 585 586#endif // __SIM_EVENTQ_HH__ 587