global_event.hh revision 11290
112605Sgiacomo.travaglini@arm.com/* 212605Sgiacomo.travaglini@arm.com * Copyright (c) 2011-2013 Advanced Micro Devices, Inc. 312605Sgiacomo.travaglini@arm.com * Copyright (c) 2013 Mark D. Hill and David A. Wood 412605Sgiacomo.travaglini@arm.com * All rights reserved. 512605Sgiacomo.travaglini@arm.com * 612605Sgiacomo.travaglini@arm.com * Redistribution and use in source and binary forms, with or without 712605Sgiacomo.travaglini@arm.com * modification, are permitted provided that the following conditions are 812605Sgiacomo.travaglini@arm.com * met: redistributions of source code must retain the above copyright 912605Sgiacomo.travaglini@arm.com * notice, this list of conditions and the following disclaimer; 1012605Sgiacomo.travaglini@arm.com * redistributions in binary form must reproduce the above copyright 1112605Sgiacomo.travaglini@arm.com * notice, this list of conditions and the following disclaimer in the 1212605Sgiacomo.travaglini@arm.com * documentation and/or other materials provided with the distribution; 1312605Sgiacomo.travaglini@arm.com * neither the name of the copyright holders nor the names of its 1412605Sgiacomo.travaglini@arm.com * contributors may be used to endorse or promote products derived from 1512605Sgiacomo.travaglini@arm.com * this software without specific prior written permission. 1612605Sgiacomo.travaglini@arm.com * 1712605Sgiacomo.travaglini@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1812605Sgiacomo.travaglini@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1912605Sgiacomo.travaglini@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2012605Sgiacomo.travaglini@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2112605Sgiacomo.travaglini@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2212605Sgiacomo.travaglini@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2312605Sgiacomo.travaglini@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2412605Sgiacomo.travaglini@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2512605Sgiacomo.travaglini@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2612605Sgiacomo.travaglini@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2712605Sgiacomo.travaglini@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2812605Sgiacomo.travaglini@arm.com * 2912605Sgiacomo.travaglini@arm.com * Authors: Steve Reinhardt 3012605Sgiacomo.travaglini@arm.com */ 3112605Sgiacomo.travaglini@arm.com 3212605Sgiacomo.travaglini@arm.com#ifndef __SIM_GLOBAL_EVENT_HH__ 3312605Sgiacomo.travaglini@arm.com#define __SIM_GLOBAL_EVENT_HH__ 3412605Sgiacomo.travaglini@arm.com 3512605Sgiacomo.travaglini@arm.com#include <mutex> 3612605Sgiacomo.travaglini@arm.com#include <vector> 3712605Sgiacomo.travaglini@arm.com 3812605Sgiacomo.travaglini@arm.com#include "base/barrier.hh" 3912605Sgiacomo.travaglini@arm.com#include "sim/eventq_impl.hh" 4012605Sgiacomo.travaglini@arm.com 4112605Sgiacomo.travaglini@arm.com/** 4212605Sgiacomo.travaglini@arm.com * @file sim/global_event.hh 4312605Sgiacomo.travaglini@arm.com * Global events and related declarations. 4412605Sgiacomo.travaglini@arm.com * 4512605Sgiacomo.travaglini@arm.com * A global event is an event that occurs across all threads, i.e., 4612605Sgiacomo.travaglini@arm.com * globally. It consists of a set of "local" (regular) Events, one 4712605Sgiacomo.travaglini@arm.com * per thread/event queue, a barrier object, and common state. The 4812605Sgiacomo.travaglini@arm.com * local events are scheduled for the same tick. The local event 4912605Sgiacomo.travaglini@arm.com * process() method enters the barrier to wait for other threads; once 5012605Sgiacomo.travaglini@arm.com * all threads reach that tick (and enter the associated barrier), the 5112605Sgiacomo.travaglini@arm.com * global event is triggered and its associated activity is performed. 5212605Sgiacomo.travaglini@arm.com * 5312605Sgiacomo.travaglini@arm.com * There are two basic global event patterns, GlobalEvent and 5412605Sgiacomo.travaglini@arm.com * GlobalSyncEvent. GlobalEvent is the base class for typical global 5512605Sgiacomo.travaglini@arm.com * events, while GlobalSyncEvent is optimized for global 5612605Sgiacomo.travaglini@arm.com * synchronization operations. 5712605Sgiacomo.travaglini@arm.com */ 5812605Sgiacomo.travaglini@arm.com 5912605Sgiacomo.travaglini@arm.com/** 6012605Sgiacomo.travaglini@arm.com * Common base class for GlobalEvent and GlobalSyncEvent. 6112605Sgiacomo.travaglini@arm.com */ 6212605Sgiacomo.travaglini@arm.comclass BaseGlobalEvent : public EventBase 6312605Sgiacomo.travaglini@arm.com{ 6412605Sgiacomo.travaglini@arm.com private: 6512605Sgiacomo.travaglini@arm.com //! Mutex variable for providing exculsive right to schedule global 6612605Sgiacomo.travaglini@arm.com //! events. This is necessary so that a total order can be maintained 6712605Sgiacomo.travaglini@arm.com //! amongst the global events. Without ensuring the total order, it is 6812605Sgiacomo.travaglini@arm.com //! possible that threads execute global events in different orders, 6912605Sgiacomo.travaglini@arm.com //! which can result in a deadlock. 7012605Sgiacomo.travaglini@arm.com static std::mutex globalQMutex; 7112605Sgiacomo.travaglini@arm.com 7212605Sgiacomo.travaglini@arm.com protected: 7312605Sgiacomo.travaglini@arm.com 7412605Sgiacomo.travaglini@arm.com /// The base class for the local events that will synchronize 7512605Sgiacomo.travaglini@arm.com /// threads to perform the global event. This class is abstract, 7612605Sgiacomo.travaglini@arm.com /// since it derives from the abstract Event class but still does 7712605Sgiacomo.travaglini@arm.com /// not define the required process() method. 7812605Sgiacomo.travaglini@arm.com class BarrierEvent : public Event 7912605Sgiacomo.travaglini@arm.com { 8012605Sgiacomo.travaglini@arm.com protected: 8112605Sgiacomo.travaglini@arm.com BaseGlobalEvent *_globalEvent; 8212605Sgiacomo.travaglini@arm.com 8312605Sgiacomo.travaglini@arm.com BarrierEvent(BaseGlobalEvent *global_event, Priority p, Flags f) 8412605Sgiacomo.travaglini@arm.com : Event(p, f), _globalEvent(global_event) 8512605Sgiacomo.travaglini@arm.com { 8612605Sgiacomo.travaglini@arm.com } 8712605Sgiacomo.travaglini@arm.com 8812605Sgiacomo.travaglini@arm.com ~BarrierEvent(); 8912605Sgiacomo.travaglini@arm.com 9012605Sgiacomo.travaglini@arm.com friend class BaseGlobalEvent; 9112605Sgiacomo.travaglini@arm.com 9212605Sgiacomo.travaglini@arm.com bool globalBarrier() 9312605Sgiacomo.travaglini@arm.com { 9412605Sgiacomo.travaglini@arm.com // This method will be called from the process() method in 9512605Sgiacomo.travaglini@arm.com // the local barrier events 9612605Sgiacomo.travaglini@arm.com // (GlobalSyncEvent::BarrierEvent). The local event 9712605Sgiacomo.travaglini@arm.com // queues are always locked when servicing events (calling 9812605Sgiacomo.travaglini@arm.com // the process() method), which means that it will be 9912605Sgiacomo.travaglini@arm.com // locked when entering this method. We need to unlock it 10012605Sgiacomo.travaglini@arm.com // while waiting on the barrier to prevent deadlocks if 10112605Sgiacomo.travaglini@arm.com // another thread wants to lock the event queue. 10212605Sgiacomo.travaglini@arm.com EventQueue::ScopedRelease release(curEventQueue()); 10312605Sgiacomo.travaglini@arm.com return _globalEvent->barrier.wait(); 10412605Sgiacomo.travaglini@arm.com } 10512605Sgiacomo.travaglini@arm.com 10612605Sgiacomo.travaglini@arm.com public: 10712605Sgiacomo.travaglini@arm.com virtual BaseGlobalEvent *globalEvent() { return _globalEvent; } 10812605Sgiacomo.travaglini@arm.com }; 10912605Sgiacomo.travaglini@arm.com 11012605Sgiacomo.travaglini@arm.com //! The barrier that all threads wait on before performing the 11112605Sgiacomo.travaglini@arm.com //! global event. 11212605Sgiacomo.travaglini@arm.com Barrier barrier; 11312605Sgiacomo.travaglini@arm.com 11412605Sgiacomo.travaglini@arm.com //! The individual local event instances (one per thread/event queue). 11512605Sgiacomo.travaglini@arm.com std::vector<BarrierEvent *> barrierEvent; 11612605Sgiacomo.travaglini@arm.com 11712605Sgiacomo.travaglini@arm.com public: 11812605Sgiacomo.travaglini@arm.com BaseGlobalEvent(Priority p, Flags f); 11912605Sgiacomo.travaglini@arm.com 12012605Sgiacomo.travaglini@arm.com virtual ~BaseGlobalEvent(); 12112605Sgiacomo.travaglini@arm.com 12212605Sgiacomo.travaglini@arm.com virtual void process() = 0; 12312605Sgiacomo.travaglini@arm.com 12412605Sgiacomo.travaglini@arm.com virtual const char *description() const = 0; 12512605Sgiacomo.travaglini@arm.com 12612605Sgiacomo.travaglini@arm.com void schedule(Tick when); 12712605Sgiacomo.travaglini@arm.com 12812605Sgiacomo.travaglini@arm.com bool scheduled() const 12912605Sgiacomo.travaglini@arm.com { 13012605Sgiacomo.travaglini@arm.com bool sched = false; 13112605Sgiacomo.travaglini@arm.com for (uint32_t i = 0; i < numMainEventQueues; ++i) { 13212605Sgiacomo.travaglini@arm.com sched = sched || barrierEvent[i]->scheduled(); 13312605Sgiacomo.travaglini@arm.com } 13412605Sgiacomo.travaglini@arm.com 13512605Sgiacomo.travaglini@arm.com return sched; 13612605Sgiacomo.travaglini@arm.com } 13712605Sgiacomo.travaglini@arm.com 13812605Sgiacomo.travaglini@arm.com Tick when() const 13912605Sgiacomo.travaglini@arm.com { 14012605Sgiacomo.travaglini@arm.com assert(numMainEventQueues > 0); 14112605Sgiacomo.travaglini@arm.com return barrierEvent[0]->when(); 14212605Sgiacomo.travaglini@arm.com } 14312605Sgiacomo.travaglini@arm.com 14412605Sgiacomo.travaglini@arm.com void deschedule(); 14512605Sgiacomo.travaglini@arm.com void reschedule(Tick when); 14612605Sgiacomo.travaglini@arm.com}; 14712605Sgiacomo.travaglini@arm.com 14812605Sgiacomo.travaglini@arm.com 14912605Sgiacomo.travaglini@arm.com/** 15012605Sgiacomo.travaglini@arm.com * Funky intermediate class to support CRTP so that we can have a 15112605Sgiacomo.travaglini@arm.com * common constructor to create the local events, even though the 15212605Sgiacomo.travaglini@arm.com * types of the local events are defined in the derived classes. 15312605Sgiacomo.travaglini@arm.com */ 15412605Sgiacomo.travaglini@arm.comtemplate <class Derived> 15512605Sgiacomo.travaglini@arm.comclass BaseGlobalEventTemplate : public BaseGlobalEvent 15612605Sgiacomo.travaglini@arm.com{ 15712605Sgiacomo.travaglini@arm.com protected: 15812605Sgiacomo.travaglini@arm.com BaseGlobalEventTemplate(Priority p, Flags f) 15912605Sgiacomo.travaglini@arm.com : BaseGlobalEvent(p, f) 16012605Sgiacomo.travaglini@arm.com { 16112605Sgiacomo.travaglini@arm.com for (int i = 0; i < numMainEventQueues; ++i) 16212605Sgiacomo.travaglini@arm.com barrierEvent[i] = new typename Derived::BarrierEvent(this, p, f); 16312605Sgiacomo.travaglini@arm.com } 16412605Sgiacomo.travaglini@arm.com}; 16512605Sgiacomo.travaglini@arm.com 16612605Sgiacomo.travaglini@arm.com 16712605Sgiacomo.travaglini@arm.com/** 16812605Sgiacomo.travaglini@arm.com * The main global event class. Ordinary global events should derive 16912605Sgiacomo.travaglini@arm.com * from this class, and define process() to specify the action to be 17012605Sgiacomo.travaglini@arm.com * taken when the event is reached. All threads will synchronize at a 17112605Sgiacomo.travaglini@arm.com * barrier, exactly one of the threads will execute the process() 17212605Sgiacomo.travaglini@arm.com * method, then the threads will synchronize again so that none of 17312605Sgiacomo.travaglini@arm.com * them continue until process() is complete. 17412605Sgiacomo.travaglini@arm.com */ 17512605Sgiacomo.travaglini@arm.comclass GlobalEvent : public BaseGlobalEventTemplate<GlobalEvent> 17612605Sgiacomo.travaglini@arm.com{ 17712605Sgiacomo.travaglini@arm.com public: 17812605Sgiacomo.travaglini@arm.com typedef BaseGlobalEventTemplate<GlobalEvent> Base; 17912605Sgiacomo.travaglini@arm.com 18012605Sgiacomo.travaglini@arm.com class BarrierEvent : public Base::BarrierEvent 18112605Sgiacomo.travaglini@arm.com { 18212605Sgiacomo.travaglini@arm.com public: 18312605Sgiacomo.travaglini@arm.com void process(); 18412605Sgiacomo.travaglini@arm.com BarrierEvent(Base *global_event, Priority p, Flags f) 18512605Sgiacomo.travaglini@arm.com : Base::BarrierEvent(global_event, p, f) 18612605Sgiacomo.travaglini@arm.com { } 18712605Sgiacomo.travaglini@arm.com }; 18812605Sgiacomo.travaglini@arm.com 18912605Sgiacomo.travaglini@arm.com GlobalEvent(Priority p, Flags f) 19012605Sgiacomo.travaglini@arm.com : Base(p, f) 19112605Sgiacomo.travaglini@arm.com { } 19212605Sgiacomo.travaglini@arm.com 19312605Sgiacomo.travaglini@arm.com GlobalEvent(Tick when, Priority p, Flags f) 19412605Sgiacomo.travaglini@arm.com : Base(p, f) 19512605Sgiacomo.travaglini@arm.com { 19612605Sgiacomo.travaglini@arm.com schedule(when); 19712605Sgiacomo.travaglini@arm.com } 19812605Sgiacomo.travaglini@arm.com 19912605Sgiacomo.travaglini@arm.com virtual void process() = 0; 20012605Sgiacomo.travaglini@arm.com}; 20112605Sgiacomo.travaglini@arm.com 20212605Sgiacomo.travaglini@arm.com/** 20312605Sgiacomo.travaglini@arm.com * A special global event that synchronizes all threads and forces 20412605Sgiacomo.travaglini@arm.com * them to process asynchronously enqueued events. Useful for 20512605Sgiacomo.travaglini@arm.com * separating quanta in a quantum-based parallel simulation. 20612605Sgiacomo.travaglini@arm.com */ 20712605Sgiacomo.travaglini@arm.comclass GlobalSyncEvent : public BaseGlobalEventTemplate<GlobalSyncEvent> 20812605Sgiacomo.travaglini@arm.com{ 20912605Sgiacomo.travaglini@arm.com public: 21012605Sgiacomo.travaglini@arm.com typedef BaseGlobalEventTemplate<GlobalSyncEvent> Base; 21112605Sgiacomo.travaglini@arm.com 21212605Sgiacomo.travaglini@arm.com class BarrierEvent : public Base::BarrierEvent 21312605Sgiacomo.travaglini@arm.com { 21412605Sgiacomo.travaglini@arm.com public: 21512605Sgiacomo.travaglini@arm.com void process(); 21612605Sgiacomo.travaglini@arm.com BarrierEvent(Base *global_event, Priority p, Flags f) 21712605Sgiacomo.travaglini@arm.com : Base::BarrierEvent(global_event, p, f) 21812605Sgiacomo.travaglini@arm.com { } 21912605Sgiacomo.travaglini@arm.com }; 22012605Sgiacomo.travaglini@arm.com 22112605Sgiacomo.travaglini@arm.com GlobalSyncEvent(Priority p, Flags f) 22212605Sgiacomo.travaglini@arm.com : Base(p, f), repeat(0) 22312605Sgiacomo.travaglini@arm.com { } 22412605Sgiacomo.travaglini@arm.com 22512605Sgiacomo.travaglini@arm.com GlobalSyncEvent(Tick when, Tick _repeat, Priority p, Flags f) 22612605Sgiacomo.travaglini@arm.com : Base(p, f), repeat(_repeat) 22712605Sgiacomo.travaglini@arm.com { 22812605Sgiacomo.travaglini@arm.com schedule(when); 22912605Sgiacomo.travaglini@arm.com } 23012605Sgiacomo.travaglini@arm.com 23112605Sgiacomo.travaglini@arm.com void process(); 23212605Sgiacomo.travaglini@arm.com 23312605Sgiacomo.travaglini@arm.com const char *description() const; 23412605Sgiacomo.travaglini@arm.com 23512605Sgiacomo.travaglini@arm.com Tick repeat; 23612605Sgiacomo.travaglini@arm.com}; 23712605Sgiacomo.travaglini@arm.com 23812605Sgiacomo.travaglini@arm.com 23912605Sgiacomo.travaglini@arm.com#endif // __SIM_GLOBAL_EVENT_HH__ 24012605Sgiacomo.travaglini@arm.com