eventq.hh revision 237
13520Sgblack@eecs.umich.edu/* 23520Sgblack@eecs.umich.edu * Copyright (c) 2003 The Regents of The University of Michigan 33520Sgblack@eecs.umich.edu * All rights reserved. 43520Sgblack@eecs.umich.edu * 53520Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 63520Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 73520Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 83520Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 93520Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 103520Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 113520Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 123520Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 133520Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 143520Sgblack@eecs.umich.edu * this software without specific prior written permission. 153520Sgblack@eecs.umich.edu * 163520Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 173520Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 183520Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 193520Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 203520Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 213520Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 223520Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 233520Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 243520Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 253520Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 263520Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 273520Sgblack@eecs.umich.edu */ 283520Sgblack@eecs.umich.edu 293520Sgblack@eecs.umich.edu/* @file 303520Sgblack@eecs.umich.edu * EventQueue interfaces 313520Sgblack@eecs.umich.edu */ 323520Sgblack@eecs.umich.edu 333520Sgblack@eecs.umich.edu#ifndef __EVENTQ_HH__ 343520Sgblack@eecs.umich.edu#define __EVENTQ_HH__ 353520Sgblack@eecs.umich.edu 363520Sgblack@eecs.umich.edu#include <assert.h> 374103Ssaidi@eecs.umich.edu 385647Sgblack@eecs.umich.edu#include <algorithm> 393520Sgblack@eecs.umich.edu#include <map> 405647Sgblack@eecs.umich.edu#include <string> 415647Sgblack@eecs.umich.edu#include <vector> 423520Sgblack@eecs.umich.edu 435565Snate@binkert.org#include "sim/host.hh" // for Tick 445565Snate@binkert.org 455647Sgblack@eecs.umich.edu#include "base/fast_alloc.hh" 463520Sgblack@eecs.umich.edu#include "sim/serialize.hh" 475565Snate@binkert.org#include "base/trace.hh" 485565Snate@binkert.org 495565Snate@binkert.orgclass EventQueue; // forward declaration 505565Snate@binkert.org 515810Sgblack@eecs.umich.edu/* 525565Snate@binkert.org * An item on an event queue. The action caused by a given 535565Snate@binkert.org * event is specified by deriving a subclass and overriding the 545565Snate@binkert.org * process() member function. 555565Snate@binkert.org */ 565565Snate@binkert.orgclass Event : public Serializeable, public FastAlloc 575565Snate@binkert.org{ 585647Sgblack@eecs.umich.edu friend class EventQueue; 595647Sgblack@eecs.umich.edu 605647Sgblack@eecs.umich.edu private: 615647Sgblack@eecs.umich.edu /// queue to which this event belongs (though it may or may not be 625647Sgblack@eecs.umich.edu /// scheduled on this queue yet) 635647Sgblack@eecs.umich.edu EventQueue *queue; 645647Sgblack@eecs.umich.edu 655647Sgblack@eecs.umich.edu Event *next; 665810Sgblack@eecs.umich.edu 673520Sgblack@eecs.umich.edu Tick _when; //!< timestamp when event should be processed 685565Snate@binkert.org int _priority; //!< event priority 695565Snate@binkert.org char _flags; 705565Snate@binkert.org 715565Snate@binkert.org protected: 723520Sgblack@eecs.umich.edu enum Flags { 735565Snate@binkert.org None = 0x0, 745810Sgblack@eecs.umich.edu Squashed = 0x1, 755810Sgblack@eecs.umich.edu Scheduled = 0x2, 765810Sgblack@eecs.umich.edu AutoDelete = 0x4, 775810Sgblack@eecs.umich.edu AutoSerialize = 0x8 785810Sgblack@eecs.umich.edu }; 795810Sgblack@eecs.umich.edu 805565Snate@binkert.org bool getFlags(Flags f) const { return (_flags & f) == f; } 815565Snate@binkert.org void setFlags(Flags f) { _flags |= f; } 825565Snate@binkert.org void clearFlags(Flags f) { _flags &= ~f; } 833520Sgblack@eecs.umich.edu 845565Snate@binkert.org protected: 855565Snate@binkert.org EventQueue *theQueue() const { return queue; } 863520Sgblack@eecs.umich.edu 875565Snate@binkert.org#if TRACING_ON 885565Snate@binkert.org Tick when_created; //!< Keep track of creation time For debugging 893520Sgblack@eecs.umich.edu Tick when_scheduled; //!< Keep track of creation time For debugging 905565Snate@binkert.org 915565Snate@binkert.org virtual void trace(const char *action); //!< trace event activity 925565Snate@binkert.org#else 933520Sgblack@eecs.umich.edu void trace(const char *) {} 945565Snate@binkert.org#endif 955565Snate@binkert.org 965565Snate@binkert.org unsigned annotated_value; 975565Snate@binkert.org 983520Sgblack@eecs.umich.edu public: 995568Snate@binkert.org 1005565Snate@binkert.org static const std::string defaultName; 1013520Sgblack@eecs.umich.edu 1025565Snate@binkert.org /* 1035565Snate@binkert.org * Event constructor 1043520Sgblack@eecs.umich.edu * @param queue that the event gets scheduled on 1055565Snate@binkert.org */ 1065565Snate@binkert.org Event(EventQueue *q, int p = 0) 1075565Snate@binkert.org : Serializeable(defaultName), queue(q), next(NULL), 1085565Snate@binkert.org _priority(p), _flags(None), 1093520Sgblack@eecs.umich.edu#if TRACING_ON 1105565Snate@binkert.org when_created(curTick), when_scheduled(0), 1115704Snate@binkert.org#endif 1125565Snate@binkert.org annotated_value(0) 1135565Snate@binkert.org { 1143520Sgblack@eecs.umich.edu } 1155565Snate@binkert.org 1165565Snate@binkert.org /* 1175565Snate@binkert.org * Event constructor 1183520Sgblack@eecs.umich.edu * @param queue that the event gets scheduled on 1195565Snate@binkert.org */ 1205565Snate@binkert.org Event(EventQueue *q, std::string _name, int p = 0) 1215565Snate@binkert.org : Serializeable(_name), queue(q), next(NULL), 1225565Snate@binkert.org _priority(p), _flags(None), 1235565Snate@binkert.org#if TRACING_ON 1245565Snate@binkert.org when_created(curTick), when_scheduled(0), 1253520Sgblack@eecs.umich.edu#endif 1265565Snate@binkert.org annotated_value(0) 1275565Snate@binkert.org { 1285565Snate@binkert.org } 1295565Snate@binkert.org 1305565Snate@binkert.org ~Event() {} 1315565Snate@binkert.org 1323520Sgblack@eecs.umich.edu /// Determine if the current event is scheduled 1335565Snate@binkert.org bool scheduled() const { return getFlags(Scheduled); } 1345704Snate@binkert.org 1355565Snate@binkert.org /// Schedule the event with the current priority or default priority 1365565Snate@binkert.org void schedule(Tick t); 1375565Snate@binkert.org 1383520Sgblack@eecs.umich.edu /// Schedule the event with a specific priority 1395565Snate@binkert.org void schedule(Tick t, int priority); 1405565Snate@binkert.org 1415565Snate@binkert.org /// Reschedule the event with the current priority 1425565Snate@binkert.org void reschedule(Tick t); 1435565Snate@binkert.org 1443521Sgblack@eecs.umich.edu /// Reschedule the event with a specific priority 1455565Snate@binkert.org void reschedule(Tick t, int priority); 1465565Snate@binkert.org 1473520Sgblack@eecs.umich.edu /// Remove the event from the current schedule 1485565Snate@binkert.org void deschedule(); 1495565Snate@binkert.org 1505565Snate@binkert.org /// Return a C string describing the event. This string should 1515565Snate@binkert.org /// *not* be dynamically allocated; just a const char array 1525565Snate@binkert.org /// describing the event class. 1535565Snate@binkert.org virtual const char *description(); 1545565Snate@binkert.org 1553520Sgblack@eecs.umich.edu /// Dump the current event data 1563520Sgblack@eecs.umich.edu void dump(); 1573520Sgblack@eecs.umich.edu 1583520Sgblack@eecs.umich.edu /* 1595565Snate@binkert.org * This member function is invoked when the event is processed 1605565Snate@binkert.org * (occurs). There is no default implementation; each subclass 1615565Snate@binkert.org * must provide its own implementation. The event is not 1625565Snate@binkert.org * automatically deleted after it is processed (to allow for 1635565Snate@binkert.org * statically allocated event objects). 1645565Snate@binkert.org * 1655565Snate@binkert.org * If the AutoDestroy flag is set, the object is deleted once it 1665565Snate@binkert.org * is processed. 1675565Snate@binkert.org */ 1685565Snate@binkert.org virtual void process() = 0; 1693633Sktlim@umich.edu 1703633Sktlim@umich.edu void annotate(unsigned value) { annotated_value = value; }; 1715565Snate@binkert.org unsigned annotation() { return annotated_value; } 1725565Snate@binkert.org 1735565Snate@binkert.org /// Squash the current event 1745565Snate@binkert.org void squash() { setFlags(Squashed); } 1755565Snate@binkert.org 1765565Snate@binkert.org /// Check whether the event is squashed 1775565Snate@binkert.org bool squashed() { return getFlags(Squashed); } 1785565Snate@binkert.org 1795565Snate@binkert.org /// Get the time that the event is scheduled 1805565Snate@binkert.org Tick when() const { return _when; } 1814103Ssaidi@eecs.umich.edu 1825565Snate@binkert.org /// Get the event priority 1834103Ssaidi@eecs.umich.edu int priority() const { return _priority; } 1845565Snate@binkert.org 1855565Snate@binkert.org struct priority_compare : 1865565Snate@binkert.org public std::binary_function<Event *, Event *, bool> 1875565Snate@binkert.org { 1885565Snate@binkert.org bool operator()(const Event *l, const Event *r) const { 1895565Snate@binkert.org return l->when() >= r->when() || l->priority() >= r->priority(); 1905565Snate@binkert.org } 1915565Snate@binkert.org }; 1925565Snate@binkert.org 1933520Sgblack@eecs.umich.edu virtual void serialize(std::ostream &os); 1945565Snate@binkert.org virtual void unserialize(Checkpoint *cp, const std::string §ion); 1955565Snate@binkert.org}; 1965565Snate@binkert.org 1975565Snate@binkert.orgtemplate <class T, void (T::* F)()> 198void 199DelayFunction(Tick when, T *object) 200{ 201 class DelayEvent : public Event 202 { 203 private: 204 T *object; 205 206 public: 207 DelayEvent(Tick when, T *o) 208 : Event(&mainEventQueue), object(o) 209 { setFlags(AutoDestroy); schedule(when); } 210 void process() { (object->*F)(); } 211 const char *description() { return "delay"; } 212 }; 213 214 new DelayEvent(when, object); 215} 216 217/* 218 * Queue of events sorted in time order 219 */ 220class EventQueue : public Serializeable 221{ 222 private: 223 Event *head; 224 225 // only used to hold value between nameChildren() and serialize() 226 int numAutoSerializeEvents; 227 228 void insert(Event *event); 229 void remove(Event *event); 230 231 public: 232 233 // constructor 234 EventQueue(const std::string &n) 235 : Serializeable(n), head(NULL), numAutoSerializeEvents(-1) 236 {} 237 238 // schedule the given event on this queue 239 void schedule(Event *ev); 240 void deschedule(Event *ev); 241 void reschedule(Event *ev); 242 243 Tick nextTick() { return head->when(); } 244 void serviceOne(); 245 246 // process all events up to the given timestamp. we inline a 247 // quick test to see if there are any events to process; if so, 248 // call the internal out-of-line version to process them all. 249 void serviceEvents(Tick when) { 250 while (!empty()) { 251 if (nextTick() > when) 252 break; 253 254 assert(head->when() >= when && "event scheduled in the past"); 255 serviceOne(); 256 } 257 } 258 259 // default: process all events up to 'now' (curTick) 260 void serviceEvents() { serviceEvents(curTick); } 261 262 // return true if no events are queued 263 bool empty() { return head == NULL; } 264 265 void dump(); 266 267 Tick nextEventTime() { return empty() ? curTick : head->when(); } 268 269 virtual void nameChildren(); 270 virtual void serialize(std::ostream &os); 271 virtual void unserialize(Checkpoint *cp, const std::string §ion); 272}; 273 274 275////////////////////// 276// 277// inline functions 278// 279// can't put these inside declaration due to circular dependence 280// between Event and EventQueue classes. 281// 282////////////////////// 283 284// schedule at specified time (place on event queue specified via 285// constructor) 286inline void 287Event::schedule(Tick t) 288{ 289 assert(!scheduled()); 290 setFlags(Scheduled); 291#if TRACING_ON 292 when_scheduled = curTick; 293#endif 294 _when = t; 295 queue->schedule(this); 296} 297 298inline void 299Event::schedule(Tick t, int p) 300{ 301 _priority = p; 302 schedule(t); 303} 304 305inline void 306Event::deschedule() 307{ 308 assert(scheduled()); 309 310 clearFlags(Squashed); 311 clearFlags(Scheduled); 312 queue->deschedule(this); 313} 314 315inline void 316Event::reschedule(Tick t) 317{ 318 assert(scheduled()); 319 clearFlags(Squashed); 320 321#if TRACING_ON 322 when_scheduled = curTick; 323#endif 324 _when = t; 325 queue->reschedule(this); 326} 327 328inline void 329Event::reschedule(Tick t, int p) 330{ 331 _priority = p; 332 reschedule(t); 333} 334 335inline void 336EventQueue::schedule(Event *event) 337{ 338 insert(event); 339 if (DTRACE(Event)) 340 event->trace("scheduled"); 341} 342 343inline void 344EventQueue::deschedule(Event *event) 345{ 346 remove(event); 347 if (DTRACE(Event)) 348 event->trace("descheduled"); 349} 350 351inline void 352EventQueue::reschedule(Event *event) 353{ 354 remove(event); 355 insert(event); 356 if (DTRACE(Event)) 357 event->trace("rescheduled"); 358} 359 360 361////////////////////// 362// 363// Main Event Queue 364// 365// Events on this queue are processed at the *beginning* of each 366// cycle, before the pipeline simulation is performed. 367// 368// defined in eventq.cc 369// 370////////////////////// 371extern EventQueue mainEventQueue; 372 373#endif // __EVENTQ_HH__ 374