gem5  v22.1.0.0
scheduler.cc
Go to the documentation of this file.
1 /*
2  * Copyright 2018 Google, Inc.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met: redistributions of source code must retain the above copyright
7  * notice, this list of conditions and the following disclaimer;
8  * redistributions in binary form must reproduce the above copyright
9  * notice, this list of conditions and the following disclaimer in the
10  * documentation and/or other materials provided with the distribution;
11  * neither the name of the copyright holders nor the names of its
12  * contributors may be used to endorse or promote products derived from
13  * this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
29 
30 #include "base/fiber.hh"
31 #include "base/logging.hh"
32 #include "sim/eventq.hh"
33 #include "sim/sim_exit.hh"
34 #include "systemc/core/kernel.hh"
40 #include "systemc/utils/report.hh"
42 
43 namespace sc_gem5
44 {
45 
47  eq(nullptr), readyEvent(this, false, ReadyPriority),
48  pauseEvent(this, false, PausePriority),
49  stopEvent(this, false, StopPriority), _throwUp(nullptr),
50  starvationEvent(this, false, StarvationPriority),
51  _elaborationDone(false), _started(false), _stopNow(false),
52  _status(StatusOther), maxTick(gem5::MaxTick),
53  maxTickEvent(this, false, MaxTickPriority),
54  timeAdvancesEvent(this, false, TimeAdvancesPriority), _numCycles(0),
55  _changeStamp(0), _current(nullptr), initDone(false), runToTime(true),
56  runOnce(false)
57 {}
58 
60 {
61  // Clear out everything that belongs to us to make sure nobody tries to
62  // clear themselves out after the scheduler goes away.
63  clear();
64 }
65 
66 void
68 {
69  // Delta notifications.
70  while (!deltas.empty())
71  deltas.front()->deschedule();
72 
73  // Timed notifications.
74  for (auto &ts: timeSlots) {
75  while (!ts->events.empty())
76  ts->events.front()->deschedule();
77  deschedule(ts);
78  }
79  timeSlots.clear();
80 
81  // gem5 events.
82  if (readyEvent.scheduled())
84  if (pauseEvent.scheduled())
86  if (stopEvent.scheduled())
88  if (starvationEvent.scheduled())
90  if (maxTickEvent.scheduled())
92  if (timeAdvancesEvent.scheduled())
94 
95  Process *p;
96  while ((p = initList.getNext()))
97  p->popListNode();
98  while ((p = readyListMethods.getNext()))
99  p->popListNode();
100  while ((p = readyListThreads.getNext()))
101  p->popListNode();
102 
103  Channel *c;
104  while ((c = updateList.getNext()))
105  c->popListNode();
106 }
107 
108 void
110 {
111  runUpdate();
112 
113  for (Process *p = initList.getNext(); p; p = initList.getNext()) {
114  p->popListNode();
115 
116  if (p->dontInitialize()) {
117  if (!p->hasStaticSensitivities() && !p->internal()) {
119  p->name());
120  }
121  } else {
122  p->ready();
123  }
124  }
125 
126  runDelta();
127 
128  for (auto ets: eventsToSchedule)
129  eq->schedule(ets.first, ets.second);
130  eventsToSchedule.clear();
131 
132  if (_started) {
133  if (!runToTime && starved())
136  }
137 
138  initDone = true;
139 
141 
143 }
144 
145 void
147 {
148  if (initDone) {
149  // If not marked as dontInitialize, mark as ready.
150  if (!p->dontInitialize())
151  p->ready();
152  } else {
153  // Otherwise, record that this process should be initialized once we
154  // get there.
156  }
157 }
158 
159 void
161 {
162  // Pull a process from the active list.
164  if (!_current) {
165  // There are no more processes, so return control to evaluate.
167  } else {
169  _current->scheduled(false);
170  // Switch to whatever Fiber is supposed to run this process. All
171  // Fibers which aren't running should be parked at this line.
172  _current->fiber()->run();
173  // If the current process needs to be manually started, start it.
174  if (_current && _current->needsStart()) {
175  _current->needsStart(false);
176  // If a process hasn't started yet, "resetting" it just starts it
177  // and signals its reset event.
178  if (_current->inReset())
180  try {
181  _current->run();
182  } catch (...) {
183  throwUp();
184  }
185  }
186  }
187  if (_current && !_current->needsStart()) {
188  if (_current->excWrapper) {
189  auto ew = _current->excWrapper;
190  _current->excWrapper = nullptr;
191  ew->throw_it();
192  } else if (_current->inReset()) {
193  _current->reset(false);
194  }
195  }
196 }
197 
198 void
200 {
201  if (_stopNow)
202  return;
203 
204  p->scheduled(true);
205 
206  if (p->procKind() == ::sc_core::SC_METHOD_PROC_)
208  else
210 
211  if (!inEvaluate())
213 }
214 
215 void
217 {
218  if (initDone)
219  ready(p);
220  else
222 }
223 
224 bool
226 {
227  ListNode *n = list->nextListNode;
228  while (n != list)
229  if (n == target)
230  return true;
231  return false;
232 }
233 
234 bool
236 {
237  bool was_ready;
238  if (initDone) {
239  // After initialization, check if we're on a ready list.
240  was_ready = (p->nextListNode != nullptr);
241  p->popListNode();
242  } else {
243  // Nothing is ready before init.
244  was_ready = false;
245  }
246  return was_ready;
247 }
248 
249 void
251 {
253  if (!inEvaluate())
255 }
256 
257 void
259 {
260  std::lock_guard<std::mutex> lock(asyncListMutex);
262  hasAsyncUpdate = true;
263 }
264 
265 void
267 {
268  // Schedule the evaluate and update phases.
269  if (!readyEvent.scheduled()) {
271  if (starvationEvent.scheduled())
273  }
274 }
275 
276 void
278 {
279  if (!starvationEvent.scheduled()) {
281  if (readyEvent.scheduled())
283  }
284 }
285 
286 void
288 {
290 
291  bool empty = readyListMethods.empty() && readyListThreads.empty();
293 
294  // The evaluation phase.
296  do {
297  yield();
298  } while (getNextReady());
299  _current = nullptr;
300 
301  if (!empty) {
302  _numCycles++;
303  _changeStamp++;
304  }
305 
306  if (_stopNow) {
308  return;
309  }
310 
311  runUpdate();
312  if (!traceFiles.empty())
313  trace(true);
314  runDelta();
315 
316  if (!runToTime && starved())
318 
319  if (runOnce)
320  schedulePause();
321 
323 }
324 
325 void
327 {
329  if (hasAsyncUpdate) {
330  std::lock_guard<std::mutex> lock(asyncListMutex);
331  Channel *channel;
332  while ((channel = asyncUpdateList.getNext()) != nullptr)
333  updateList.pushLast(channel);
334  hasAsyncUpdate = false;
335  }
336 
337  try {
338  Channel *channel = updateList.getNext();
339  while (channel) {
340  channel->popListNode();
341  channel->update();
342  channel = updateList.getNext();
343  }
344  } catch (...) {
345  throwUp();
346  }
347 }
348 
349 void
351 {
353 
354  try {
355  while (!deltas.empty())
356  deltas.back()->run();
357  } catch (...) {
358  throwUp();
359  }
360 }
361 
362 void
364 {
365  using namespace gem5;
366 
369  runOnce = false;
370  if (scMainFiber.called()) {
371  if (!scMainFiber.finished())
372  scMainFiber.run();
373  } else {
374  if (scMainFiber.finished())
375  fatal("Pausing systemc after sc_main completed.");
376  else
377  gem5::exitSimLoopNow("systemc pause");
378  }
379 }
380 
381 void
383 {
384  using namespace gem5;
385 
387  kernel->stop();
388 
389  clear();
390 
391  runOnce = false;
392  if (scMainFiber.called()) {
393  if (!scMainFiber.finished())
394  scMainFiber.run();
395  } else {
396  if (scMainFiber.finished())
397  fatal("Stopping systemc after sc_main completed.");
398  else
399  gem5::exitSimLoopNow("systemc stop");
400  }
401 }
402 
403 void
404 Scheduler::start(gem5::Tick max_tick, bool run_to_time)
405 {
406  _started = true;
408  runToTime = run_to_time;
409 
410  maxTick = max_tick;
412 
413  if (initDone) {
414  if (!runToTime && starved())
417  }
418 
421 
422  // Return to gem5 to let it run events, etc.
424 
425  if (pauseEvent.scheduled())
427  if (stopEvent.scheduled())
429  if (maxTickEvent.scheduled())
431  if (starvationEvent.scheduled())
433 
434  if (_throwUp) {
435  const ::sc_core::sc_report *to_throw = _throwUp;
436  _throwUp = nullptr;
437  throw *to_throw;
438  }
439 }
440 
441 void
443 {
444  runOnce = true;
446  start(gem5::MaxTick, false);
447 }
448 
449 void
451 {
452  if (pauseEvent.scheduled())
453  return;
454 
456 }
457 
458 void
460 {
461  if (scMainFiber.called() && !scMainFiber.finished()) {
463  _throwUp = &report;
465  scMainFiber.run();
466  } else {
469  }
470 }
471 
472 void
473 Scheduler::scheduleStop(bool finish_delta)
474 {
475  if (stopEvent.scheduled())
476  return;
477 
478  if (!finish_delta) {
479  _stopNow = true;
480  // If we're not supposed to finish the delta cycle, flush all
481  // pending activity.
482  clear();
483  }
485 }
486 
487 void
488 Scheduler::trace(bool delta)
489 {
490  for (auto tf: traceFiles)
491  tf->trace(delta);
492 }
493 
496 
497 namespace {
498 
499 void
500 throwingReportHandler(const ::sc_core::sc_report &r,
502 {
503  throw r;
504 }
505 
506 } // anonymous namespace
507 
508 const ::sc_core::sc_report
510 {
512  ::sc_core::sc_report_handler::set_handler(&throwingReportHandler);
513 
514  try {
515  try {
516  // Rethrow the current exception so we can catch it and throw an
517  // sc_report instead if it's not a type we recognize/can handle.
518  throw;
519  } catch (const ::sc_core::sc_report &) {
520  // It's already a sc_report, so nothing to do.
521  throw;
522  } catch (const ::sc_core::sc_unwind_exception &) {
523  panic("Kill/reset exception escaped a Process::run()");
524  } catch (const std::exception &e) {
527  } catch (const char *msg) {
530  } catch (...) {
533  "UNKNOWN EXCEPTION");
534  }
535  } catch (const ::sc_core::sc_report &r) {
537  return r;
538  }
539  panic("No exception thrown in reportifyException.");
540 }
541 
542 } // namespace sc_gem5
static sc_actions get_catch_actions()
static void set_handler(sc_report_handler_proc)
void update()
Definition: channel.hh:48
static sc_core::sc_status status()
Definition: kernel.cc:54
static void stop()
Definition: kernel.cc:143
::sc_core::sc_event & resetEvent()
Definition: process.hh:101
bool scheduled() const
Definition: process.hh:73
virtual gem5::Fiber * fiber()
Definition: process.hh:121
bool inReset()
Definition: process.hh:131
void reset(bool inc_kids)
Definition: process.cc:169
ExceptionWrapperBase * excWrapper
Definition: process.hh:91
bool needsStart() const
Definition: process.hh:66
gem5::Tick getCurTick()
Definition: scheduler.hh:243
std::set< TraceFile * > traceFiles
Definition: scheduler.hh:538
gem5::EventWrapper< Scheduler, &Scheduler::pause > pauseEvent
Definition: scheduler.hh:473
void resume(Process *p)
Definition: scheduler.cc:216
ProcessList readyListMethods
Definition: scheduler.hh:527
uint64_t _changeStamp
Definition: scheduler.hh:517
bool suspend(Process *p)
Definition: scheduler.cc:235
gem5::EventWrapper< Scheduler, &Scheduler::stop > stopEvent
Definition: scheduler.hh:474
void trace(bool delta)
Definition: scheduler.cc:488
void start(gem5::Tick max_tick, bool run_to_time)
Definition: scheduler.cc:404
gem5::Tick lastReadyTick
Definition: scheduler.hh:497
void deschedule(ScEvent *event)
Definition: scheduler.hh:280
const ::sc_core::sc_report * _throwUp
Definition: scheduler.hh:476
gem5::EventWrapper< Scheduler, &Scheduler::runReady > readyEvent
Definition: scheduler.hh:468
std::mutex asyncListMutex
Definition: scheduler.hh:533
void scheduleStop(bool finish_delta)
Definition: scheduler.cc:473
ProcessList readyListThreads
Definition: scheduler.hh:528
std::map< gem5::Event *, gem5::Tick > eventsToSchedule
Definition: scheduler.hh:536
gem5::EventWrapper< Scheduler, &Scheduler::pause > starvationEvent
Definition: scheduler.hh:487
ChannelList asyncUpdateList
Definition: scheduler.hh:532
void asyncRequestUpdate(Channel *c)
Definition: scheduler.cc:258
void schedule(ScEvent *event, const ::sc_core::sc_time &delay)
Definition: scheduler.hh:253
Process * _current
Definition: scheduler.hh:519
std::atomic< bool > hasAsyncUpdate
Definition: scheduler.hh:534
void ready(Process *p)
Definition: scheduler.cc:199
TimeSlots timeSlots
Definition: scheduler.hh:457
void reg(Process *p)
Definition: scheduler.cc:146
Process * getNextReady()
Definition: scheduler.hh:461
void scheduleStarvationEvent()
Definition: scheduler.cc:277
void requestUpdate(Channel *c)
Definition: scheduler.cc:250
uint64_t _numCycles
Definition: scheduler.hh:516
gem5::EventWrapper< Scheduler, &Scheduler::maxTickFunc > maxTickEvent
Definition: scheduler.hh:505
Process * current()
Definition: scheduler.hh:185
void scheduleTimeAdvancesEvent()
Definition: scheduler.hh:510
gem5::EventQueue * eq
Definition: scheduler.hh:433
gem5::Tick maxTick
Definition: scheduler.hh:496
ChannelList updateList
Definition: scheduler.hh:530
void scheduleReadyEvent()
Definition: scheduler.cc:266
ProcessList initList
Definition: scheduler.hh:525
gem5::EventWrapper< Scheduler, &Scheduler::timeAdvances > timeAdvancesEvent
Definition: scheduler.hh:508
void schedule(Event *event, Tick when, bool global=false)
Schedule the given event on this queue.
Definition: eventq.hh:764
static Fiber * primaryFiber()
Get a pointer to the primary Fiber.
Definition: fiber.cc:186
bool finished() const
Returns whether the "main" function of this fiber has finished.
Definition: fiber.hh:109
void run()
Start executing the fiber represented by this object.
Definition: fiber.cc:166
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:178
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:190
Bitfield< 31 > n
Definition: misc_types.hh:462
Bitfield< 9 > e
Definition: misc_types.hh:65
Bitfield< 55, 52 > ts
Definition: misc_types.hh:93
Bitfield< 29 > eq
Definition: misc.hh:58
Bitfield< 5 > r
Definition: pagetable.hh:60
Bitfield< 2 > c
Definition: pagetable.hh:63
Bitfield< 54 > p
Definition: pagetable.hh:70
Bitfield< 5 > lock
Definition: types.hh:82
Bitfield< 8 > tf
Definition: misc.hh:574
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
uint64_t Tick
Tick count type.
Definition: types.hh:58
const Tick MaxTick
Definition: types.hh:60
void exitSimLoopNow(const std::string &message, int exit_code, Tick repeat, bool serialize)
Schedule an event as above, but make it high priority so it runs before any normal events which are s...
Definition: sim_events.cc:99
const char SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_[]
Definition: messages.cc:117
const char SC_ID_DISABLE_WILL_ORPHAN_PROCESS_[]
Definition: messages.cc:132
@ SC_RUNNING
Definition: sc_main.hh:87
@ SC_PAUSED
Definition: sc_main.hh:88
unsigned sc_actions
void(* sc_report_handler_proc)(const sc_report &, const sc_actions &)
static scfx_rep_node * list
Definition: scfx_rep.cc:336
sc_core::sc_report_handler_proc reportHandlerProc
Definition: report.cc:68
const ::sc_core::sc_report reportifyException()
Definition: scheduler.cc:509
ScMainFiber scMainFiber
Scheduler scheduler
Definition: scheduler.cc:494
Kernel * kernel
Definition: kernel.cc:184
Process * getCurrentProcess()
Definition: scheduler.cc:495
bool listContains(ListNode *list, ListNode *target)
Definition: scheduler.cc:225
#define SC_REPORT_WARNING(msg_type, msg)
#define SC_REPORT_ERROR(msg_type, msg)
void popListNode()
Definition: list.hh:51
bool empty()
Definition: list.hh:111
T * getNext()
Definition: list.hh:106
void pushLast(T *t)
Definition: list.hh:89

Generated on Wed Dec 21 2022 10:22:35 for gem5 by doxygen 1.9.1