scheduler.cc revision 12987
18926Sandreas.hansson@arm.com/*
27586SAli.Saidi@arm.com * Copyright 2018 Google, Inc.
37586SAli.Saidi@arm.com *
47586SAli.Saidi@arm.com * Redistribution and use in source and binary forms, with or without
57586SAli.Saidi@arm.com * modification, are permitted provided that the following conditions are
67586SAli.Saidi@arm.com * met: redistributions of source code must retain the above copyright
77586SAli.Saidi@arm.com * notice, this list of conditions and the following disclaimer;
87586SAli.Saidi@arm.com * redistributions in binary form must reproduce the above copyright
97586SAli.Saidi@arm.com * notice, this list of conditions and the following disclaimer in the
107586SAli.Saidi@arm.com * documentation and/or other materials provided with the distribution;
117586SAli.Saidi@arm.com * neither the name of the copyright holders nor the names of its
127586SAli.Saidi@arm.com * contributors may be used to endorse or promote products derived from
133970Sgblack@eecs.umich.edu * this software without specific prior written permission.
143005Sstever@eecs.umich.edu *
153005Sstever@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
163005Sstever@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
173005Sstever@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
183005Sstever@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
193005Sstever@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
203005Sstever@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
213005Sstever@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
223005Sstever@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
233005Sstever@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
243005Sstever@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
253005Sstever@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
263005Sstever@eecs.umich.edu *
273005Sstever@eecs.umich.edu * Authors: Gabe Black
283005Sstever@eecs.umich.edu */
293005Sstever@eecs.umich.edu
303005Sstever@eecs.umich.edu#include "systemc/core/scheduler.hh"
313005Sstever@eecs.umich.edu
323005Sstever@eecs.umich.edu#include "base/fiber.hh"
333005Sstever@eecs.umich.edu#include "base/logging.hh"
343005Sstever@eecs.umich.edu#include "sim/eventq.hh"
353005Sstever@eecs.umich.edu#include "systemc/core/kernel.hh"
363005Sstever@eecs.umich.edu#include "systemc/ext/core/sc_main.hh"
373005Sstever@eecs.umich.edu
383005Sstever@eecs.umich.edunamespace sc_gem5
393005Sstever@eecs.umich.edu{
403005Sstever@eecs.umich.edu
416654Snate@binkert.orgScheduler::Scheduler() :
426654Snate@binkert.org    eq(nullptr), readyEvent(this, false, ReadyPriority),
432889SN/A    pauseEvent(this, false, PausePriority),
442710SN/A    stopEvent(this, false, StopPriority),
456654Snate@binkert.org    scMain(nullptr),
466654Snate@binkert.org    starvationEvent(this, false, StarvationPriority),
476654Snate@binkert.org    _started(false), _paused(false), _stopped(false),
485457Ssaidi@eecs.umich.edu    maxTickEvent(this, false, MaxTickPriority),
496654Snate@binkert.org    _numCycles(0), _current(nullptr), initReady(false)
506654Snate@binkert.org{}
512934SN/A
522549SN/Avoid
532995SN/AScheduler::prepareForInit()
543395Shsul@eecs.umich.edu{
556981SLisa.Hsu@amd.com    for (Process *p = toFinalize.getNext(); p; p = toFinalize.getNext()) {
563448Shsul@eecs.umich.edu        p->finalize();
578920Snilay@cs.wisc.edu        p->popListNode();
583444Sktlim@umich.edu    }
592889SN/A
608920Snilay@cs.wisc.edu    for (Process *p = initList.getNext(); p; p = initList.getNext()) {
618920Snilay@cs.wisc.edu        p->finalize();
623322Shsul@eecs.umich.edu        p->ready();
632710SN/A    }
642710SN/A
652710SN/A    for (auto ets: eventsToSchedule)
662710SN/A        eq->schedule(ets.first, ets.second);
672710SN/A    eventsToSchedule.clear();
682710SN/A
693322Shsul@eecs.umich.edu    if (_started)
703304Sstever@eecs.umich.edu        eq->schedule(&maxTickEvent, maxTick);
713322Shsul@eecs.umich.edu
723322Shsul@eecs.umich.edu    initReady = true;
733304Sstever@eecs.umich.edu}
743481Shsul@eecs.umich.edu
753481Shsul@eecs.umich.eduvoid
762566SN/AScheduler::reg(Process *p)
779129Sandreas.hansson@arm.com{
789129Sandreas.hansson@arm.com    if (initReady) {
792995SN/A        // If we're past initialization, finalize static sensitivity.
802995SN/A        p->finalize();
813304Sstever@eecs.umich.edu        // Mark the process as ready.
823304Sstever@eecs.umich.edu        p->ready();
833304Sstever@eecs.umich.edu    } else {
842995SN/A        // Otherwise, record that this process should be initialized once we
852995SN/A        // get there.
862995SN/A        initList.pushLast(p);
872917SN/A    }
882995SN/A}
898956Sjayneel@cs.wisc.edu
902995SN/Avoid
918956Sjayneel@cs.wisc.eduScheduler::dontInitialize(Process *p)
923304Sstever@eecs.umich.edu{
936135Sgblack@eecs.umich.edu    if (initReady) {
946135Sgblack@eecs.umich.edu        // Pop this process off of the ready list.
956654Snate@binkert.org        p->popListNode();
963819Shsul@eecs.umich.edu    } else {
976654Snate@binkert.org        // Push this process onto the list of processes which still need
985222Sksewell@umich.edu        // their static sensitivity to be finalized. That implicitly pops it
996654Snate@binkert.org        // off the list of processes to be initialized/marked ready.
1003819Shsul@eecs.umich.edu        toFinalize.pushLast(p);
1016654Snate@binkert.org    }
1027925Sgblack@eecs.umich.edu}
1037586SAli.Saidi@arm.com
1048061SAli.Saidi@ARM.comvoid
1058061SAli.Saidi@ARM.comScheduler::yield()
1068061SAli.Saidi@ARM.com{
1073819Shsul@eecs.umich.edu    _current = readyList.getNext();
1089059Snilay@cs.wisc.edu    if (!_current) {
1093819Shsul@eecs.umich.edu        // There are no more processes, so return control to evaluate.
1103873Sbinkertn@umich.edu        Fiber::primaryFiber()->run();
1113873Sbinkertn@umich.edu    } else {
1123873Sbinkertn@umich.edu        _current->popListNode();
1133873Sbinkertn@umich.edu        // Switch to whatever Fiber is supposed to run this process. All
1143873Sbinkertn@umich.edu        // Fibers which aren't running should be parked at this line.
1153873Sbinkertn@umich.edu        _current->fiber()->run();
1168659SAli.Saidi@ARM.com        // If the current process needs to be manually started, start it.
1178659SAli.Saidi@ARM.com        if (_current && _current->needsStart())
1186995Sgblack@eecs.umich.edu            _current->run();
1193668Srdreslin@umich.edu    }
1208713Sandreas.hansson@arm.com}
1218713Sandreas.hansson@arm.com
1228713Sandreas.hansson@arm.comvoid
1238713Sandreas.hansson@arm.comScheduler::ready(Process *p)
1246636Ssteve.reinhardt@amd.com{
1258894Ssaidi@eecs.umich.edu    // Clump methods together to minimize context switching.
1268839Sandreas.hansson@arm.com    if (p->procKind() == ::sc_core::SC_METHOD_PROC_)
1278839Sandreas.hansson@arm.com        readyList.pushFirst(p);
1288713Sandreas.hansson@arm.com    else
1298713Sandreas.hansson@arm.com        readyList.pushLast(p);
1308870SAli.Saidi@ARM.com
1318839Sandreas.hansson@arm.com    scheduleReadyEvent();
1328839Sandreas.hansson@arm.com}
1335142Ssaidi@eecs.umich.edu
1348926Sandreas.hansson@arm.comvoid
1358926Sandreas.hansson@arm.comScheduler::requestUpdate(Channel *c)
1368926Sandreas.hansson@arm.com{
1378926Sandreas.hansson@arm.com    updateList.pushLast(c);
1383312Sstever@eecs.umich.edu    scheduleReadyEvent();
1394968Sacolyte@umich.edu}
1408926Sandreas.hansson@arm.com
1418887Sgeoffrey.blake@arm.comvoid
1428887Sgeoffrey.blake@arm.comScheduler::scheduleReadyEvent()
1438887Sgeoffrey.blake@arm.com{
1448887Sgeoffrey.blake@arm.com    // Schedule the evaluate and update phases.
1454968Sacolyte@umich.edu    if (!readyEvent.scheduled()) {
1463005Sstever@eecs.umich.edu        panic_if(!eq, "Need to schedule ready, but no event manager.\n");
1476654Snate@binkert.org        eq->schedule(&readyEvent, eq->getCurTick());
1483819Shsul@eecs.umich.edu        if (starvationEvent.scheduled())
1496654Snate@binkert.org            eq->deschedule(&starvationEvent);
1505222Sksewell@umich.edu    }
1516654Snate@binkert.org}
1523819Shsul@eecs.umich.edu
1536654Snate@binkert.orgvoid
1546135Sgblack@eecs.umich.eduScheduler::scheduleStarvationEvent()
1557586SAli.Saidi@arm.com{
1568661SAli.Saidi@ARM.com    if (!starvationEvent.scheduled()) {
1578661SAli.Saidi@ARM.com        panic_if(!eq, "Need to schedule starvation event, "
1583322Shsul@eecs.umich.edu                "but no event manager.\n");
1598863Snilay@cs.wisc.edu        eq->schedule(&starvationEvent, eq->getCurTick());
1607876Sgblack@eecs.umich.edu        if (readyEvent.scheduled())
1614968Sacolyte@umich.edu            eq->deschedule(&readyEvent);
1628926Sandreas.hansson@arm.com    }
1634837Ssaidi@eecs.umich.edu}
1644837Ssaidi@eecs.umich.edu
1658810SAli.Saidi@ARM.comvoid
1668870SAli.Saidi@ARM.comScheduler::runReady()
1678845Sandreas.hansson@arm.com{
1688845Sandreas.hansson@arm.com    bool empty = readyList.empty();
1694837Ssaidi@eecs.umich.edu
1708659SAli.Saidi@ARM.com    // The evaluation phase.
1718801Sgblack@eecs.umich.edu    do {
1723005Sstever@eecs.umich.edu        yield();
1738801Sgblack@eecs.umich.edu    } while (!readyList.empty());
1743005Sstever@eecs.umich.edu
1753005Sstever@eecs.umich.edu    if (!empty)
1763005Sstever@eecs.umich.edu        _numCycles++;
1772566SN/A
1787861Sgblack@eecs.umich.edu    // The update phase.
1797861Sgblack@eecs.umich.edu    update();
1807861Sgblack@eecs.umich.edu
1818635Schris.emmons@arm.com    if (starved() && !runToTime)
1828635Schris.emmons@arm.com        scheduleStarvationEvent();
1838635Schris.emmons@arm.com
1849061Snilay@cs.wisc.edu    // The delta phase will happen naturally through the event queue.
1853481Shsul@eecs.umich.edu}
186
187void
188Scheduler::update()
189{
190    Channel *channel = updateList.getNext();
191    while (channel) {
192        channel->popListNode();
193        channel->update();
194        channel = updateList.getNext();
195    }
196}
197
198void
199Scheduler::pause()
200{
201    _paused = true;
202    kernel->status(::sc_core::SC_PAUSED);
203    scMain->run();
204}
205
206void
207Scheduler::stop()
208{
209    _stopped = true;
210    kernel->stop();
211    scMain->run();
212}
213
214void
215Scheduler::start(Tick max_tick, bool run_to_time)
216{
217    // We should be running from sc_main. Keep track of that Fiber to return
218    // to later.
219    scMain = Fiber::currentFiber();
220
221    _started = true;
222    _paused = false;
223    _stopped = false;
224    runToTime = run_to_time;
225
226    maxTick = max_tick;
227
228    if (starved() && !runToTime)
229        return;
230
231    if (initReady) {
232        kernel->status(::sc_core::SC_RUNNING);
233        eq->schedule(&maxTickEvent, maxTick);
234    }
235
236    // Return to gem5 to let it run events, etc.
237    Fiber::primaryFiber()->run();
238
239    if (pauseEvent.scheduled())
240        eq->deschedule(&pauseEvent);
241    if (stopEvent.scheduled())
242        eq->deschedule(&stopEvent);
243    if (maxTickEvent.scheduled())
244        eq->deschedule(&maxTickEvent);
245    if (starvationEvent.scheduled())
246        eq->deschedule(&starvationEvent);
247}
248
249void
250Scheduler::schedulePause()
251{
252    if (pauseEvent.scheduled())
253        return;
254
255    eq->schedule(&pauseEvent, eq->getCurTick());
256}
257
258void
259Scheduler::scheduleStop(bool finish_delta)
260{
261    if (stopEvent.scheduled())
262        return;
263
264    if (!finish_delta) {
265        // If we're not supposed to finish the delta cycle, flush the list
266        // of ready processes and scheduled updates.
267        Process *p;
268        while ((p = readyList.getNext()))
269            p->popListNode();
270        Channel *c;
271        while ((c = updateList.getNext()))
272            c->popListNode();
273    }
274    eq->schedule(&stopEvent, eq->getCurTick());
275}
276
277Scheduler scheduler;
278
279} // namespace sc_gem5
280