gem5  [DEVELOP-FOR-23.0]
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 <thread>
47 
48 #include "base/logging.hh"
49 #include "base/pollevent.hh"
50 #include "base/types.hh"
51 #include "sim/async.hh"
52 #include "sim/eventq.hh"
53 #include "sim/sim_events.hh"
54 #include "sim/sim_exit.hh"
55 #include "sim/stat_control.hh"
56 
57 namespace gem5
58 {
59 
61 Event *doSimLoop(EventQueue *);
62 
64 
66 {
67  public:
68  SimulatorThreads() = delete;
69  SimulatorThreads(const SimulatorThreads &) = delete;
71 
72  SimulatorThreads(uint32_t num_queues)
73  : terminate(false),
74  numQueues(num_queues),
75  barrier(num_queues)
76  {
77  threads.reserve(num_queues);
78  }
79 
81  {
82  // This should only happen after exit has been
83  // called. Subordinate event queues should normally (assuming
84  // exit is called from Python) be waiting on the barrier when
85  // this happens.
86  //
87  // N.B.: Not terminating here would make it impossible to
88  // safely destroy the barrier.
90  }
91 
93  {
94  assert(!terminate);
95 
96  // Start subordinate threads if needed.
97  if (threads.empty()) {
98  // the main thread (the one running Python) handles queue 0,
99  // so we only need to allocate new threads for queues 1..N-1.
100  // We'll call these the "subordinate" threads.
101  for (uint32_t i = 1; i < numQueues; i++) {
102  threads.emplace_back(
103  [this](EventQueue *eq) {
104  thread_main(eq);
105  }, mainEventQueue[i]);
106  }
107  }
108 
109  // This method is called from the main thread. All subordinate
110  // threads should be waiting on the barrier when the function
111  // is called. The arrival of the main thread here will satisfy
112  // the barrier and start another iteration in the thread loop.
113  barrier.wait();
114  }
115 
116  void
118  {
119  assert(!terminate);
120  if (threads.empty())
121  return;
122 
123  /* This function should only be called when the simulator is
124  * handling a global exit event (typically from Python). This
125  * means that the helper threads will be waiting on the
126  * barrier. Tell the helper threads to exit and release them from
127  * their barrier. */
128  terminate = true;
129  barrier.wait();
130 
131  /* Wait for all of the threads to terminate */
132  for (auto &t : threads) {
133  t.join();
134  }
135 
136  terminate = false;
137  threads.clear();
138  }
139 
140  protected:
149  void
151  {
152  /* Wait for all initialisation to complete */
153  barrier.wait();
154 
155  while (!terminate) {
156  doSimLoop(queue);
157  barrier.wait();
158  }
159  }
160 
161  std::atomic<bool> terminate;
162  uint32_t numQueues;
165 };
166 
167 static std::unique_ptr<SimulatorThreads> simulatorThreads;
168 
170 {
172  {
173  if (!event)
174  return;
175 
176  event->deschedule();
177  delete event;
178  }
179 };
180 
188 simulate(Tick num_cycles)
189 {
190  if (global_exit_event)//cleaning last global exit event
192  std::unique_ptr<GlobalSyncEvent, DescheduleDeleter> quantum_event;
193 
194  inform("Entering event queue @ %d. Starting simulation...\n", curTick());
195 
196  if (!simulatorThreads)
198 
199  if (!simulate_limit_event) {
200  // If the simulate_limit_event is not set, we set it to MaxTick.
202  }
203 
204  if (num_cycles != -1) {
205  // If the user has specified an exit event after X cycles, do so here.
206  // Note: This will override any prior set max_tick behaviour (such as
207  // that above when it is set to MAxTick).
208  const Tick max_tick = num_cycles < MaxTick - curTick() ?
209  curTick() + num_cycles : MaxTick;
210 
211  // This is kept to `set_max_tick` instead of `schedule_tick_exit` to
212  // preserve backwards functionality. It may be better to deprecate this
213  // behaviour at some point in favor of `schedule_tick_exit`.
214  set_max_tick(max_tick);
215  }
216 
217  if (numMainEventQueues > 1) {
218  fatal_if(simQuantum == 0,
219  "Quantum for multi-eventq simulation not specified");
220 
221  quantum_event.reset(
224 
225  inParallelMode = true;
226  }
227 
228  simulatorThreads->runUntilLocalExit();
229  Event *local_event = doSimLoop(mainEventQueue[0]);
230  assert(local_event);
231 
232  inParallelMode = false;
233 
234  // locate the global exit event and return it to Python
235  BaseGlobalEvent *global_event = local_event->globalEvent();
236  assert(global_event);
237 
239  dynamic_cast<GlobalSimLoopExitEvent *>(global_event);
240  assert(global_exit_event);
241 
242  return global_exit_event;
243 }
244 
245 void set_max_tick(Tick tick)
246 {
247  if (!simulate_limit_event) {
249  mainEventQueue[0]->getCurTick(),
250  "simulate() limit reached", 0);
251  }
253 }
254 
255 
257 {
258  if (!simulate_limit_event) {
259  /* If the GlobalSimLoopExitEvent has not been setup, the maximum tick
260  * is `MaxTick` as declared in "src/base/types.hh".
261  */
262  return MaxTick;
263  }
264 
265  return simulate_limit_event->when();
266 }
267 
268 void
270 {
271  simulatorThreads->terminateThreads();
272 }
273 
274 
280 Event *
282 {
283  // set the per thread current eventq pointer
284  curEventQueue(eventq);
285  eventq->handleAsyncInsertions();
286 
287  bool mainQueue = eventq == getEventQueue(0);
288 
289  while (1) {
290  // there should always be at least one event (the SimLoopExitEvent
291  // we just scheduled) in the queue
292  assert(!eventq->empty());
293  assert(curTick() <= eventq->nextTick() &&
294  "event scheduled in the past");
295 
296  if (mainQueue && async_event) {
297  async_event = false;
298  // Take the event queue lock in case any of the service
299  // routines want to schedule new events.
300  std::lock_guard<EventQueue> lock(*eventq);
303  async_statdump = false;
304  async_statreset = false;
305  }
306 
307  if (async_io) {
308  async_io = false;
309  pollQueue.service();
310  }
311 
312  if (async_exit) {
313  async_exit = false;
314  exitSimLoop("user interrupt received");
315  }
316 
317  if (async_exception) {
318  async_exception = false;
319  return NULL;
320  }
321  }
322 
323  Event *exit_event = eventq->serviceOne();
324  if (exit_event != NULL) {
325  return exit_event;
326  }
327  }
328 
329  // not reached... only exit is return on SimLoopExitEvent
330 }
331 
332 } // namespace gem5
gem5::GlobalSyncEvent
A special global event that synchronizes all threads and forces them to process asynchronously enqueu...
Definition: global_event.hh:210
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:269
gem5::Barrier::wait
bool wait()
Definition: barrier.hh:66
gem5::global_exit_event
GlobalSimLoopExitEvent * global_exit_event
Simulate for num_cycles additional cycles.
Definition: simulate.cc:186
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:164
simulate.hh
gem5::MipsISA::event
Bitfield< 10, 5 > event
Definition: pra_constants.hh:300
gem5::getEventQueue
EventQueue * getEventQueue(uint32_t index)
Function for returning eventq queue for the provided index.
Definition: eventq.cc:62
gem5::SimulatorThreads::terminate
std::atomic< bool > terminate
Definition: simulate.cc:161
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:171
gem5::set_max_tick
void set_max_tick(Tick tick)
Set the maximum tick.
Definition: simulate.cc:245
std::vector< std::thread >
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:67
sim_exit.hh
gem5::GlobalSimLoopExitEvent::clean
virtual void clean()
Definition: sim_events.hh:72
gem5::EventBase::Progress_Event_Pri
static const Priority Progress_Event_Pri
Progress events come at the end.
Definition: eventq.hh:229
gem5::SimulatorThreads::runUntilLocalExit
void runUntilLocalExit()
Definition: simulate.cc:92
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:281
gem5::SimulatorThreads::numQueues
uint32_t numQueues
Definition: simulate.cc:162
gem5::EventQueue::handleAsyncInsertions
void handleAsyncInsertions()
Function for moving events from the async_queue to the main queue.
Definition: eventq.cc:458
gem5::SimulatorThreads
Definition: simulate.cc:65
gem5::BaseGlobalEvent
Common base class for GlobalEvent and GlobalSyncEvent.
Definition: global_event.hh:63
gem5::get_max_tick
Tick get_max_tick()
Get the maximum simulation tick.
Definition: simulate.cc:256
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:254
gem5::SimulatorThreads::~SimulatorThreads
~SimulatorThreads()
Definition: simulate.cc:80
gem5::Tick
uint64_t Tick
Tick count type.
Definition: types.hh:58
pollevent.hh
gem5::EventQueue::nextTick
Tick nextTick() const
Definition: eventq.hh:836
gem5::DescheduleDeleter
Definition: simulate.cc:169
gem5::EventQueue
Queue of events sorted in time order.
Definition: eventq.hh:615
gem5::Event::globalEvent
virtual BaseGlobalEvent * globalEvent()
If this is part of a GlobalEvent, return the pointer to the Global Event.
Definition: eventq.hh:513
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:891
gem5::SimulatorThreads::terminateThreads
void terminateThreads()
Definition: simulate.cc:117
gem5::BaseGlobalEvent::when
Tick when() const
Definition: global_event.hh:139
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)
Definition: simulate.cc:188
inform
#define inform(...)
Definition: logging.hh:257
gem5::curEventQueue
EventQueue * curEventQueue()
Definition: eventq.hh:91
types.hh
gem5::PowerISA::eq
Bitfield< 29 > eq
Definition: misc.hh:58
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:150
logging.hh
gem5::SimulatorThreads::threads
std::vector< std::thread > threads
Definition: simulate.cc:163
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:236
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:224
gem5::simulatorThreads
static std::unique_ptr< SimulatorThreads > simulatorThreads
Definition: simulate.cc:167
gem5::statistics::schedStatEvent
void schedStatEvent(bool dump, bool reset, Tick when, Tick repeat)
Schedule statistics dumping.
Definition: stat_control.cc:106
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:63
gem5::SimulatorThreads::SimulatorThreads
SimulatorThreads(uint32_t num_queues)
Definition: simulate.cc:72
eventq.hh

Generated on Sun Jul 30 2023 01:57:00 for gem5 by doxygen 1.8.17