global_event.hh revision 9983
19983Sstever@gmail.com/* 29983Sstever@gmail.com * Copyright (c) 2011-2013 Advanced Micro Devices, Inc. 39983Sstever@gmail.com * Copyright (c) 2013 Mark D. Hill and David A. Wood 49983Sstever@gmail.com * All rights reserved. 59983Sstever@gmail.com * 69983Sstever@gmail.com * Redistribution and use in source and binary forms, with or without 79983Sstever@gmail.com * modification, are permitted provided that the following conditions are 89983Sstever@gmail.com * met: redistributions of source code must retain the above copyright 99983Sstever@gmail.com * notice, this list of conditions and the following disclaimer; 109983Sstever@gmail.com * redistributions in binary form must reproduce the above copyright 119983Sstever@gmail.com * notice, this list of conditions and the following disclaimer in the 129983Sstever@gmail.com * documentation and/or other materials provided with the distribution; 139983Sstever@gmail.com * neither the name of the copyright holders nor the names of its 149983Sstever@gmail.com * contributors may be used to endorse or promote products derived from 159983Sstever@gmail.com * this software without specific prior written permission. 169983Sstever@gmail.com * 179983Sstever@gmail.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 189983Sstever@gmail.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 199983Sstever@gmail.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 209983Sstever@gmail.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 219983Sstever@gmail.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 229983Sstever@gmail.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 239983Sstever@gmail.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 249983Sstever@gmail.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 259983Sstever@gmail.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 269983Sstever@gmail.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 279983Sstever@gmail.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 289983Sstever@gmail.com * 299983Sstever@gmail.com * Authors: Steve Reinhardt 309983Sstever@gmail.com */ 319983Sstever@gmail.com 329983Sstever@gmail.com#ifndef __SIM_GLOBAL_EVENT_HH__ 339983Sstever@gmail.com#define __SIM_GLOBAL_EVENT_HH__ 349983Sstever@gmail.com 359983Sstever@gmail.com#include <mutex> 369983Sstever@gmail.com#include <vector> 379983Sstever@gmail.com 389983Sstever@gmail.com#include "base/barrier.hh" 399983Sstever@gmail.com#include "sim/eventq_impl.hh" 409983Sstever@gmail.com 419983Sstever@gmail.com/** 429983Sstever@gmail.com * @file sim/global_event.hh 439983Sstever@gmail.com * Global events and related declarations. 449983Sstever@gmail.com * 459983Sstever@gmail.com * A global event is an event that occurs across all threads, i.e., 469983Sstever@gmail.com * globally. It consists of a set of "local" (regular) Events, one 479983Sstever@gmail.com * per thread/event queue, a barrier object, and common state. The 489983Sstever@gmail.com * local events are scheduled for the same tick. The local event 499983Sstever@gmail.com * process() method enters the barrier to wait for other threads; once 509983Sstever@gmail.com * all threads reach that tick (and enter the associated barrier), the 519983Sstever@gmail.com * global event is triggered and its associated activity is performed. 529983Sstever@gmail.com * 539983Sstever@gmail.com * There are two basic global event patterns, GlobalEvent and 549983Sstever@gmail.com * GlobalSyncEvent. GlobalEvent is the base class for typical global 559983Sstever@gmail.com * events, while GlobalSyncEvent is optimized for global 569983Sstever@gmail.com * synchronization operations. 579983Sstever@gmail.com */ 589983Sstever@gmail.com 599983Sstever@gmail.com/** 609983Sstever@gmail.com * Common base class for GlobalEvent and GlobalSyncEvent. 619983Sstever@gmail.com */ 629983Sstever@gmail.comclass BaseGlobalEvent : public EventBase 639983Sstever@gmail.com{ 649983Sstever@gmail.com private: 659983Sstever@gmail.com //! Mutex variable for providing exculsive right to schedule global 669983Sstever@gmail.com //! events. This is necessary so that a total order can be maintained 679983Sstever@gmail.com //! amongst the global events. Without ensuring the total order, it is 689983Sstever@gmail.com //! possible that threads execute global events in different orders, 699983Sstever@gmail.com //! which can result in a deadlock. 709983Sstever@gmail.com static std::mutex globalQMutex; 719983Sstever@gmail.com 729983Sstever@gmail.com protected: 739983Sstever@gmail.com 749983Sstever@gmail.com /// The base class for the local events that will synchronize 759983Sstever@gmail.com /// threads to perform the global event. This class is abstract, 769983Sstever@gmail.com /// since it derives from the abstract Event class but still does 779983Sstever@gmail.com /// not define the required process() method. 789983Sstever@gmail.com class BarrierEvent : public Event 799983Sstever@gmail.com { 809983Sstever@gmail.com protected: 819983Sstever@gmail.com BaseGlobalEvent *_globalEvent; 829983Sstever@gmail.com 839983Sstever@gmail.com BarrierEvent(BaseGlobalEvent *global_event, Priority p, Flags f) 849983Sstever@gmail.com : Event(p, f), _globalEvent(global_event) 859983Sstever@gmail.com { 869983Sstever@gmail.com } 879983Sstever@gmail.com 889983Sstever@gmail.com ~BarrierEvent(); 899983Sstever@gmail.com 909983Sstever@gmail.com friend class BaseGlobalEvent; 919983Sstever@gmail.com 929983Sstever@gmail.com bool globalBarrier() 939983Sstever@gmail.com { 949983Sstever@gmail.com return _globalEvent->barrier->wait(); 959983Sstever@gmail.com } 969983Sstever@gmail.com 979983Sstever@gmail.com public: 989983Sstever@gmail.com virtual BaseGlobalEvent *globalEvent() { return _globalEvent; } 999983Sstever@gmail.com }; 1009983Sstever@gmail.com 1019983Sstever@gmail.com //! The barrier that all threads wait on before performing the 1029983Sstever@gmail.com //! global event. 1039983Sstever@gmail.com Barrier *barrier; 1049983Sstever@gmail.com 1059983Sstever@gmail.com //! The individual local event instances (one per thread/event queue). 1069983Sstever@gmail.com std::vector<BarrierEvent *> barrierEvent; 1079983Sstever@gmail.com 1089983Sstever@gmail.com public: 1099983Sstever@gmail.com BaseGlobalEvent(Priority p, Flags f); 1109983Sstever@gmail.com 1119983Sstever@gmail.com virtual ~BaseGlobalEvent(); 1129983Sstever@gmail.com 1139983Sstever@gmail.com virtual void process() = 0; 1149983Sstever@gmail.com 1159983Sstever@gmail.com virtual const char *description() const = 0; 1169983Sstever@gmail.com 1179983Sstever@gmail.com void schedule(Tick when); 1189983Sstever@gmail.com 1199983Sstever@gmail.com bool scheduled() const 1209983Sstever@gmail.com { 1219983Sstever@gmail.com bool sched = false; 1229983Sstever@gmail.com for (uint32_t i = 0; i < numMainEventQueues; ++i) { 1239983Sstever@gmail.com sched = sched || barrierEvent[i]->scheduled(); 1249983Sstever@gmail.com } 1259983Sstever@gmail.com 1269983Sstever@gmail.com return sched; 1279983Sstever@gmail.com } 1289983Sstever@gmail.com 1299983Sstever@gmail.com Tick when() const 1309983Sstever@gmail.com { 1319983Sstever@gmail.com assert(numMainEventQueues > 0); 1329983Sstever@gmail.com return barrierEvent[0]->when(); 1339983Sstever@gmail.com } 1349983Sstever@gmail.com 1359983Sstever@gmail.com void deschedule(); 1369983Sstever@gmail.com void reschedule(Tick when); 1379983Sstever@gmail.com}; 1389983Sstever@gmail.com 1399983Sstever@gmail.com 1409983Sstever@gmail.com/** 1419983Sstever@gmail.com * Funky intermediate class to support CRTP so that we can have a 1429983Sstever@gmail.com * common constructor to create the local events, even though the 1439983Sstever@gmail.com * types of the local events are defined in the derived classes. 1449983Sstever@gmail.com */ 1459983Sstever@gmail.comtemplate <class Derived> 1469983Sstever@gmail.comclass BaseGlobalEventTemplate : public BaseGlobalEvent 1479983Sstever@gmail.com{ 1489983Sstever@gmail.com protected: 1499983Sstever@gmail.com BaseGlobalEventTemplate(Priority p, Flags f) 1509983Sstever@gmail.com : BaseGlobalEvent(p, f) 1519983Sstever@gmail.com { 1529983Sstever@gmail.com for (int i = 0; i < numMainEventQueues; ++i) 1539983Sstever@gmail.com barrierEvent[i] = new typename Derived::BarrierEvent(this, p, f); 1549983Sstever@gmail.com } 1559983Sstever@gmail.com}; 1569983Sstever@gmail.com 1579983Sstever@gmail.com 1589983Sstever@gmail.com/** 1599983Sstever@gmail.com * The main global event class. Ordinary global events should derive 1609983Sstever@gmail.com * from this class, and define process() to specify the action to be 1619983Sstever@gmail.com * taken when the event is reached. All threads will synchronize at a 1629983Sstever@gmail.com * barrier, exactly one of the threads will execute the process() 1639983Sstever@gmail.com * method, then the threads will synchronize again so that none of 1649983Sstever@gmail.com * them continue until process() is complete. 1659983Sstever@gmail.com */ 1669983Sstever@gmail.comclass GlobalEvent : public BaseGlobalEventTemplate<GlobalEvent> 1679983Sstever@gmail.com{ 1689983Sstever@gmail.com public: 1699983Sstever@gmail.com typedef BaseGlobalEventTemplate<GlobalEvent> Base; 1709983Sstever@gmail.com 1719983Sstever@gmail.com class BarrierEvent : public Base::BarrierEvent 1729983Sstever@gmail.com { 1739983Sstever@gmail.com public: 1749983Sstever@gmail.com void process(); 1759983Sstever@gmail.com BarrierEvent(Base *global_event, Priority p, Flags f) 1769983Sstever@gmail.com : Base::BarrierEvent(global_event, p, f) 1779983Sstever@gmail.com { } 1789983Sstever@gmail.com }; 1799983Sstever@gmail.com 1809983Sstever@gmail.com GlobalEvent(Priority p, Flags f) 1819983Sstever@gmail.com : Base(p, f) 1829983Sstever@gmail.com { } 1839983Sstever@gmail.com 1849983Sstever@gmail.com GlobalEvent(Tick when, Priority p, Flags f) 1859983Sstever@gmail.com : Base(p, f) 1869983Sstever@gmail.com { 1879983Sstever@gmail.com schedule(when); 1889983Sstever@gmail.com } 1899983Sstever@gmail.com 1909983Sstever@gmail.com virtual void process() = 0; 1919983Sstever@gmail.com}; 1929983Sstever@gmail.com 1939983Sstever@gmail.com/** 1949983Sstever@gmail.com * A special global event that synchronizes all threads and forces 1959983Sstever@gmail.com * them to process asynchronously enqueued events. Useful for 1969983Sstever@gmail.com * separating quanta in a quantum-based parallel simulation. 1979983Sstever@gmail.com */ 1989983Sstever@gmail.comclass GlobalSyncEvent : public BaseGlobalEventTemplate<GlobalSyncEvent> 1999983Sstever@gmail.com{ 2009983Sstever@gmail.com public: 2019983Sstever@gmail.com typedef BaseGlobalEventTemplate<GlobalSyncEvent> Base; 2029983Sstever@gmail.com 2039983Sstever@gmail.com class BarrierEvent : public Base::BarrierEvent 2049983Sstever@gmail.com { 2059983Sstever@gmail.com public: 2069983Sstever@gmail.com void process(); 2079983Sstever@gmail.com BarrierEvent(Base *global_event, Priority p, Flags f) 2089983Sstever@gmail.com : Base::BarrierEvent(global_event, p, f) 2099983Sstever@gmail.com { } 2109983Sstever@gmail.com }; 2119983Sstever@gmail.com 2129983Sstever@gmail.com GlobalSyncEvent(Priority p, Flags f) 2139983Sstever@gmail.com : Base(p, f) 2149983Sstever@gmail.com { } 2159983Sstever@gmail.com 2169983Sstever@gmail.com GlobalSyncEvent(Tick when, Tick _repeat, Priority p, Flags f) 2179983Sstever@gmail.com : Base(p, f), repeat(_repeat) 2189983Sstever@gmail.com { 2199983Sstever@gmail.com schedule(when); 2209983Sstever@gmail.com } 2219983Sstever@gmail.com 2229983Sstever@gmail.com void process(); 2239983Sstever@gmail.com 2249983Sstever@gmail.com const char *description() const; 2259983Sstever@gmail.com 2269983Sstever@gmail.com Tick repeat; 2279983Sstever@gmail.com}; 2289983Sstever@gmail.com 2299983Sstever@gmail.com 2309983Sstever@gmail.com#endif // __SIM_GLOBAL_EVENT_HH__ 231