global_event.hh revision 9983:2cce74fe359e
1/* 2 * Copyright (c) 2011-2013 Advanced Micro Devices, Inc. 3 * Copyright (c) 2013 Mark D. Hill and David A. Wood 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer; 10 * redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution; 13 * neither the name of the copyright holders nor the names of its 14 * contributors may be used to endorse or promote products derived from 15 * this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * Authors: Steve Reinhardt 30 */ 31 32#ifndef __SIM_GLOBAL_EVENT_HH__ 33#define __SIM_GLOBAL_EVENT_HH__ 34 35#include <mutex> 36#include <vector> 37 38#include "base/barrier.hh" 39#include "sim/eventq_impl.hh" 40 41/** 42 * @file sim/global_event.hh 43 * Global events and related declarations. 44 * 45 * A global event is an event that occurs across all threads, i.e., 46 * globally. It consists of a set of "local" (regular) Events, one 47 * per thread/event queue, a barrier object, and common state. The 48 * local events are scheduled for the same tick. The local event 49 * process() method enters the barrier to wait for other threads; once 50 * all threads reach that tick (and enter the associated barrier), the 51 * global event is triggered and its associated activity is performed. 52 * 53 * There are two basic global event patterns, GlobalEvent and 54 * GlobalSyncEvent. GlobalEvent is the base class for typical global 55 * events, while GlobalSyncEvent is optimized for global 56 * synchronization operations. 57 */ 58 59/** 60 * Common base class for GlobalEvent and GlobalSyncEvent. 61 */ 62class BaseGlobalEvent : public EventBase 63{ 64 private: 65 //! Mutex variable for providing exculsive right to schedule global 66 //! events. This is necessary so that a total order can be maintained 67 //! amongst the global events. Without ensuring the total order, it is 68 //! possible that threads execute global events in different orders, 69 //! which can result in a deadlock. 70 static std::mutex globalQMutex; 71 72 protected: 73 74 /// The base class for the local events that will synchronize 75 /// threads to perform the global event. This class is abstract, 76 /// since it derives from the abstract Event class but still does 77 /// not define the required process() method. 78 class BarrierEvent : public Event 79 { 80 protected: 81 BaseGlobalEvent *_globalEvent; 82 83 BarrierEvent(BaseGlobalEvent *global_event, Priority p, Flags f) 84 : Event(p, f), _globalEvent(global_event) 85 { 86 } 87 88 ~BarrierEvent(); 89 90 friend class BaseGlobalEvent; 91 92 bool globalBarrier() 93 { 94 return _globalEvent->barrier->wait(); 95 } 96 97 public: 98 virtual BaseGlobalEvent *globalEvent() { return _globalEvent; } 99 }; 100 101 //! The barrier that all threads wait on before performing the 102 //! global event. 103 Barrier *barrier; 104 105 //! The individual local event instances (one per thread/event queue). 106 std::vector<BarrierEvent *> barrierEvent; 107 108 public: 109 BaseGlobalEvent(Priority p, Flags f); 110 111 virtual ~BaseGlobalEvent(); 112 113 virtual void process() = 0; 114 115 virtual const char *description() const = 0; 116 117 void schedule(Tick when); 118 119 bool scheduled() const 120 { 121 bool sched = false; 122 for (uint32_t i = 0; i < numMainEventQueues; ++i) { 123 sched = sched || barrierEvent[i]->scheduled(); 124 } 125 126 return sched; 127 } 128 129 Tick when() const 130 { 131 assert(numMainEventQueues > 0); 132 return barrierEvent[0]->when(); 133 } 134 135 void deschedule(); 136 void reschedule(Tick when); 137}; 138 139 140/** 141 * Funky intermediate class to support CRTP so that we can have a 142 * common constructor to create the local events, even though the 143 * types of the local events are defined in the derived classes. 144 */ 145template <class Derived> 146class BaseGlobalEventTemplate : public BaseGlobalEvent 147{ 148 protected: 149 BaseGlobalEventTemplate(Priority p, Flags f) 150 : BaseGlobalEvent(p, f) 151 { 152 for (int i = 0; i < numMainEventQueues; ++i) 153 barrierEvent[i] = new typename Derived::BarrierEvent(this, p, f); 154 } 155}; 156 157 158/** 159 * The main global event class. Ordinary global events should derive 160 * from this class, and define process() to specify the action to be 161 * taken when the event is reached. All threads will synchronize at a 162 * barrier, exactly one of the threads will execute the process() 163 * method, then the threads will synchronize again so that none of 164 * them continue until process() is complete. 165 */ 166class GlobalEvent : public BaseGlobalEventTemplate<GlobalEvent> 167{ 168 public: 169 typedef BaseGlobalEventTemplate<GlobalEvent> Base; 170 171 class BarrierEvent : public Base::BarrierEvent 172 { 173 public: 174 void process(); 175 BarrierEvent(Base *global_event, Priority p, Flags f) 176 : Base::BarrierEvent(global_event, p, f) 177 { } 178 }; 179 180 GlobalEvent(Priority p, Flags f) 181 : Base(p, f) 182 { } 183 184 GlobalEvent(Tick when, Priority p, Flags f) 185 : Base(p, f) 186 { 187 schedule(when); 188 } 189 190 virtual void process() = 0; 191}; 192 193/** 194 * A special global event that synchronizes all threads and forces 195 * them to process asynchronously enqueued events. Useful for 196 * separating quanta in a quantum-based parallel simulation. 197 */ 198class GlobalSyncEvent : public BaseGlobalEventTemplate<GlobalSyncEvent> 199{ 200 public: 201 typedef BaseGlobalEventTemplate<GlobalSyncEvent> Base; 202 203 class BarrierEvent : public Base::BarrierEvent 204 { 205 public: 206 void process(); 207 BarrierEvent(Base *global_event, Priority p, Flags f) 208 : Base::BarrierEvent(global_event, p, f) 209 { } 210 }; 211 212 GlobalSyncEvent(Priority p, Flags f) 213 : Base(p, f) 214 { } 215 216 GlobalSyncEvent(Tick when, Tick _repeat, Priority p, Flags f) 217 : Base(p, f), repeat(_repeat) 218 { 219 schedule(when); 220 } 221 222 void process(); 223 224 const char *description() const; 225 226 Tick repeat; 227}; 228 229 230#endif // __SIM_GLOBAL_EVENT_HH__ 231