scheduler.cc revision 12962
112953Sgabeblack@google.com/* 212953Sgabeblack@google.com * Copyright 2018 Google, Inc. 312953Sgabeblack@google.com * 412953Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 512953Sgabeblack@google.com * modification, are permitted provided that the following conditions are 612953Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 712953Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 812953Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 912953Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 1012953Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 1112953Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 1212953Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 1312953Sgabeblack@google.com * this software without specific prior written permission. 1412953Sgabeblack@google.com * 1512953Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1612953Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1712953Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1812953Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1912953Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2012953Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2112953Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2212953Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2312953Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2412953Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2512953Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2612953Sgabeblack@google.com * 2712953Sgabeblack@google.com * Authors: Gabe Black 2812953Sgabeblack@google.com */ 2912953Sgabeblack@google.com 3012953Sgabeblack@google.com#include "systemc/core/scheduler.hh" 3112953Sgabeblack@google.com 3212953Sgabeblack@google.com#include "base/fiber.hh" 3312954Sgabeblack@google.com#include "base/logging.hh" 3412954Sgabeblack@google.com#include "sim/eventq.hh" 3512953Sgabeblack@google.com 3612953Sgabeblack@google.comnamespace sc_gem5 3712953Sgabeblack@google.com{ 3812953Sgabeblack@google.com 3912954Sgabeblack@google.comScheduler::Scheduler() : 4012962Sgabeblack@google.com eq(nullptr), readyEvent(this, false, ReadyPriority), 4112961Sgabeblack@google.com pauseEvent(this, false, PausePriority), 4212961Sgabeblack@google.com stopEvent(this, false, StopPriority), 4312961Sgabeblack@google.com scMain(nullptr), _started(false), _paused(false), _stopped(false), 4412961Sgabeblack@google.com maxTickEvent(this, false, MaxTickPriority), 4512957Sgabeblack@google.com _numCycles(0), _current(nullptr), initReady(false) 4612954Sgabeblack@google.com{} 4712953Sgabeblack@google.com 4812953Sgabeblack@google.comvoid 4912957Sgabeblack@google.comScheduler::prepareForInit() 5012953Sgabeblack@google.com{ 5112957Sgabeblack@google.com for (Process *p = toFinalize.getNext(); p; p = toFinalize.getNext()) { 5212957Sgabeblack@google.com p->finalize(); 5312957Sgabeblack@google.com p->popListNode(); 5412957Sgabeblack@google.com } 5512957Sgabeblack@google.com 5612957Sgabeblack@google.com for (Process *p = initList.getNext(); p; p = initList.getNext()) { 5712957Sgabeblack@google.com p->finalize(); 5812959Sgabeblack@google.com p->ready(); 5912957Sgabeblack@google.com } 6012957Sgabeblack@google.com 6112961Sgabeblack@google.com if (_started) 6212961Sgabeblack@google.com eq->schedule(&maxTickEvent, maxTick); 6312961Sgabeblack@google.com 6412957Sgabeblack@google.com initReady = true; 6512957Sgabeblack@google.com} 6612957Sgabeblack@google.com 6712957Sgabeblack@google.comvoid 6812957Sgabeblack@google.comScheduler::reg(Process *p) 6912957Sgabeblack@google.com{ 7012957Sgabeblack@google.com if (initReady) { 7112957Sgabeblack@google.com // If we're past initialization, finalize static sensitivity. 7212957Sgabeblack@google.com p->finalize(); 7312957Sgabeblack@google.com // Mark the process as ready. 7412959Sgabeblack@google.com p->ready(); 7512957Sgabeblack@google.com } else { 7612957Sgabeblack@google.com // Otherwise, record that this process should be initialized once we 7712957Sgabeblack@google.com // get there. 7812957Sgabeblack@google.com initList.pushLast(p); 7912957Sgabeblack@google.com } 8012957Sgabeblack@google.com} 8112957Sgabeblack@google.com 8212957Sgabeblack@google.comvoid 8312957Sgabeblack@google.comScheduler::dontInitialize(Process *p) 8412957Sgabeblack@google.com{ 8512957Sgabeblack@google.com if (initReady) { 8612957Sgabeblack@google.com // Pop this process off of the ready list. 8712957Sgabeblack@google.com p->popListNode(); 8812957Sgabeblack@google.com } else { 8912957Sgabeblack@google.com // Push this process onto the list of processes which still need 9012957Sgabeblack@google.com // their static sensitivity to be finalized. That implicitly pops it 9112957Sgabeblack@google.com // off the list of processes to be initialized/marked ready. 9212957Sgabeblack@google.com toFinalize.pushLast(p); 9312957Sgabeblack@google.com } 9412953Sgabeblack@google.com} 9512953Sgabeblack@google.com 9612953Sgabeblack@google.comvoid 9712953Sgabeblack@google.comScheduler::yield() 9812953Sgabeblack@google.com{ 9912953Sgabeblack@google.com _current = readyList.getNext(); 10012953Sgabeblack@google.com if (!_current) { 10112953Sgabeblack@google.com // There are no more processes, so return control to evaluate. 10212953Sgabeblack@google.com Fiber::primaryFiber()->run(); 10312953Sgabeblack@google.com } else { 10412953Sgabeblack@google.com _current->popListNode(); 10512953Sgabeblack@google.com // Switch to whatever Fiber is supposed to run this process. All 10612953Sgabeblack@google.com // Fibers which aren't running should be parked at this line. 10712953Sgabeblack@google.com _current->fiber()->run(); 10812961Sgabeblack@google.com // If the current process needs to be manually started, start it. 10912961Sgabeblack@google.com if (_current && _current->needsStart()) 11012953Sgabeblack@google.com _current->run(); 11112953Sgabeblack@google.com } 11212953Sgabeblack@google.com} 11312953Sgabeblack@google.com 11412953Sgabeblack@google.comvoid 11512954Sgabeblack@google.comScheduler::ready(Process *p) 11612953Sgabeblack@google.com{ 11712954Sgabeblack@google.com // Clump methods together to minimize context switching. 11812954Sgabeblack@google.com if (p->procKind() == ::sc_core::SC_METHOD_PROC_) 11912954Sgabeblack@google.com readyList.pushFirst(p); 12012954Sgabeblack@google.com else 12112954Sgabeblack@google.com readyList.pushLast(p); 12212953Sgabeblack@google.com 12312954Sgabeblack@google.com scheduleReadyEvent(); 12412954Sgabeblack@google.com} 12512954Sgabeblack@google.com 12612954Sgabeblack@google.comvoid 12712954Sgabeblack@google.comScheduler::requestUpdate(Channel *c) 12812954Sgabeblack@google.com{ 12912954Sgabeblack@google.com updateList.pushLast(c); 13012954Sgabeblack@google.com scheduleReadyEvent(); 13112954Sgabeblack@google.com} 13212954Sgabeblack@google.com 13312954Sgabeblack@google.comvoid 13412954Sgabeblack@google.comScheduler::scheduleReadyEvent() 13512954Sgabeblack@google.com{ 13612954Sgabeblack@google.com // Schedule the evaluate and update phases. 13712954Sgabeblack@google.com if (!readyEvent.scheduled()) { 13812954Sgabeblack@google.com panic_if(!eq, "Need to schedule ready, but no event manager.\n"); 13912954Sgabeblack@google.com eq->schedule(&readyEvent, eq->getCurTick()); 14012954Sgabeblack@google.com } 14112954Sgabeblack@google.com} 14212954Sgabeblack@google.com 14312954Sgabeblack@google.comvoid 14412954Sgabeblack@google.comScheduler::runReady() 14512954Sgabeblack@google.com{ 14612954Sgabeblack@google.com bool empty = readyList.empty(); 14712954Sgabeblack@google.com 14812954Sgabeblack@google.com // The evaluation phase. 14912953Sgabeblack@google.com do { 15012953Sgabeblack@google.com yield(); 15112953Sgabeblack@google.com } while (!readyList.empty()); 15212954Sgabeblack@google.com 15312954Sgabeblack@google.com if (!empty) 15412954Sgabeblack@google.com _numCycles++; 15512954Sgabeblack@google.com 15612954Sgabeblack@google.com // The update phase. 15712954Sgabeblack@google.com update(); 15812954Sgabeblack@google.com 15912954Sgabeblack@google.com // The delta phase will happen naturally through the event queue. 16012953Sgabeblack@google.com} 16112953Sgabeblack@google.com 16212953Sgabeblack@google.comvoid 16312953Sgabeblack@google.comScheduler::update() 16412953Sgabeblack@google.com{ 16512954Sgabeblack@google.com Channel *channel = updateList.getNext(); 16612954Sgabeblack@google.com while (channel) { 16712954Sgabeblack@google.com channel->popListNode(); 16812954Sgabeblack@google.com channel->update(); 16912954Sgabeblack@google.com channel = updateList.getNext(); 17012954Sgabeblack@google.com } 17112953Sgabeblack@google.com} 17212953Sgabeblack@google.com 17312961Sgabeblack@google.comvoid 17412961Sgabeblack@google.comScheduler::pause() 17512961Sgabeblack@google.com{ 17612961Sgabeblack@google.com _paused = true; 17712961Sgabeblack@google.com scMain->run(); 17812961Sgabeblack@google.com} 17912961Sgabeblack@google.com 18012961Sgabeblack@google.comvoid 18112961Sgabeblack@google.comScheduler::stop() 18212961Sgabeblack@google.com{ 18312961Sgabeblack@google.com _stopped = true; 18412961Sgabeblack@google.com scMain->run(); 18512961Sgabeblack@google.com} 18612961Sgabeblack@google.com 18712961Sgabeblack@google.comvoid 18812961Sgabeblack@google.comScheduler::start(Tick max_tick, bool run_to_time) 18912961Sgabeblack@google.com{ 19012961Sgabeblack@google.com // We should be running from sc_main. Keep track of that Fiber to return 19112961Sgabeblack@google.com // to later. 19212961Sgabeblack@google.com scMain = Fiber::currentFiber(); 19312961Sgabeblack@google.com 19412961Sgabeblack@google.com _started = true; 19512961Sgabeblack@google.com _paused = false; 19612961Sgabeblack@google.com _stopped = false; 19712961Sgabeblack@google.com 19812961Sgabeblack@google.com maxTick = max_tick; 19912961Sgabeblack@google.com 20012961Sgabeblack@google.com if (initReady) 20112961Sgabeblack@google.com eq->schedule(&maxTickEvent, maxTick); 20212961Sgabeblack@google.com 20312961Sgabeblack@google.com // Return to gem5 to let it run events, etc. 20412961Sgabeblack@google.com Fiber::primaryFiber()->run(); 20512961Sgabeblack@google.com 20612961Sgabeblack@google.com if (pauseEvent.scheduled()) 20712961Sgabeblack@google.com eq->deschedule(&pauseEvent); 20812961Sgabeblack@google.com if (stopEvent.scheduled()) 20912961Sgabeblack@google.com eq->deschedule(&stopEvent); 21012961Sgabeblack@google.com if (maxTickEvent.scheduled()) 21112961Sgabeblack@google.com eq->deschedule(&maxTickEvent); 21212961Sgabeblack@google.com} 21312961Sgabeblack@google.com 21412961Sgabeblack@google.comvoid 21512961Sgabeblack@google.comScheduler::schedulePause() 21612961Sgabeblack@google.com{ 21712961Sgabeblack@google.com if (pauseEvent.scheduled()) 21812961Sgabeblack@google.com return; 21912961Sgabeblack@google.com 22012961Sgabeblack@google.com eq->schedule(&pauseEvent, eq->getCurTick()); 22112961Sgabeblack@google.com} 22212961Sgabeblack@google.com 22312961Sgabeblack@google.comvoid 22412961Sgabeblack@google.comScheduler::scheduleStop(bool finish_delta) 22512961Sgabeblack@google.com{ 22612961Sgabeblack@google.com if (stopEvent.scheduled()) 22712961Sgabeblack@google.com return; 22812961Sgabeblack@google.com 22912961Sgabeblack@google.com if (!finish_delta) { 23012961Sgabeblack@google.com // If we're not supposed to finish the delta cycle, flush the list 23112961Sgabeblack@google.com // of ready processes and scheduled updates. 23212961Sgabeblack@google.com Process *p; 23312961Sgabeblack@google.com while ((p = readyList.getNext())) 23412961Sgabeblack@google.com p->popListNode(); 23512961Sgabeblack@google.com Channel *c; 23612961Sgabeblack@google.com while ((c = updateList.getNext())) 23712961Sgabeblack@google.com c->popListNode(); 23812961Sgabeblack@google.com } 23912961Sgabeblack@google.com eq->schedule(&stopEvent, eq->getCurTick()); 24012961Sgabeblack@google.com} 24112961Sgabeblack@google.com 24212953Sgabeblack@google.comScheduler scheduler; 24312953Sgabeblack@google.com 24412953Sgabeblack@google.com} // namespace sc_gem5 245