scheduler.cc (13328:d5f4e801436a) scheduler.cc (13329:a2d273c8e667)
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/ext/core/messages.hh"
37#include "systemc/ext/core/sc_main.hh"
38#include "systemc/ext/utils/sc_report.hh"
39#include "systemc/ext/utils/sc_report_handler.hh"
40#include "systemc/utils/report.hh"
41#include "systemc/utils/tracefile.hh"
42
43namespace sc_gem5
44{
45
46Scheduler::Scheduler() :
47 eq(nullptr), readyEvent(this, false, ReadyPriority),
48 pauseEvent(this, false, PausePriority),
49 stopEvent(this, false, StopPriority),
50 scMain(nullptr), _throwToScMain(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 for (Process *p = initList.getNext(); p; p = initList.getNext()) {
112 p->popListNode();
113
114 if (p->dontInitialize()) {
115 if (!p->hasStaticSensitivities() && !p->internal()) {
116 SC_REPORT_WARNING(sc_core::SC_ID_DISABLE_WILL_ORPHAN_PROCESS_,
117 p->name());
118 }
119 } else {
120 p->ready();
121 }
122 }
123
124 runUpdate();
125 runDelta();
126
127 for (auto ets: eventsToSchedule)
128 eq->schedule(ets.first, ets.second);
129 eventsToSchedule.clear();
130
131 if (_started) {
132 if (!runToTime && starved())
133 scheduleStarvationEvent();
134 kernel->status(::sc_core::SC_RUNNING);
135 }
136
137 initDone = true;
138
139 status(StatusOther);
140
141 scheduleTimeAdvancesEvent();
142}
143
144void
145Scheduler::reg(Process *p)
146{
147 if (initDone) {
148 // If not marked as dontInitialize, mark as ready.
149 if (!p->dontInitialize())
150 p->ready();
151 } else {
152 // Otherwise, record that this process should be initialized once we
153 // get there.
154 initList.pushLast(p);
155 }
156}
157
158void
159Scheduler::yield()
160{
161 // Pull a process from the active list.
162 _current = getNextReady();
163 if (!_current) {
164 // There are no more processes, so return control to evaluate.
165 Fiber::primaryFiber()->run();
166 } else {
167 _current->popListNode();
168 _current->scheduled(false);
169 // Switch to whatever Fiber is supposed to run this process. All
170 // Fibers which aren't running should be parked at this line.
171 _current->fiber()->run();
172 // If the current process needs to be manually started, start it.
173 if (_current && _current->needsStart()) {
174 _current->needsStart(false);
175 // If a process hasn't started yet, "resetting" it just starts it
176 // and signals its reset event.
177 if (_current->inReset())
178 _current->resetEvent().notify();
179 try {
180 _current->run();
181 } catch (...) {
182 throwToScMain();
183 }
184 }
185 }
186 if (_current && !_current->needsStart()) {
187 if (_current->excWrapper) {
188 auto ew = _current->excWrapper;
189 _current->excWrapper = nullptr;
190 ew->throw_it();
191 } else if (_current->inReset()) {
192 _current->reset(false);
193 }
194 }
195}
196
197void
198Scheduler::ready(Process *p)
199{
200 if (_stopNow)
201 return;
202
203 p->scheduled(true);
204
205 if (p->procKind() == ::sc_core::SC_METHOD_PROC_)
206 readyListMethods.pushLast(p);
207 else
208 readyListThreads.pushLast(p);
209
210 if (!inEvaluate())
211 scheduleReadyEvent();
212}
213
214void
215Scheduler::resume(Process *p)
216{
217 if (initDone)
218 ready(p);
219 else
220 initList.pushLast(p);
221}
222
223bool
224listContains(ListNode *list, ListNode *target)
225{
226 ListNode *n = list->nextListNode;
227 while (n != list)
228 if (n == target)
229 return true;
230 return false;
231}
232
233bool
234Scheduler::suspend(Process *p)
235{
236 bool was_ready;
237 if (initDone) {
238 // After initialization, check if we're on a ready list.
239 was_ready = (p->nextListNode != nullptr);
240 p->popListNode();
241 } else {
242 // Nothing is ready before init.
243 was_ready = false;
244 }
245 return was_ready;
246}
247
248void
249Scheduler::requestUpdate(Channel *c)
250{
251 updateList.pushLast(c);
252 if (!inEvaluate())
253 scheduleReadyEvent();
254}
255
256void
257Scheduler::scheduleReadyEvent()
258{
259 // Schedule the evaluate and update phases.
260 if (!readyEvent.scheduled()) {
261 schedule(&readyEvent);
262 if (starvationEvent.scheduled())
263 deschedule(&starvationEvent);
264 }
265}
266
267void
268Scheduler::scheduleStarvationEvent()
269{
270 if (!starvationEvent.scheduled()) {
271 schedule(&starvationEvent);
272 if (readyEvent.scheduled())
273 deschedule(&readyEvent);
274 }
275}
276
277void
278Scheduler::runReady()
279{
280 scheduleTimeAdvancesEvent();
281
282 bool empty = readyListMethods.empty() && readyListThreads.empty();
283 lastReadyTick = getCurTick();
284
285 // The evaluation phase.
286 status(StatusEvaluate);
287 do {
288 yield();
289 } while (getNextReady());
290 _current = nullptr;
291
292 if (!empty) {
293 _numCycles++;
294 _changeStamp++;
295 }
296
297 if (_stopNow) {
298 status(StatusOther);
299 return;
300 }
301
302 runUpdate();
303 if (!traceFiles.empty())
304 trace(true);
305 runDelta();
306
307 if (!runToTime && starved())
308 scheduleStarvationEvent();
309
310 if (runOnce)
311 schedulePause();
312
313 status(StatusOther);
314}
315
316void
317Scheduler::runUpdate()
318{
319 status(StatusUpdate);
320
321 try {
322 Channel *channel = updateList.getNext();
323 while (channel) {
324 channel->popListNode();
325 channel->update();
326 channel = updateList.getNext();
327 }
328 } catch (...) {
329 throwToScMain();
330 }
331}
332
333void
334Scheduler::runDelta()
335{
336 status(StatusDelta);
337
338 try {
339 while (!deltas.empty())
340 deltas.back()->run();
341 } catch (...) {
342 throwToScMain();
343 }
344}
345
346void
347Scheduler::pause()
348{
349 status(StatusPaused);
350 kernel->status(::sc_core::SC_PAUSED);
351 runOnce = false;
352 if (scMain && !scMain->finished())
353 scMain->run();
354}
355
356void
357Scheduler::stop()
358{
359 status(StatusStopped);
360 kernel->stop();
361
362 clear();
363
364 runOnce = false;
365 if (scMain && !scMain->finished())
366 scMain->run();
367}
368
369void
370Scheduler::start(Tick max_tick, bool run_to_time)
371{
372 // We should be running from sc_main. Keep track of that Fiber to return
373 // to later.
374 scMain = Fiber::currentFiber();
375
376 _started = true;
377 status(StatusOther);
378 runToTime = run_to_time;
379
380 maxTick = max_tick;
381 lastReadyTick = getCurTick();
382
383 if (initDone) {
384 if (!runToTime && starved())
385 scheduleStarvationEvent();
386 kernel->status(::sc_core::SC_RUNNING);
387 }
388
389 schedule(&maxTickEvent, maxTick);
390 scheduleTimeAdvancesEvent();
391
392 // Return to gem5 to let it run events, etc.
393 Fiber::primaryFiber()->run();
394
395 if (pauseEvent.scheduled())
396 deschedule(&pauseEvent);
397 if (stopEvent.scheduled())
398 deschedule(&stopEvent);
399 if (maxTickEvent.scheduled())
400 deschedule(&maxTickEvent);
401 if (starvationEvent.scheduled())
402 deschedule(&starvationEvent);
403
404 if (_throwToScMain) {
405 const ::sc_core::sc_report *to_throw = _throwToScMain;
406 _throwToScMain = nullptr;
407 throw *to_throw;
408 }
409}
410
411void
412Scheduler::oneCycle()
413{
414 runOnce = true;
415 scheduleReadyEvent();
416 start(::MaxTick, false);
417}
418
419void
420Scheduler::schedulePause()
421{
422 if (pauseEvent.scheduled())
423 return;
424
425 schedule(&pauseEvent);
426}
427
428void
429Scheduler::throwToScMain()
430{
431 ::sc_core::sc_report report = reportifyException();
432 _throwToScMain = &report;
433 status(StatusOther);
434 scMain->run();
435}
436
437void
438Scheduler::scheduleStop(bool finish_delta)
439{
440 if (stopEvent.scheduled())
441 return;
442
443 if (!finish_delta) {
444 _stopNow = true;
445 // If we're not supposed to finish the delta cycle, flush all
446 // pending activity.
447 clear();
448 }
449 schedule(&stopEvent);
450}
451
452void
453Scheduler::trace(bool delta)
454{
455 for (auto tf: traceFiles)
456 tf->trace(delta);
457}
458
459Scheduler scheduler;
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/ext/core/messages.hh"
37#include "systemc/ext/core/sc_main.hh"
38#include "systemc/ext/utils/sc_report.hh"
39#include "systemc/ext/utils/sc_report_handler.hh"
40#include "systemc/utils/report.hh"
41#include "systemc/utils/tracefile.hh"
42
43namespace sc_gem5
44{
45
46Scheduler::Scheduler() :
47 eq(nullptr), readyEvent(this, false, ReadyPriority),
48 pauseEvent(this, false, PausePriority),
49 stopEvent(this, false, StopPriority),
50 scMain(nullptr), _throwToScMain(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 for (Process *p = initList.getNext(); p; p = initList.getNext()) {
112 p->popListNode();
113
114 if (p->dontInitialize()) {
115 if (!p->hasStaticSensitivities() && !p->internal()) {
116 SC_REPORT_WARNING(sc_core::SC_ID_DISABLE_WILL_ORPHAN_PROCESS_,
117 p->name());
118 }
119 } else {
120 p->ready();
121 }
122 }
123
124 runUpdate();
125 runDelta();
126
127 for (auto ets: eventsToSchedule)
128 eq->schedule(ets.first, ets.second);
129 eventsToSchedule.clear();
130
131 if (_started) {
132 if (!runToTime && starved())
133 scheduleStarvationEvent();
134 kernel->status(::sc_core::SC_RUNNING);
135 }
136
137 initDone = true;
138
139 status(StatusOther);
140
141 scheduleTimeAdvancesEvent();
142}
143
144void
145Scheduler::reg(Process *p)
146{
147 if (initDone) {
148 // If not marked as dontInitialize, mark as ready.
149 if (!p->dontInitialize())
150 p->ready();
151 } else {
152 // Otherwise, record that this process should be initialized once we
153 // get there.
154 initList.pushLast(p);
155 }
156}
157
158void
159Scheduler::yield()
160{
161 // Pull a process from the active list.
162 _current = getNextReady();
163 if (!_current) {
164 // There are no more processes, so return control to evaluate.
165 Fiber::primaryFiber()->run();
166 } else {
167 _current->popListNode();
168 _current->scheduled(false);
169 // Switch to whatever Fiber is supposed to run this process. All
170 // Fibers which aren't running should be parked at this line.
171 _current->fiber()->run();
172 // If the current process needs to be manually started, start it.
173 if (_current && _current->needsStart()) {
174 _current->needsStart(false);
175 // If a process hasn't started yet, "resetting" it just starts it
176 // and signals its reset event.
177 if (_current->inReset())
178 _current->resetEvent().notify();
179 try {
180 _current->run();
181 } catch (...) {
182 throwToScMain();
183 }
184 }
185 }
186 if (_current && !_current->needsStart()) {
187 if (_current->excWrapper) {
188 auto ew = _current->excWrapper;
189 _current->excWrapper = nullptr;
190 ew->throw_it();
191 } else if (_current->inReset()) {
192 _current->reset(false);
193 }
194 }
195}
196
197void
198Scheduler::ready(Process *p)
199{
200 if (_stopNow)
201 return;
202
203 p->scheduled(true);
204
205 if (p->procKind() == ::sc_core::SC_METHOD_PROC_)
206 readyListMethods.pushLast(p);
207 else
208 readyListThreads.pushLast(p);
209
210 if (!inEvaluate())
211 scheduleReadyEvent();
212}
213
214void
215Scheduler::resume(Process *p)
216{
217 if (initDone)
218 ready(p);
219 else
220 initList.pushLast(p);
221}
222
223bool
224listContains(ListNode *list, ListNode *target)
225{
226 ListNode *n = list->nextListNode;
227 while (n != list)
228 if (n == target)
229 return true;
230 return false;
231}
232
233bool
234Scheduler::suspend(Process *p)
235{
236 bool was_ready;
237 if (initDone) {
238 // After initialization, check if we're on a ready list.
239 was_ready = (p->nextListNode != nullptr);
240 p->popListNode();
241 } else {
242 // Nothing is ready before init.
243 was_ready = false;
244 }
245 return was_ready;
246}
247
248void
249Scheduler::requestUpdate(Channel *c)
250{
251 updateList.pushLast(c);
252 if (!inEvaluate())
253 scheduleReadyEvent();
254}
255
256void
257Scheduler::scheduleReadyEvent()
258{
259 // Schedule the evaluate and update phases.
260 if (!readyEvent.scheduled()) {
261 schedule(&readyEvent);
262 if (starvationEvent.scheduled())
263 deschedule(&starvationEvent);
264 }
265}
266
267void
268Scheduler::scheduleStarvationEvent()
269{
270 if (!starvationEvent.scheduled()) {
271 schedule(&starvationEvent);
272 if (readyEvent.scheduled())
273 deschedule(&readyEvent);
274 }
275}
276
277void
278Scheduler::runReady()
279{
280 scheduleTimeAdvancesEvent();
281
282 bool empty = readyListMethods.empty() && readyListThreads.empty();
283 lastReadyTick = getCurTick();
284
285 // The evaluation phase.
286 status(StatusEvaluate);
287 do {
288 yield();
289 } while (getNextReady());
290 _current = nullptr;
291
292 if (!empty) {
293 _numCycles++;
294 _changeStamp++;
295 }
296
297 if (_stopNow) {
298 status(StatusOther);
299 return;
300 }
301
302 runUpdate();
303 if (!traceFiles.empty())
304 trace(true);
305 runDelta();
306
307 if (!runToTime && starved())
308 scheduleStarvationEvent();
309
310 if (runOnce)
311 schedulePause();
312
313 status(StatusOther);
314}
315
316void
317Scheduler::runUpdate()
318{
319 status(StatusUpdate);
320
321 try {
322 Channel *channel = updateList.getNext();
323 while (channel) {
324 channel->popListNode();
325 channel->update();
326 channel = updateList.getNext();
327 }
328 } catch (...) {
329 throwToScMain();
330 }
331}
332
333void
334Scheduler::runDelta()
335{
336 status(StatusDelta);
337
338 try {
339 while (!deltas.empty())
340 deltas.back()->run();
341 } catch (...) {
342 throwToScMain();
343 }
344}
345
346void
347Scheduler::pause()
348{
349 status(StatusPaused);
350 kernel->status(::sc_core::SC_PAUSED);
351 runOnce = false;
352 if (scMain && !scMain->finished())
353 scMain->run();
354}
355
356void
357Scheduler::stop()
358{
359 status(StatusStopped);
360 kernel->stop();
361
362 clear();
363
364 runOnce = false;
365 if (scMain && !scMain->finished())
366 scMain->run();
367}
368
369void
370Scheduler::start(Tick max_tick, bool run_to_time)
371{
372 // We should be running from sc_main. Keep track of that Fiber to return
373 // to later.
374 scMain = Fiber::currentFiber();
375
376 _started = true;
377 status(StatusOther);
378 runToTime = run_to_time;
379
380 maxTick = max_tick;
381 lastReadyTick = getCurTick();
382
383 if (initDone) {
384 if (!runToTime && starved())
385 scheduleStarvationEvent();
386 kernel->status(::sc_core::SC_RUNNING);
387 }
388
389 schedule(&maxTickEvent, maxTick);
390 scheduleTimeAdvancesEvent();
391
392 // Return to gem5 to let it run events, etc.
393 Fiber::primaryFiber()->run();
394
395 if (pauseEvent.scheduled())
396 deschedule(&pauseEvent);
397 if (stopEvent.scheduled())
398 deschedule(&stopEvent);
399 if (maxTickEvent.scheduled())
400 deschedule(&maxTickEvent);
401 if (starvationEvent.scheduled())
402 deschedule(&starvationEvent);
403
404 if (_throwToScMain) {
405 const ::sc_core::sc_report *to_throw = _throwToScMain;
406 _throwToScMain = nullptr;
407 throw *to_throw;
408 }
409}
410
411void
412Scheduler::oneCycle()
413{
414 runOnce = true;
415 scheduleReadyEvent();
416 start(::MaxTick, false);
417}
418
419void
420Scheduler::schedulePause()
421{
422 if (pauseEvent.scheduled())
423 return;
424
425 schedule(&pauseEvent);
426}
427
428void
429Scheduler::throwToScMain()
430{
431 ::sc_core::sc_report report = reportifyException();
432 _throwToScMain = &report;
433 status(StatusOther);
434 scMain->run();
435}
436
437void
438Scheduler::scheduleStop(bool finish_delta)
439{
440 if (stopEvent.scheduled())
441 return;
442
443 if (!finish_delta) {
444 _stopNow = true;
445 // If we're not supposed to finish the delta cycle, flush all
446 // pending activity.
447 clear();
448 }
449 schedule(&stopEvent);
450}
451
452void
453Scheduler::trace(bool delta)
454{
455 for (auto tf: traceFiles)
456 tf->trace(delta);
457}
458
459Scheduler scheduler;
460Process *getCurrentProcess() { return scheduler.current(); }
460
461namespace {
462
463void
464throwingReportHandler(const ::sc_core::sc_report &r,
465 const ::sc_core::sc_actions &)
466{
467 throw r;
468}
469
470} // anonymous namespace
471
472const ::sc_core::sc_report
473reportifyException()
474{
475 ::sc_core::sc_report_handler_proc old_handler = reportHandlerProc;
476 ::sc_core::sc_report_handler::set_handler(&throwingReportHandler);
477
478 try {
479 try {
480 // Rethrow the current exception so we can catch it and throw an
481 // sc_report instead if it's not a type we recognize/can handle.
482 throw;
483 } catch (const ::sc_core::sc_report &) {
484 // It's already a sc_report, so nothing to do.
485 throw;
486 } catch (const ::sc_core::sc_unwind_exception &) {
487 panic("Kill/reset exception escaped a Process::run()");
488 } catch (const std::exception &e) {
489 SC_REPORT_ERROR(
490 sc_core::SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, e.what());
491 } catch (const char *msg) {
492 SC_REPORT_ERROR(
493 sc_core::SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, msg);
494 } catch (...) {
495 SC_REPORT_ERROR(
496 sc_core::SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_,
497 "UNKNOWN EXCEPTION");
498 }
499 } catch (const ::sc_core::sc_report &r) {
500 ::sc_core::sc_report_handler::set_handler(old_handler);
501 return r;
502 }
503 panic("No exception thrown in reportifyException.");
504}
505
506} // namespace sc_gem5
461
462namespace {
463
464void
465throwingReportHandler(const ::sc_core::sc_report &r,
466 const ::sc_core::sc_actions &)
467{
468 throw r;
469}
470
471} // anonymous namespace
472
473const ::sc_core::sc_report
474reportifyException()
475{
476 ::sc_core::sc_report_handler_proc old_handler = reportHandlerProc;
477 ::sc_core::sc_report_handler::set_handler(&throwingReportHandler);
478
479 try {
480 try {
481 // Rethrow the current exception so we can catch it and throw an
482 // sc_report instead if it's not a type we recognize/can handle.
483 throw;
484 } catch (const ::sc_core::sc_report &) {
485 // It's already a sc_report, so nothing to do.
486 throw;
487 } catch (const ::sc_core::sc_unwind_exception &) {
488 panic("Kill/reset exception escaped a Process::run()");
489 } catch (const std::exception &e) {
490 SC_REPORT_ERROR(
491 sc_core::SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, e.what());
492 } catch (const char *msg) {
493 SC_REPORT_ERROR(
494 sc_core::SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, msg);
495 } catch (...) {
496 SC_REPORT_ERROR(
497 sc_core::SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_,
498 "UNKNOWN EXCEPTION");
499 }
500 } catch (const ::sc_core::sc_report &r) {
501 ::sc_core::sc_report_handler::set_handler(old_handler);
502 return r;
503 }
504 panic("No exception thrown in reportifyException.");
505}
506
507} // namespace sc_gem5