global_event.hh revision 10153
112647Santhony.gutierrez@amd.com/* 212647Santhony.gutierrez@amd.com * Copyright (c) 2011-2013 Advanced Micro Devices, Inc. 311308Santhony.gutierrez@amd.com * Copyright (c) 2013 Mark D. Hill and David A. Wood 412647Santhony.gutierrez@amd.com * All rights reserved. 511308Santhony.gutierrez@amd.com * 612647Santhony.gutierrez@amd.com * Redistribution and use in source and binary forms, with or without 712647Santhony.gutierrez@amd.com * modification, are permitted provided that the following conditions are 811308Santhony.gutierrez@amd.com * met: redistributions of source code must retain the above copyright 912647Santhony.gutierrez@amd.com * notice, this list of conditions and the following disclaimer; 1012647Santhony.gutierrez@amd.com * redistributions in binary form must reproduce the above copyright 1111308Santhony.gutierrez@amd.com * notice, this list of conditions and the following disclaimer in the 1212647Santhony.gutierrez@amd.com * documentation and/or other materials provided with the distribution; 1312647Santhony.gutierrez@amd.com * neither the name of the copyright holders nor the names of its 1412647Santhony.gutierrez@amd.com * contributors may be used to endorse or promote products derived from 1511308Santhony.gutierrez@amd.com * this software without specific prior written permission. 1612647Santhony.gutierrez@amd.com * 1712647Santhony.gutierrez@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1812647Santhony.gutierrez@amd.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1911308Santhony.gutierrez@amd.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2012647Santhony.gutierrez@amd.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2112647Santhony.gutierrez@amd.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2212647Santhony.gutierrez@amd.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2312647Santhony.gutierrez@amd.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2412647Santhony.gutierrez@amd.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2512647Santhony.gutierrez@amd.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2612647Santhony.gutierrez@amd.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2712647Santhony.gutierrez@amd.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2812647Santhony.gutierrez@amd.com * 2912647Santhony.gutierrez@amd.com * Authors: Steve Reinhardt 3012647Santhony.gutierrez@amd.com */ 3111308Santhony.gutierrez@amd.com 3212647Santhony.gutierrez@amd.com#ifndef __SIM_GLOBAL_EVENT_HH__ 3311308Santhony.gutierrez@amd.com#define __SIM_GLOBAL_EVENT_HH__ 3411308Santhony.gutierrez@amd.com 3511308Santhony.gutierrez@amd.com#include <mutex> 3611308Santhony.gutierrez@amd.com#include <vector> 3711308Santhony.gutierrez@amd.com 3811308Santhony.gutierrez@amd.com#include "base/barrier.hh" 3911308Santhony.gutierrez@amd.com#include "sim/eventq_impl.hh" 4011308Santhony.gutierrez@amd.com 4111670Sandreas.hansson@arm.com/** 4211670Sandreas.hansson@arm.com * @file sim/global_event.hh 4311308Santhony.gutierrez@amd.com * Global events and related declarations. 4411308Santhony.gutierrez@amd.com * 4511308Santhony.gutierrez@amd.com * A global event is an event that occurs across all threads, i.e., 4611308Santhony.gutierrez@amd.com * globally. It consists of a set of "local" (regular) Events, one 4711308Santhony.gutierrez@amd.com * per thread/event queue, a barrier object, and common state. The 4811308Santhony.gutierrez@amd.com * local events are scheduled for the same tick. The local event 4911308Santhony.gutierrez@amd.com * process() method enters the barrier to wait for other threads; once 5011308Santhony.gutierrez@amd.com * all threads reach that tick (and enter the associated barrier), the 5111308Santhony.gutierrez@amd.com * global event is triggered and its associated activity is performed. 5211308Santhony.gutierrez@amd.com * 5311308Santhony.gutierrez@amd.com * There are two basic global event patterns, GlobalEvent and 5411308Santhony.gutierrez@amd.com * GlobalSyncEvent. GlobalEvent is the base class for typical global 5511308Santhony.gutierrez@amd.com * events, while GlobalSyncEvent is optimized for global 5611308Santhony.gutierrez@amd.com * synchronization operations. 5711308Santhony.gutierrez@amd.com */ 5811308Santhony.gutierrez@amd.com 5911308Santhony.gutierrez@amd.com/** 6011308Santhony.gutierrez@amd.com * Common base class for GlobalEvent and GlobalSyncEvent. 6111308Santhony.gutierrez@amd.com */ 6211308Santhony.gutierrez@amd.comclass BaseGlobalEvent : public EventBase 6311308Santhony.gutierrez@amd.com{ 6411308Santhony.gutierrez@amd.com private: 6511308Santhony.gutierrez@amd.com //! Mutex variable for providing exculsive right to schedule global 6611308Santhony.gutierrez@amd.com //! events. This is necessary so that a total order can be maintained 6711308Santhony.gutierrez@amd.com //! amongst the global events. Without ensuring the total order, it is 6811308Santhony.gutierrez@amd.com //! possible that threads execute global events in different orders, 6911308Santhony.gutierrez@amd.com //! which can result in a deadlock. 7011308Santhony.gutierrez@amd.com static std::mutex globalQMutex; 7111308Santhony.gutierrez@amd.com 7211308Santhony.gutierrez@amd.com protected: 7311308Santhony.gutierrez@amd.com 7411308Santhony.gutierrez@amd.com /// The base class for the local events that will synchronize 7511308Santhony.gutierrez@amd.com /// threads to perform the global event. This class is abstract, 7611308Santhony.gutierrez@amd.com /// since it derives from the abstract Event class but still does 7711308Santhony.gutierrez@amd.com /// not define the required process() method. 7811308Santhony.gutierrez@amd.com class BarrierEvent : public Event 7911308Santhony.gutierrez@amd.com { 8011308Santhony.gutierrez@amd.com protected: 8111308Santhony.gutierrez@amd.com BaseGlobalEvent *_globalEvent; 8211308Santhony.gutierrez@amd.com 8311308Santhony.gutierrez@amd.com BarrierEvent(BaseGlobalEvent *global_event, Priority p, Flags f) 8411308Santhony.gutierrez@amd.com : Event(p, f), _globalEvent(global_event) 8511308Santhony.gutierrez@amd.com { 8611308Santhony.gutierrez@amd.com } 8711308Santhony.gutierrez@amd.com 8811308Santhony.gutierrez@amd.com ~BarrierEvent(); 8911308Santhony.gutierrez@amd.com 9011308Santhony.gutierrez@amd.com friend class BaseGlobalEvent; 9111308Santhony.gutierrez@amd.com 9211308Santhony.gutierrez@amd.com bool globalBarrier() 9311308Santhony.gutierrez@amd.com { 9411308Santhony.gutierrez@amd.com // This method will be called from the process() method in 9511308Santhony.gutierrez@amd.com // the local barrier events 9611308Santhony.gutierrez@amd.com // (GlobalSyncEvent::BarrierEvent). The local event 9711308Santhony.gutierrez@amd.com // queues are always locked when servicing events (calling 9811308Santhony.gutierrez@amd.com // the process() method), which means that it will be 9911308Santhony.gutierrez@amd.com // locked when entering this method. We need to unlock it 10011308Santhony.gutierrez@amd.com // while waiting on the barrier to prevent deadlocks if 10111308Santhony.gutierrez@amd.com // another thread wants to lock the event queue. 10211308Santhony.gutierrez@amd.com EventQueue::ScopedRelease release(curEventQueue()); 10311308Santhony.gutierrez@amd.com return _globalEvent->barrier->wait(); 10411308Santhony.gutierrez@amd.com } 10511308Santhony.gutierrez@amd.com 10611308Santhony.gutierrez@amd.com public: 10711308Santhony.gutierrez@amd.com virtual BaseGlobalEvent *globalEvent() { return _globalEvent; } 10811308Santhony.gutierrez@amd.com }; 10911308Santhony.gutierrez@amd.com 11011308Santhony.gutierrez@amd.com //! The barrier that all threads wait on before performing the 11111308Santhony.gutierrez@amd.com //! global event. 11211308Santhony.gutierrez@amd.com Barrier *barrier; 11311308Santhony.gutierrez@amd.com 11411308Santhony.gutierrez@amd.com //! The individual local event instances (one per thread/event queue). 11511308Santhony.gutierrez@amd.com std::vector<BarrierEvent *> barrierEvent; 11611308Santhony.gutierrez@amd.com 11711308Santhony.gutierrez@amd.com public: 11811308Santhony.gutierrez@amd.com BaseGlobalEvent(Priority p, Flags f); 11911308Santhony.gutierrez@amd.com 12011308Santhony.gutierrez@amd.com virtual ~BaseGlobalEvent(); 12111308Santhony.gutierrez@amd.com 12211308Santhony.gutierrez@amd.com virtual void process() = 0; 12311308Santhony.gutierrez@amd.com 12411308Santhony.gutierrez@amd.com virtual const char *description() const = 0; 12511308Santhony.gutierrez@amd.com 12611308Santhony.gutierrez@amd.com void schedule(Tick when); 12711308Santhony.gutierrez@amd.com 12811308Santhony.gutierrez@amd.com bool scheduled() const 12911308Santhony.gutierrez@amd.com { 13011308Santhony.gutierrez@amd.com bool sched = false; 13111308Santhony.gutierrez@amd.com for (uint32_t i = 0; i < numMainEventQueues; ++i) { 13211308Santhony.gutierrez@amd.com sched = sched || barrierEvent[i]->scheduled(); 13311308Santhony.gutierrez@amd.com } 13411308Santhony.gutierrez@amd.com 13511308Santhony.gutierrez@amd.com return sched; 13611308Santhony.gutierrez@amd.com } 13711308Santhony.gutierrez@amd.com 13811308Santhony.gutierrez@amd.com Tick when() const 13911308Santhony.gutierrez@amd.com { 14011308Santhony.gutierrez@amd.com assert(numMainEventQueues > 0); 14111308Santhony.gutierrez@amd.com return barrierEvent[0]->when(); 14211308Santhony.gutierrez@amd.com } 14311308Santhony.gutierrez@amd.com 14411308Santhony.gutierrez@amd.com void deschedule(); 14511308Santhony.gutierrez@amd.com void reschedule(Tick when); 14611308Santhony.gutierrez@amd.com}; 14711308Santhony.gutierrez@amd.com 14811308Santhony.gutierrez@amd.com 14911308Santhony.gutierrez@amd.com/** 15011308Santhony.gutierrez@amd.com * Funky intermediate class to support CRTP so that we can have a 15111308Santhony.gutierrez@amd.com * common constructor to create the local events, even though the 15211308Santhony.gutierrez@amd.com * types of the local events are defined in the derived classes. 15311308Santhony.gutierrez@amd.com */ 15411308Santhony.gutierrez@amd.comtemplate <class Derived> 15511308Santhony.gutierrez@amd.comclass BaseGlobalEventTemplate : public BaseGlobalEvent 15611308Santhony.gutierrez@amd.com{ 15711308Santhony.gutierrez@amd.com protected: 15811308Santhony.gutierrez@amd.com BaseGlobalEventTemplate(Priority p, Flags f) 15911308Santhony.gutierrez@amd.com : BaseGlobalEvent(p, f) 16011308Santhony.gutierrez@amd.com { 16111308Santhony.gutierrez@amd.com for (int i = 0; i < numMainEventQueues; ++i) 16211308Santhony.gutierrez@amd.com barrierEvent[i] = new typename Derived::BarrierEvent(this, p, f); 16311308Santhony.gutierrez@amd.com } 16411308Santhony.gutierrez@amd.com}; 16511308Santhony.gutierrez@amd.com 16611308Santhony.gutierrez@amd.com 16711308Santhony.gutierrez@amd.com/** 16811308Santhony.gutierrez@amd.com * The main global event class. Ordinary global events should derive 16911308Santhony.gutierrez@amd.com * from this class, and define process() to specify the action to be 17011308Santhony.gutierrez@amd.com * taken when the event is reached. All threads will synchronize at a 17111308Santhony.gutierrez@amd.com * barrier, exactly one of the threads will execute the process() 17211308Santhony.gutierrez@amd.com * method, then the threads will synchronize again so that none of 17311308Santhony.gutierrez@amd.com * them continue until process() is complete. 17411308Santhony.gutierrez@amd.com */ 17511308Santhony.gutierrez@amd.comclass GlobalEvent : public BaseGlobalEventTemplate<GlobalEvent> 17611308Santhony.gutierrez@amd.com{ 17711308Santhony.gutierrez@amd.com public: 17811308Santhony.gutierrez@amd.com typedef BaseGlobalEventTemplate<GlobalEvent> Base; 17911308Santhony.gutierrez@amd.com 18011308Santhony.gutierrez@amd.com class BarrierEvent : public Base::BarrierEvent 18111308Santhony.gutierrez@amd.com { 18211308Santhony.gutierrez@amd.com public: 18311308Santhony.gutierrez@amd.com void process(); 18411308Santhony.gutierrez@amd.com BarrierEvent(Base *global_event, Priority p, Flags f) 18511308Santhony.gutierrez@amd.com : Base::BarrierEvent(global_event, p, f) 18611308Santhony.gutierrez@amd.com { } 18711308Santhony.gutierrez@amd.com }; 18811308Santhony.gutierrez@amd.com 18911308Santhony.gutierrez@amd.com GlobalEvent(Priority p, Flags f) 19011308Santhony.gutierrez@amd.com : Base(p, f) 19111308Santhony.gutierrez@amd.com { } 19211308Santhony.gutierrez@amd.com 19311308Santhony.gutierrez@amd.com GlobalEvent(Tick when, Priority p, Flags f) 19411308Santhony.gutierrez@amd.com : Base(p, f) 19511308Santhony.gutierrez@amd.com { 19611308Santhony.gutierrez@amd.com schedule(when); 19711308Santhony.gutierrez@amd.com } 19811308Santhony.gutierrez@amd.com 19911308Santhony.gutierrez@amd.com virtual void process() = 0; 20011308Santhony.gutierrez@amd.com}; 20111308Santhony.gutierrez@amd.com 20211308Santhony.gutierrez@amd.com/** 20311308Santhony.gutierrez@amd.com * A special global event that synchronizes all threads and forces 20411308Santhony.gutierrez@amd.com * them to process asynchronously enqueued events. Useful for 20511308Santhony.gutierrez@amd.com * separating quanta in a quantum-based parallel simulation. 20611308Santhony.gutierrez@amd.com */ 20711308Santhony.gutierrez@amd.comclass GlobalSyncEvent : public BaseGlobalEventTemplate<GlobalSyncEvent> 20811308Santhony.gutierrez@amd.com{ 20911308Santhony.gutierrez@amd.com public: 21011308Santhony.gutierrez@amd.com typedef BaseGlobalEventTemplate<GlobalSyncEvent> Base; 21111308Santhony.gutierrez@amd.com 21211308Santhony.gutierrez@amd.com class BarrierEvent : public Base::BarrierEvent 21311308Santhony.gutierrez@amd.com { 21411308Santhony.gutierrez@amd.com public: 21511308Santhony.gutierrez@amd.com void process(); 21611308Santhony.gutierrez@amd.com BarrierEvent(Base *global_event, Priority p, Flags f) 21711308Santhony.gutierrez@amd.com : Base::BarrierEvent(global_event, p, f) 21811308Santhony.gutierrez@amd.com { } 21911308Santhony.gutierrez@amd.com }; 22011308Santhony.gutierrez@amd.com 22111308Santhony.gutierrez@amd.com GlobalSyncEvent(Priority p, Flags f) 22211308Santhony.gutierrez@amd.com : Base(p, f) 22311308Santhony.gutierrez@amd.com { } 22411308Santhony.gutierrez@amd.com 22511308Santhony.gutierrez@amd.com GlobalSyncEvent(Tick when, Tick _repeat, Priority p, Flags f) 22611308Santhony.gutierrez@amd.com : Base(p, f), repeat(_repeat) 22711308Santhony.gutierrez@amd.com { 22811308Santhony.gutierrez@amd.com schedule(when); 22911308Santhony.gutierrez@amd.com } 23011308Santhony.gutierrez@amd.com 23111308Santhony.gutierrez@amd.com void process(); 23211308Santhony.gutierrez@amd.com 23311308Santhony.gutierrez@amd.com const char *description() const; 23411308Santhony.gutierrez@amd.com 23511308Santhony.gutierrez@amd.com Tick repeat; 23611308Santhony.gutierrez@amd.com}; 23711308Santhony.gutierrez@amd.com 23811308Santhony.gutierrez@amd.com 23911308Santhony.gutierrez@amd.com#endif // __SIM_GLOBAL_EVENT_HH__ 24011308Santhony.gutierrez@amd.com