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