scheduler.cc (13488:2e12afaa6cc7) scheduler.cc (13701:d84e5d2979a7)
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 * Authors: Gabe Black
28 */
29
30#include "systemc/core/scheduler.hh"
31
32#include "base/fiber.hh"
33#include "base/logging.hh"
34#include "sim/eventq.hh"
35#include "systemc/core/kernel.hh"
36#include "systemc/core/sc_main_fiber.hh"
37#include "systemc/ext/core/messages.hh"
38#include "systemc/ext/core/sc_main.hh"
39#include "systemc/ext/utils/sc_report.hh"
40#include "systemc/ext/utils/sc_report_handler.hh"
41#include "systemc/utils/report.hh"
42#include "systemc/utils/tracefile.hh"
43
44namespace sc_gem5
45{
46
47Scheduler::Scheduler() :
48 eq(nullptr), readyEvent(this, false, ReadyPriority),
49 pauseEvent(this, false, PausePriority),
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 * Authors: Gabe Black
28 */
29
30#include "systemc/core/scheduler.hh"
31
32#include "base/fiber.hh"
33#include "base/logging.hh"
34#include "sim/eventq.hh"
35#include "systemc/core/kernel.hh"
36#include "systemc/core/sc_main_fiber.hh"
37#include "systemc/ext/core/messages.hh"
38#include "systemc/ext/core/sc_main.hh"
39#include "systemc/ext/utils/sc_report.hh"
40#include "systemc/ext/utils/sc_report_handler.hh"
41#include "systemc/utils/report.hh"
42#include "systemc/utils/tracefile.hh"
43
44namespace sc_gem5
45{
46
47Scheduler::Scheduler() :
48 eq(nullptr), readyEvent(this, false, ReadyPriority),
49 pauseEvent(this, false, PausePriority),
50 stopEvent(this, false, StopPriority), _throwToScMain(nullptr),
50 stopEvent(this, false, StopPriority), _throwUp(nullptr),
51 starvationEvent(this, false, StarvationPriority),
52 _elaborationDone(false), _started(false), _stopNow(false),
53 _status(StatusOther), maxTickEvent(this, false, MaxTickPriority),
54 timeAdvancesEvent(this, false, TimeAdvancesPriority), _numCycles(0),
55 _changeStamp(0), _current(nullptr), initDone(false), runOnce(false)
56{}
57
58Scheduler::~Scheduler()
59{
60 // Clear out everything that belongs to us to make sure nobody tries to
61 // clear themselves out after the scheduler goes away.
62 clear();
63}
64
65void
66Scheduler::clear()
67{
68 // Delta notifications.
69 while (!deltas.empty())
70 deltas.front()->deschedule();
71
72 // Timed notifications.
73 for (auto &tsp: timeSlots) {
74 TimeSlot *&ts = tsp.second;
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())
83 deschedule(&readyEvent);
84 if (pauseEvent.scheduled())
85 deschedule(&pauseEvent);
86 if (stopEvent.scheduled())
87 deschedule(&stopEvent);
88 if (starvationEvent.scheduled())
89 deschedule(&starvationEvent);
90 if (maxTickEvent.scheduled())
91 deschedule(&maxTickEvent);
92 if (timeAdvancesEvent.scheduled())
93 deschedule(&timeAdvancesEvent);
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
108void
109Scheduler::initPhase()
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()) {
118 SC_REPORT_WARNING(sc_core::SC_ID_DISABLE_WILL_ORPHAN_PROCESS_,
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())
134 scheduleStarvationEvent();
135 kernel->status(::sc_core::SC_RUNNING);
136 }
137
138 initDone = true;
139
140 status(StatusOther);
141
142 scheduleTimeAdvancesEvent();
143}
144
145void
146Scheduler::reg(Process *p)
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.
155 initList.pushLast(p);
156 }
157}
158
159void
160Scheduler::yield()
161{
162 // Pull a process from the active list.
163 _current = getNextReady();
164 if (!_current) {
165 // There are no more processes, so return control to evaluate.
166 Fiber::primaryFiber()->run();
167 } else {
168 _current->popListNode();
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())
179 _current->resetEvent().notify();
180 try {
181 _current->run();
182 } catch (...) {
51 starvationEvent(this, false, StarvationPriority),
52 _elaborationDone(false), _started(false), _stopNow(false),
53 _status(StatusOther), maxTickEvent(this, false, MaxTickPriority),
54 timeAdvancesEvent(this, false, TimeAdvancesPriority), _numCycles(0),
55 _changeStamp(0), _current(nullptr), initDone(false), runOnce(false)
56{}
57
58Scheduler::~Scheduler()
59{
60 // Clear out everything that belongs to us to make sure nobody tries to
61 // clear themselves out after the scheduler goes away.
62 clear();
63}
64
65void
66Scheduler::clear()
67{
68 // Delta notifications.
69 while (!deltas.empty())
70 deltas.front()->deschedule();
71
72 // Timed notifications.
73 for (auto &tsp: timeSlots) {
74 TimeSlot *&ts = tsp.second;
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())
83 deschedule(&readyEvent);
84 if (pauseEvent.scheduled())
85 deschedule(&pauseEvent);
86 if (stopEvent.scheduled())
87 deschedule(&stopEvent);
88 if (starvationEvent.scheduled())
89 deschedule(&starvationEvent);
90 if (maxTickEvent.scheduled())
91 deschedule(&maxTickEvent);
92 if (timeAdvancesEvent.scheduled())
93 deschedule(&timeAdvancesEvent);
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
108void
109Scheduler::initPhase()
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()) {
118 SC_REPORT_WARNING(sc_core::SC_ID_DISABLE_WILL_ORPHAN_PROCESS_,
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())
134 scheduleStarvationEvent();
135 kernel->status(::sc_core::SC_RUNNING);
136 }
137
138 initDone = true;
139
140 status(StatusOther);
141
142 scheduleTimeAdvancesEvent();
143}
144
145void
146Scheduler::reg(Process *p)
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.
155 initList.pushLast(p);
156 }
157}
158
159void
160Scheduler::yield()
161{
162 // Pull a process from the active list.
163 _current = getNextReady();
164 if (!_current) {
165 // There are no more processes, so return control to evaluate.
166 Fiber::primaryFiber()->run();
167 } else {
168 _current->popListNode();
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())
179 _current->resetEvent().notify();
180 try {
181 _current->run();
182 } catch (...) {
183 throwToScMain();
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
198void
199Scheduler::ready(Process *p)
200{
201 if (_stopNow)
202 return;
203
204 p->scheduled(true);
205
206 if (p->procKind() == ::sc_core::SC_METHOD_PROC_)
207 readyListMethods.pushLast(p);
208 else
209 readyListThreads.pushLast(p);
210
211 if (!inEvaluate())
212 scheduleReadyEvent();
213}
214
215void
216Scheduler::resume(Process *p)
217{
218 if (initDone)
219 ready(p);
220 else
221 initList.pushLast(p);
222}
223
224bool
225listContains(ListNode *list, ListNode *target)
226{
227 ListNode *n = list->nextListNode;
228 while (n != list)
229 if (n == target)
230 return true;
231 return false;
232}
233
234bool
235Scheduler::suspend(Process *p)
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
249void
250Scheduler::requestUpdate(Channel *c)
251{
252 updateList.pushLast(c);
253 if (!inEvaluate())
254 scheduleReadyEvent();
255}
256
257void
258Scheduler::scheduleReadyEvent()
259{
260 // Schedule the evaluate and update phases.
261 if (!readyEvent.scheduled()) {
262 schedule(&readyEvent);
263 if (starvationEvent.scheduled())
264 deschedule(&starvationEvent);
265 }
266}
267
268void
269Scheduler::scheduleStarvationEvent()
270{
271 if (!starvationEvent.scheduled()) {
272 schedule(&starvationEvent);
273 if (readyEvent.scheduled())
274 deschedule(&readyEvent);
275 }
276}
277
278void
279Scheduler::runReady()
280{
281 scheduleTimeAdvancesEvent();
282
283 bool empty = readyListMethods.empty() && readyListThreads.empty();
284 lastReadyTick = getCurTick();
285
286 // The evaluation phase.
287 status(StatusEvaluate);
288 do {
289 yield();
290 } while (getNextReady());
291 _current = nullptr;
292
293 if (!empty) {
294 _numCycles++;
295 _changeStamp++;
296 }
297
298 if (_stopNow) {
299 status(StatusOther);
300 return;
301 }
302
303 runUpdate();
304 if (!traceFiles.empty())
305 trace(true);
306 runDelta();
307
308 if (!runToTime && starved())
309 scheduleStarvationEvent();
310
311 if (runOnce)
312 schedulePause();
313
314 status(StatusOther);
315}
316
317void
318Scheduler::runUpdate()
319{
320 status(StatusUpdate);
321
322 try {
323 Channel *channel = updateList.getNext();
324 while (channel) {
325 channel->popListNode();
326 channel->update();
327 channel = updateList.getNext();
328 }
329 } catch (...) {
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
198void
199Scheduler::ready(Process *p)
200{
201 if (_stopNow)
202 return;
203
204 p->scheduled(true);
205
206 if (p->procKind() == ::sc_core::SC_METHOD_PROC_)
207 readyListMethods.pushLast(p);
208 else
209 readyListThreads.pushLast(p);
210
211 if (!inEvaluate())
212 scheduleReadyEvent();
213}
214
215void
216Scheduler::resume(Process *p)
217{
218 if (initDone)
219 ready(p);
220 else
221 initList.pushLast(p);
222}
223
224bool
225listContains(ListNode *list, ListNode *target)
226{
227 ListNode *n = list->nextListNode;
228 while (n != list)
229 if (n == target)
230 return true;
231 return false;
232}
233
234bool
235Scheduler::suspend(Process *p)
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
249void
250Scheduler::requestUpdate(Channel *c)
251{
252 updateList.pushLast(c);
253 if (!inEvaluate())
254 scheduleReadyEvent();
255}
256
257void
258Scheduler::scheduleReadyEvent()
259{
260 // Schedule the evaluate and update phases.
261 if (!readyEvent.scheduled()) {
262 schedule(&readyEvent);
263 if (starvationEvent.scheduled())
264 deschedule(&starvationEvent);
265 }
266}
267
268void
269Scheduler::scheduleStarvationEvent()
270{
271 if (!starvationEvent.scheduled()) {
272 schedule(&starvationEvent);
273 if (readyEvent.scheduled())
274 deschedule(&readyEvent);
275 }
276}
277
278void
279Scheduler::runReady()
280{
281 scheduleTimeAdvancesEvent();
282
283 bool empty = readyListMethods.empty() && readyListThreads.empty();
284 lastReadyTick = getCurTick();
285
286 // The evaluation phase.
287 status(StatusEvaluate);
288 do {
289 yield();
290 } while (getNextReady());
291 _current = nullptr;
292
293 if (!empty) {
294 _numCycles++;
295 _changeStamp++;
296 }
297
298 if (_stopNow) {
299 status(StatusOther);
300 return;
301 }
302
303 runUpdate();
304 if (!traceFiles.empty())
305 trace(true);
306 runDelta();
307
308 if (!runToTime && starved())
309 scheduleStarvationEvent();
310
311 if (runOnce)
312 schedulePause();
313
314 status(StatusOther);
315}
316
317void
318Scheduler::runUpdate()
319{
320 status(StatusUpdate);
321
322 try {
323 Channel *channel = updateList.getNext();
324 while (channel) {
325 channel->popListNode();
326 channel->update();
327 channel = updateList.getNext();
328 }
329 } catch (...) {
330 throwToScMain();
330 throwUp();
331 }
332}
333
334void
335Scheduler::runDelta()
336{
337 status(StatusDelta);
338
339 try {
340 while (!deltas.empty())
341 deltas.back()->run();
342 } catch (...) {
331 }
332}
333
334void
335Scheduler::runDelta()
336{
337 status(StatusDelta);
338
339 try {
340 while (!deltas.empty())
341 deltas.back()->run();
342 } catch (...) {
343 throwToScMain();
343 throwUp();
344 }
345}
346
347void
348Scheduler::pause()
349{
350 status(StatusPaused);
351 kernel->status(::sc_core::SC_PAUSED);
352 runOnce = false;
353 if (scMainFiber.called() && !scMainFiber.finished())
354 scMainFiber.run();
355}
356
357void
358Scheduler::stop()
359{
360 status(StatusStopped);
361 kernel->stop();
362
363 clear();
364
365 runOnce = false;
366 if (scMainFiber.called() && !scMainFiber.finished())
367 scMainFiber.run();
368}
369
370void
371Scheduler::start(Tick max_tick, bool run_to_time)
372{
373 _started = true;
374 status(StatusOther);
375 runToTime = run_to_time;
376
377 maxTick = max_tick;
378 lastReadyTick = getCurTick();
379
380 if (initDone) {
381 if (!runToTime && starved())
382 scheduleStarvationEvent();
383 kernel->status(::sc_core::SC_RUNNING);
384 }
385
386 schedule(&maxTickEvent, maxTick);
387 scheduleTimeAdvancesEvent();
388
389 // Return to gem5 to let it run events, etc.
390 Fiber::primaryFiber()->run();
391
392 if (pauseEvent.scheduled())
393 deschedule(&pauseEvent);
394 if (stopEvent.scheduled())
395 deschedule(&stopEvent);
396 if (maxTickEvent.scheduled())
397 deschedule(&maxTickEvent);
398 if (starvationEvent.scheduled())
399 deschedule(&starvationEvent);
400
344 }
345}
346
347void
348Scheduler::pause()
349{
350 status(StatusPaused);
351 kernel->status(::sc_core::SC_PAUSED);
352 runOnce = false;
353 if (scMainFiber.called() && !scMainFiber.finished())
354 scMainFiber.run();
355}
356
357void
358Scheduler::stop()
359{
360 status(StatusStopped);
361 kernel->stop();
362
363 clear();
364
365 runOnce = false;
366 if (scMainFiber.called() && !scMainFiber.finished())
367 scMainFiber.run();
368}
369
370void
371Scheduler::start(Tick max_tick, bool run_to_time)
372{
373 _started = true;
374 status(StatusOther);
375 runToTime = run_to_time;
376
377 maxTick = max_tick;
378 lastReadyTick = getCurTick();
379
380 if (initDone) {
381 if (!runToTime && starved())
382 scheduleStarvationEvent();
383 kernel->status(::sc_core::SC_RUNNING);
384 }
385
386 schedule(&maxTickEvent, maxTick);
387 scheduleTimeAdvancesEvent();
388
389 // Return to gem5 to let it run events, etc.
390 Fiber::primaryFiber()->run();
391
392 if (pauseEvent.scheduled())
393 deschedule(&pauseEvent);
394 if (stopEvent.scheduled())
395 deschedule(&stopEvent);
396 if (maxTickEvent.scheduled())
397 deschedule(&maxTickEvent);
398 if (starvationEvent.scheduled())
399 deschedule(&starvationEvent);
400
401 if (_throwToScMain) {
402 const ::sc_core::sc_report *to_throw = _throwToScMain;
403 _throwToScMain = nullptr;
401 if (_throwUp) {
402 const ::sc_core::sc_report *to_throw = _throwUp;
403 _throwUp = nullptr;
404 throw *to_throw;
405 }
406}
407
408void
409Scheduler::oneCycle()
410{
411 runOnce = true;
412 scheduleReadyEvent();
413 start(::MaxTick, false);
414}
415
416void
417Scheduler::schedulePause()
418{
419 if (pauseEvent.scheduled())
420 return;
421
422 schedule(&pauseEvent);
423}
424
425void
404 throw *to_throw;
405 }
406}
407
408void
409Scheduler::oneCycle()
410{
411 runOnce = true;
412 scheduleReadyEvent();
413 start(::MaxTick, false);
414}
415
416void
417Scheduler::schedulePause()
418{
419 if (pauseEvent.scheduled())
420 return;
421
422 schedule(&pauseEvent);
423}
424
425void
426Scheduler::throwToScMain()
426Scheduler::throwUp()
427{
427{
428 ::sc_core::sc_report report = reportifyException();
429 _throwToScMain = &report;
430 status(StatusOther);
431 scMainFiber.run();
428 if (scMainFiber.called() && !scMainFiber.finished()) {
429 ::sc_core::sc_report report = reportifyException();
430 _throwUp = &report;
431 status(StatusOther);
432 scMainFiber.run();
433 } else {
434 reportHandlerProc(reportifyException(),
435 ::sc_core::sc_report_handler::get_catch_actions());
436 }
432}
433
434void
435Scheduler::scheduleStop(bool finish_delta)
436{
437 if (stopEvent.scheduled())
438 return;
439
440 if (!finish_delta) {
441 _stopNow = true;
442 // If we're not supposed to finish the delta cycle, flush all
443 // pending activity.
444 clear();
445 }
446 schedule(&stopEvent);
447}
448
449void
450Scheduler::trace(bool delta)
451{
452 for (auto tf: traceFiles)
453 tf->trace(delta);
454}
455
456Scheduler scheduler;
457Process *getCurrentProcess() { return scheduler.current(); }
458
459namespace {
460
461void
462throwingReportHandler(const ::sc_core::sc_report &r,
463 const ::sc_core::sc_actions &)
464{
465 throw r;
466}
467
468} // anonymous namespace
469
470const ::sc_core::sc_report
471reportifyException()
472{
473 ::sc_core::sc_report_handler_proc old_handler = reportHandlerProc;
474 ::sc_core::sc_report_handler::set_handler(&throwingReportHandler);
475
476 try {
477 try {
478 // Rethrow the current exception so we can catch it and throw an
479 // sc_report instead if it's not a type we recognize/can handle.
480 throw;
481 } catch (const ::sc_core::sc_report &) {
482 // It's already a sc_report, so nothing to do.
483 throw;
484 } catch (const ::sc_core::sc_unwind_exception &) {
485 panic("Kill/reset exception escaped a Process::run()");
486 } catch (const std::exception &e) {
487 SC_REPORT_ERROR(
488 sc_core::SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, e.what());
489 } catch (const char *msg) {
490 SC_REPORT_ERROR(
491 sc_core::SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, msg);
492 } catch (...) {
493 SC_REPORT_ERROR(
494 sc_core::SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_,
495 "UNKNOWN EXCEPTION");
496 }
497 } catch (const ::sc_core::sc_report &r) {
498 ::sc_core::sc_report_handler::set_handler(old_handler);
499 return r;
500 }
501 panic("No exception thrown in reportifyException.");
502}
503
504} // namespace sc_gem5
437}
438
439void
440Scheduler::scheduleStop(bool finish_delta)
441{
442 if (stopEvent.scheduled())
443 return;
444
445 if (!finish_delta) {
446 _stopNow = true;
447 // If we're not supposed to finish the delta cycle, flush all
448 // pending activity.
449 clear();
450 }
451 schedule(&stopEvent);
452}
453
454void
455Scheduler::trace(bool delta)
456{
457 for (auto tf: traceFiles)
458 tf->trace(delta);
459}
460
461Scheduler scheduler;
462Process *getCurrentProcess() { return scheduler.current(); }
463
464namespace {
465
466void
467throwingReportHandler(const ::sc_core::sc_report &r,
468 const ::sc_core::sc_actions &)
469{
470 throw r;
471}
472
473} // anonymous namespace
474
475const ::sc_core::sc_report
476reportifyException()
477{
478 ::sc_core::sc_report_handler_proc old_handler = reportHandlerProc;
479 ::sc_core::sc_report_handler::set_handler(&throwingReportHandler);
480
481 try {
482 try {
483 // Rethrow the current exception so we can catch it and throw an
484 // sc_report instead if it's not a type we recognize/can handle.
485 throw;
486 } catch (const ::sc_core::sc_report &) {
487 // It's already a sc_report, so nothing to do.
488 throw;
489 } catch (const ::sc_core::sc_unwind_exception &) {
490 panic("Kill/reset exception escaped a Process::run()");
491 } catch (const std::exception &e) {
492 SC_REPORT_ERROR(
493 sc_core::SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, e.what());
494 } catch (const char *msg) {
495 SC_REPORT_ERROR(
496 sc_core::SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, msg);
497 } catch (...) {
498 SC_REPORT_ERROR(
499 sc_core::SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_,
500 "UNKNOWN EXCEPTION");
501 }
502 } catch (const ::sc_core::sc_report &r) {
503 ::sc_core::sc_report_handler::set_handler(old_handler);
504 return r;
505 }
506 panic("No exception thrown in reportifyException.");
507}
508
509} // namespace sc_gem5