gem5  v22.0.0.2
simulate.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2021 Arm Limited
3  * All rights reserved
4  *
5  * The license below extends only to copyright in the software and shall
6  * not be construed as granting a license to any other intellectual
7  * property including but not limited to intellectual property relating
8  * to a hardware implementation of the functionality of the software
9  * licensed hereunder. You may use the software subject to the license
10  * terms below provided that you ensure that this notice is replicated
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Copyright (c) 2006 The Regents of The University of Michigan
15  * Copyright (c) 2013 Advanced Micro Devices, Inc.
16  * Copyright (c) 2013 Mark D. Hill and David A. Wood
17  * All rights reserved.
18  *
19  * Redistribution and use in source and binary forms, with or without
20  * modification, are permitted provided that the following conditions are
21  * met: redistributions of source code must retain the above copyright
22  * notice, this list of conditions and the following disclaimer;
23  * redistributions in binary form must reproduce the above copyright
24  * notice, this list of conditions and the following disclaimer in the
25  * documentation and/or other materials provided with the distribution;
26  * neither the name of the copyright holders nor the names of its
27  * contributors may be used to endorse or promote products derived from
28  * this software without specific prior written permission.
29  *
30  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
34  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
36  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
40  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41  */
42 
43 #include "sim/simulate.hh"
44 
45 #include <atomic>
46 #include <mutex>
47 #include <thread>
48 
49 #include "base/logging.hh"
50 #include "base/pollevent.hh"
51 #include "base/types.hh"
52 #include "sim/async.hh"
53 #include "sim/eventq.hh"
54 #include "sim/sim_events.hh"
55 #include "sim/sim_exit.hh"
56 #include "sim/stat_control.hh"
57 
58 namespace gem5
59 {
60 
62 Event *doSimLoop(EventQueue *);
63 
65 
67 {
68  public:
69  SimulatorThreads() = delete;
70  SimulatorThreads(const SimulatorThreads &) = delete;
72 
73  SimulatorThreads(uint32_t num_queues)
74  : terminate(false),
75  numQueues(num_queues),
76  barrier(num_queues)
77  {
78  threads.reserve(num_queues);
79  }
80 
82  {
83  // This should only happen after exit has been
84  // called. Subordinate event queues should normally (assuming
85  // exit is called from Python) be waiting on the barrier when
86  // this happens.
87  //
88  // N.B.: Not terminating here would make it impossible to
89  // safely destroy the barrier.
91  }
92 
94  {
95  assert(!terminate);
96 
97  // Start subordinate threads if needed.
98  if (threads.empty()) {
99  // the main thread (the one running Python) handles queue 0,
100  // so we only need to allocate new threads for queues 1..N-1.
101  // We'll call these the "subordinate" threads.
102  for (uint32_t i = 1; i < numQueues; i++) {
103  threads.emplace_back(
104  [this](EventQueue *eq) {
105  thread_main(eq);
106  }, mainEventQueue[i]);
107  }
108  }
109 
110  // This method is called from the main thread. All subordinate
111  // threads should be waiting on the barrier when the function
112  // is called. The arrival of the main thread here will satisfy
113  // the barrier and start another iteration in the thread loop.
114  barrier.wait();
115  }
116 
117  void
119  {
120  assert(!terminate);
121  if (threads.empty())
122  return;
123 
124  /* This function should only be called when the simulator is
125  * handling a global exit event (typically from Python). This
126  * means that the helper threads will be waiting on the
127  * barrier. Tell the helper threads to exit and release them from
128  * their barrier. */
129  terminate = true;
130  barrier.wait();
131 
132  /* Wait for all of the threads to terminate */
133  for (auto &t : threads) {
134  t.join();
135  }
136 
137  terminate = false;
138  threads.clear();
139  }
140 
141  protected:
150  void
152  {
153  /* Wait for all initialisation to complete */
154  barrier.wait();
155 
156  while (!terminate) {
157  doSimLoop(queue);
158  barrier.wait();
159  }
160  }
161 
162  std::atomic<bool> terminate;
163  uint32_t numQueues;
166 };
167 
168 static std::unique_ptr<SimulatorThreads> simulatorThreads;
169 
171 {
173  {
174  if (!event)
175  return;
176 
177  event->deschedule();
178  delete event;
179  }
180 };
181 
187 GlobalSimLoopExitEvent *
188 simulate(Tick num_cycles)
189 {
190  std::unique_ptr<GlobalSyncEvent, DescheduleDeleter> quantum_event;
191  const Tick exit_tick = num_cycles < MaxTick - curTick() ?
192  curTick() + num_cycles : MaxTick;
193 
194  inform("Entering event queue @ %d. Starting simulation...\n", curTick());
195 
196  if (!simulatorThreads)
198 
199  if (!simulate_limit_event) {
201  mainEventQueue[0]->getCurTick(),
202  "simulate() limit reached", 0);
203  }
204  simulate_limit_event->reschedule(exit_tick);
205 
206  if (numMainEventQueues > 1) {
207  fatal_if(simQuantum == 0,
208  "Quantum for multi-eventq simulation not specified");
209 
210  quantum_event.reset(
213 
214  inParallelMode = true;
215  }
216 
217  simulatorThreads->runUntilLocalExit();
218  Event *local_event = doSimLoop(mainEventQueue[0]);
219  assert(local_event);
220 
221  inParallelMode = false;
222 
223  // locate the global exit event and return it to Python
224  BaseGlobalEvent *global_event = local_event->globalEvent();
225  assert(global_event);
226 
227  GlobalSimLoopExitEvent *global_exit_event =
228  dynamic_cast<GlobalSimLoopExitEvent *>(global_event);
229  assert(global_exit_event);
230 
231  return global_exit_event;
232 }
233 
234 void
236 {
237  simulatorThreads->terminateThreads();
238 }
239 
240 
246 static bool
248 {
249  static std::mutex mutex;
250 
251  bool was_set = false;
252  mutex.lock();
253 
254  if (async_event) {
255  was_set = true;
256  async_event = false;
257  }
258 
259  mutex.unlock();
260  return was_set;
261 }
262 
268 Event *
270 {
271  // set the per thread current eventq pointer
272  curEventQueue(eventq);
273  eventq->handleAsyncInsertions();
274 
275  while (1) {
276  // there should always be at least one event (the SimLoopExitEvent
277  // we just scheduled) in the queue
278  assert(!eventq->empty());
279  assert(curTick() <= eventq->nextTick() &&
280  "event scheduled in the past");
281 
283  // Take the event queue lock in case any of the service
284  // routines want to schedule new events.
285  std::lock_guard<EventQueue> lock(*eventq);
288  async_statdump = false;
289  async_statreset = false;
290  }
291 
292  if (async_io) {
293  async_io = false;
294  pollQueue.service();
295  }
296 
297  if (async_exit) {
298  async_exit = false;
299  exitSimLoop("user interrupt received");
300  }
301 
302  if (async_exception) {
303  async_exception = false;
304  return NULL;
305  }
306  }
307 
308  Event *exit_event = eventq->serviceOne();
309  if (exit_event != NULL) {
310  return exit_event;
311  }
312  }
313 
314  // not reached... only exit is return on SimLoopExitEvent
315 }
316 
317 } // namespace gem5
gem5::GlobalSyncEvent
A special global event that synchronizes all threads and forces them to process asynchronously enqueu...
Definition: global_event.hh:208
gem5::curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
gem5::terminateEventQueueThreads
void terminateEventQueueThreads()
Terminate helper threads when running in parallel mode.
Definition: simulate.cc:235
gem5::Barrier::wait
bool wait()
Definition: barrier.hh:66
gem5::mainEventQueue
std::vector< EventQueue * > mainEventQueue
Array for main event queues.
Definition: eventq.cc:57
sim_events.hh
gem5::pollQueue
PollQueue pollQueue
Definition: pollevent.cc:55
gem5::async_exit
volatile bool async_exit
Async request to exit simulator.
Definition: async.cc:35
gem5::SimulatorThreads::barrier
Barrier barrier
Definition: simulate.cc:165
simulate.hh
gem5::MipsISA::event
Bitfield< 10, 5 > event
Definition: pra_constants.hh:300
gem5::SimulatorThreads::terminate
std::atomic< bool > terminate
Definition: simulate.cc:162
gem5::testAndClearAsyncEvent
static bool testAndClearAsyncEvent()
Test and clear the global async_event flag, such that each time the flag is cleared,...
Definition: simulate.cc:247
gem5::BaseGlobalEvent::reschedule
void reschedule(Tick when)
Definition: global_event.cc:100
gem5::X86ISA::lock
Bitfield< 5 > lock
Definition: types.hh:82
gem5::async_statreset
volatile bool async_statreset
Async request to reset stats.
Definition: async.cc:34
gem5::inParallelMode
bool inParallelMode
Current mode of execution: parallel / serial.
Definition: eventq.cc:59
gem5::MaxTick
const Tick MaxTick
Definition: types.hh:60
gem5::GlobalSimLoopExitEvent
Definition: sim_events.hh:55
gem5::DescheduleDeleter::operator()
void operator()(BaseGlobalEvent *event)
Definition: simulate.cc:172
std::vector< std::thread >
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:67
sim_exit.hh
gem5::EventBase::Progress_Event_Pri
static const Priority Progress_Event_Pri
Progress events come at the end.
Definition: eventq.hh:226
gem5::SimulatorThreads::runUntilLocalExit
void runUntilLocalExit()
Definition: simulate.cc:93
gem5::exitSimLoop
void exitSimLoop(const std::string &message, int exit_code, Tick when, Tick repeat, bool serialize)
Schedule an event to exit the simulation loop (returning to Python) at the end of the current cycle (...
Definition: sim_events.cc:88
gem5::async_statdump
volatile bool async_statdump
Async request to dump stats.
Definition: async.cc:33
gem5::doSimLoop
Event * doSimLoop(EventQueue *)
forward declaration
Definition: simulate.cc:269
gem5::SimulatorThreads::numQueues
uint32_t numQueues
Definition: simulate.cc:163
gem5::EventQueue::handleAsyncInsertions
void handleAsyncInsertions()
Function for moving events from the async_queue to the main queue.
Definition: eventq.cc:432
gem5::SimulatorThreads
Definition: simulate.cc:66
gem5::BaseGlobalEvent
Common base class for GlobalEvent and GlobalSyncEvent.
Definition: global_event.hh:63
gem5::VegaISA::t
Bitfield< 51 > t
Definition: pagetable.hh:56
gem5::SimulatorThreads::operator=
SimulatorThreads & operator=(SimulatorThreads &)=delete
gem5::async_exception
volatile bool async_exception
Python exception.
Definition: async.cc:37
gem5::Event
Definition: eventq.hh:251
gem5::SimulatorThreads::~SimulatorThreads
~SimulatorThreads()
Definition: simulate.cc:81
gem5::Tick
uint64_t Tick
Tick count type.
Definition: types.hh:58
pollevent.hh
gem5::EventQueue::nextTick
Tick nextTick() const
Definition: eventq.hh:843
gem5::DescheduleDeleter
Definition: simulate.cc:170
gem5::EventQueue
Queue of events sorted in time order.
Definition: eventq.hh:622
gem5::Event::globalEvent
virtual BaseGlobalEvent * globalEvent()
If this is part of a GlobalEvent, return the pointer to the Global Event.
Definition: eventq.hh:520
gem5::simQuantum
Tick simQuantum
Simulation Quantum for multiple eventq simulation.
Definition: eventq.cc:48
gem5::EventQueue::empty
bool empty() const
Returns true if no events are queued.
Definition: eventq.hh:898
gem5::SimulatorThreads::terminateThreads
void terminateThreads()
Definition: simulate.cc:118
gem5::SimulatorThreads::SimulatorThreads
SimulatorThreads()=delete
gem5::async_io
volatile bool async_io
Async I/O request (SIGIO).
Definition: async.cc:36
gem5::Barrier
Definition: barrier.hh:46
async.hh
stat_control.hh
gem5::simulate
GlobalSimLoopExitEvent * simulate(Tick num_cycles)
Simulate for num_cycles additional cycles.
Definition: simulate.cc:188
inform
#define inform(...)
Definition: logging.hh:247
gem5::curEventQueue
EventQueue * curEventQueue()
Definition: eventq.hh:88
types.hh
gem5::PowerISA::eq
Bitfield< 29 > eq
Definition: misc.hh:53
gem5::numMainEventQueues
uint32_t numMainEventQueues
Current number of allocated main event queues.
Definition: eventq.cc:56
gem5::SimulatorThreads::thread_main
void thread_main(EventQueue *queue)
The main function for all subordinate threads (i.e., all threads other than the main thread).
Definition: simulate.cc:151
logging.hh
gem5::SimulatorThreads::threads
std::vector< std::thread > threads
Definition: simulate.cc:164
gem5::PollQueue::service
void service()
Definition: pollevent.cc:186
fatal_if
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition: logging.hh:226
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: gpu_translation_state.hh:37
gem5::EventQueue::serviceOne
Event * serviceOne()
Definition: eventq.cc:198
gem5::simulatorThreads
static std::unique_ptr< SimulatorThreads > simulatorThreads
Definition: simulate.cc:168
gem5::statistics::schedStatEvent
void schedStatEvent(bool dump, bool reset, Tick when, Tick repeat)
Schedule statistics dumping.
Definition: stat_control.cc:107
gem5::async_event
volatile bool async_event
Some asynchronous event has happened.
Definition: async.cc:32
gem5::simulate_limit_event
GlobalSimLoopExitEvent * simulate_limit_event
Definition: simulate.cc:64
gem5::SimulatorThreads::SimulatorThreads
SimulatorThreads(uint32_t num_queues)
Definition: simulate.cc:73
eventq.hh

Generated on Thu Jul 28 2022 13:32:37 for gem5 by doxygen 1.8.17