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 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), 51 _numCycles(0), _changeStamp(0), _current(nullptr), initDone(false),
| 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 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), 51 _numCycles(0), _changeStamp(0), _current(nullptr), initDone(false),
|
283 if (!empty) { 284 _numCycles++; 285 _changeStamp++; 286 } 287 288 if (_stopNow) 289 return; 290 291 runUpdate(); 292 runDelta(); 293 294 if (!runToTime && starved()) 295 scheduleStarvationEvent(); 296 297 if (runOnce) 298 schedulePause(); 299 300 status(StatusOther); 301} 302 303void 304Scheduler::runUpdate() 305{ 306 status(StatusUpdate); 307 308 try { 309 Channel *channel = updateList.getNext(); 310 while (channel) { 311 channel->popListNode(); 312 channel->update(); 313 channel = updateList.getNext(); 314 } 315 } catch (...) { 316 throwToScMain(); 317 } 318} 319 320void 321Scheduler::runDelta() 322{ 323 status(StatusDelta); 324 325 try { 326 while (!deltas.empty()) 327 deltas.front()->run(); 328 } catch (...) { 329 throwToScMain(); 330 } 331} 332 333void 334Scheduler::pause() 335{ 336 status(StatusPaused); 337 kernel->status(::sc_core::SC_PAUSED); 338 runOnce = false; 339 if (scMain && !scMain->finished()) 340 scMain->run(); 341} 342 343void 344Scheduler::stop() 345{ 346 status(StatusStopped); 347 kernel->stop(); 348 349 clear(); 350 351 runOnce = false; 352 if (scMain && !scMain->finished()) 353 scMain->run(); 354} 355 356void 357Scheduler::start(Tick max_tick, bool run_to_time) 358{ 359 // We should be running from sc_main. Keep track of that Fiber to return 360 // to later. 361 scMain = Fiber::currentFiber(); 362 363 _started = true; 364 status(StatusOther); 365 runToTime = run_to_time; 366 367 maxTick = max_tick; 368 lastReadyTick = getCurTick(); 369 370 if (initDone) { 371 if (!runToTime && starved()) 372 scheduleStarvationEvent(); 373 kernel->status(::sc_core::SC_RUNNING); 374 } 375 376 schedule(&maxTickEvent, maxTick); 377 378 // Return to gem5 to let it run events, etc. 379 Fiber::primaryFiber()->run(); 380 381 if (pauseEvent.scheduled()) 382 deschedule(&pauseEvent); 383 if (stopEvent.scheduled()) 384 deschedule(&stopEvent); 385 if (maxTickEvent.scheduled()) 386 deschedule(&maxTickEvent); 387 if (starvationEvent.scheduled()) 388 deschedule(&starvationEvent); 389 390 if (_throwToScMain) { 391 const ::sc_core::sc_report *to_throw = _throwToScMain; 392 _throwToScMain = nullptr; 393 throw *to_throw; 394 } 395} 396 397void 398Scheduler::oneCycle() 399{ 400 runOnce = true; 401 scheduleReadyEvent(); 402 start(::MaxTick, false); 403} 404 405void 406Scheduler::schedulePause() 407{ 408 if (pauseEvent.scheduled()) 409 return; 410 411 schedule(&pauseEvent); 412} 413 414void 415Scheduler::throwToScMain(const ::sc_core::sc_report *r) 416{ 417 if (!r) 418 r = reportifyException(); 419 _throwToScMain = r; 420 status(StatusOther); 421 scMain->run(); 422} 423 424void 425Scheduler::scheduleStop(bool finish_delta) 426{ 427 if (stopEvent.scheduled()) 428 return; 429 430 if (!finish_delta) { 431 _stopNow = true; 432 // If we're not supposed to finish the delta cycle, flush all 433 // pending activity. 434 clear(); 435 } 436 schedule(&stopEvent); 437} 438 439Scheduler scheduler; 440 441namespace { 442 443void 444throwingReportHandler(const ::sc_core::sc_report &r, 445 const ::sc_core::sc_actions &) 446{ 447 throw r; 448} 449 450} // anonymous namespace 451 452const ::sc_core::sc_report * 453reportifyException() 454{ 455 ::sc_core::sc_report_handler_proc old_handler = 456 ::sc_core::sc_report_handler::get_handler(); 457 ::sc_core::sc_report_handler::set_handler(&throwingReportHandler); 458 459 try { 460 try { 461 // Rethrow the current exception so we can catch it and throw an 462 // sc_report instead if it's not a type we recognize/can handle. 463 throw; 464 } catch (const ::sc_core::sc_report &) { 465 // It's already a sc_report, so nothing to do. 466 throw; 467 } catch (const ::sc_core::sc_unwind_exception &) { 468 panic("Kill/reset exception escaped a Process::run()"); 469 } catch (const std::exception &e) { 470 SC_REPORT_ERROR("uncaught exception", e.what()); 471 } catch (const char *msg) { 472 SC_REPORT_ERROR("uncaught exception", msg); 473 } catch (...) { 474 SC_REPORT_ERROR("uncaught exception", "UNKNOWN EXCEPTION"); 475 } 476 } catch (const ::sc_core::sc_report &r) { 477 ::sc_core::sc_report_handler::set_handler(old_handler); 478 return &r; 479 } 480 panic("No exception thrown in reportifyException."); 481} 482 483} // namespace sc_gem5
| 272 if (!empty) { 273 _numCycles++; 274 _changeStamp++; 275 } 276 277 if (_stopNow) 278 return; 279 280 runUpdate(); 281 runDelta(); 282 283 if (!runToTime && starved()) 284 scheduleStarvationEvent(); 285 286 if (runOnce) 287 schedulePause(); 288 289 status(StatusOther); 290} 291 292void 293Scheduler::runUpdate() 294{ 295 status(StatusUpdate); 296 297 try { 298 Channel *channel = updateList.getNext(); 299 while (channel) { 300 channel->popListNode(); 301 channel->update(); 302 channel = updateList.getNext(); 303 } 304 } catch (...) { 305 throwToScMain(); 306 } 307} 308 309void 310Scheduler::runDelta() 311{ 312 status(StatusDelta); 313 314 try { 315 while (!deltas.empty()) 316 deltas.front()->run(); 317 } catch (...) { 318 throwToScMain(); 319 } 320} 321 322void 323Scheduler::pause() 324{ 325 status(StatusPaused); 326 kernel->status(::sc_core::SC_PAUSED); 327 runOnce = false; 328 if (scMain && !scMain->finished()) 329 scMain->run(); 330} 331 332void 333Scheduler::stop() 334{ 335 status(StatusStopped); 336 kernel->stop(); 337 338 clear(); 339 340 runOnce = false; 341 if (scMain && !scMain->finished()) 342 scMain->run(); 343} 344 345void 346Scheduler::start(Tick max_tick, bool run_to_time) 347{ 348 // We should be running from sc_main. Keep track of that Fiber to return 349 // to later. 350 scMain = Fiber::currentFiber(); 351 352 _started = true; 353 status(StatusOther); 354 runToTime = run_to_time; 355 356 maxTick = max_tick; 357 lastReadyTick = getCurTick(); 358 359 if (initDone) { 360 if (!runToTime && starved()) 361 scheduleStarvationEvent(); 362 kernel->status(::sc_core::SC_RUNNING); 363 } 364 365 schedule(&maxTickEvent, maxTick); 366 367 // Return to gem5 to let it run events, etc. 368 Fiber::primaryFiber()->run(); 369 370 if (pauseEvent.scheduled()) 371 deschedule(&pauseEvent); 372 if (stopEvent.scheduled()) 373 deschedule(&stopEvent); 374 if (maxTickEvent.scheduled()) 375 deschedule(&maxTickEvent); 376 if (starvationEvent.scheduled()) 377 deschedule(&starvationEvent); 378 379 if (_throwToScMain) { 380 const ::sc_core::sc_report *to_throw = _throwToScMain; 381 _throwToScMain = nullptr; 382 throw *to_throw; 383 } 384} 385 386void 387Scheduler::oneCycle() 388{ 389 runOnce = true; 390 scheduleReadyEvent(); 391 start(::MaxTick, false); 392} 393 394void 395Scheduler::schedulePause() 396{ 397 if (pauseEvent.scheduled()) 398 return; 399 400 schedule(&pauseEvent); 401} 402 403void 404Scheduler::throwToScMain(const ::sc_core::sc_report *r) 405{ 406 if (!r) 407 r = reportifyException(); 408 _throwToScMain = r; 409 status(StatusOther); 410 scMain->run(); 411} 412 413void 414Scheduler::scheduleStop(bool finish_delta) 415{ 416 if (stopEvent.scheduled()) 417 return; 418 419 if (!finish_delta) { 420 _stopNow = true; 421 // If we're not supposed to finish the delta cycle, flush all 422 // pending activity. 423 clear(); 424 } 425 schedule(&stopEvent); 426} 427 428Scheduler scheduler; 429 430namespace { 431 432void 433throwingReportHandler(const ::sc_core::sc_report &r, 434 const ::sc_core::sc_actions &) 435{ 436 throw r; 437} 438 439} // anonymous namespace 440 441const ::sc_core::sc_report * 442reportifyException() 443{ 444 ::sc_core::sc_report_handler_proc old_handler = 445 ::sc_core::sc_report_handler::get_handler(); 446 ::sc_core::sc_report_handler::set_handler(&throwingReportHandler); 447 448 try { 449 try { 450 // Rethrow the current exception so we can catch it and throw an 451 // sc_report instead if it's not a type we recognize/can handle. 452 throw; 453 } catch (const ::sc_core::sc_report &) { 454 // It's already a sc_report, so nothing to do. 455 throw; 456 } catch (const ::sc_core::sc_unwind_exception &) { 457 panic("Kill/reset exception escaped a Process::run()"); 458 } catch (const std::exception &e) { 459 SC_REPORT_ERROR("uncaught exception", e.what()); 460 } catch (const char *msg) { 461 SC_REPORT_ERROR("uncaught exception", msg); 462 } catch (...) { 463 SC_REPORT_ERROR("uncaught exception", "UNKNOWN EXCEPTION"); 464 } 465 } catch (const ::sc_core::sc_report &r) { 466 ::sc_core::sc_report_handler::set_handler(old_handler); 467 return &r; 468 } 469 panic("No exception thrown in reportifyException."); 470} 471 472} // namespace sc_gem5
|