/*
 * Copyright 2018 Google, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#include "systemc/core/scheduler.hh"

#include "base/fiber.hh"
#include "base/logging.hh"
#include "sim/eventq.hh"
#include "systemc/core/kernel.hh"
#include "systemc/core/sc_main_fiber.hh"
#include "systemc/ext/core/messages.hh"
#include "systemc/ext/core/sc_main.hh"
#include "systemc/ext/utils/sc_report.hh"
#include "systemc/ext/utils/sc_report_handler.hh"
#include "systemc/utils/report.hh"
#include "systemc/utils/tracefile.hh"

namespace sc_gem5
{

Scheduler::Scheduler() :
    eq(nullptr), readyEvent(this, false, ReadyPriority),
    pauseEvent(this, false, PausePriority),
    stopEvent(this, false, StopPriority), _throwToScMain(nullptr),
    starvationEvent(this, false, StarvationPriority),
    _elaborationDone(false), _started(false), _stopNow(false),
    _status(StatusOther), maxTickEvent(this, false, MaxTickPriority),
    timeAdvancesEvent(this, false, TimeAdvancesPriority), _numCycles(0),
    _changeStamp(0), _current(nullptr), initDone(false), runOnce(false)
{}

Scheduler::~Scheduler()
{
    // Clear out everything that belongs to us to make sure nobody tries to
    // clear themselves out after the scheduler goes away.
    clear();
}

void
Scheduler::clear()
{
    // Delta notifications.
    while (!deltas.empty())
        deltas.front()->deschedule();

    // Timed notifications.
    for (auto &tsp: timeSlots) {
        TimeSlot *&ts = tsp.second;
        while (!ts->events.empty())
            ts->events.front()->deschedule();
        deschedule(ts);
    }
    timeSlots.clear();

    // gem5 events.
    if (readyEvent.scheduled())
        deschedule(&readyEvent);
    if (pauseEvent.scheduled())
        deschedule(&pauseEvent);
    if (stopEvent.scheduled())
        deschedule(&stopEvent);
    if (starvationEvent.scheduled())
        deschedule(&starvationEvent);
    if (maxTickEvent.scheduled())
        deschedule(&maxTickEvent);
    if (timeAdvancesEvent.scheduled())
        deschedule(&timeAdvancesEvent);

    Process *p;
    while ((p = initList.getNext()))
        p->popListNode();
    while ((p = readyListMethods.getNext()))
        p->popListNode();
    while ((p = readyListThreads.getNext()))
        p->popListNode();

    Channel *c;
    while ((c = updateList.getNext()))
        c->popListNode();
}

void
Scheduler::initPhase()
{
    for (Process *p = initList.getNext(); p; p = initList.getNext()) {
        p->popListNode();

        if (p->dontInitialize()) {
            if (!p->hasStaticSensitivities() && !p->internal()) {
                SC_REPORT_WARNING(sc_core::SC_ID_DISABLE_WILL_ORPHAN_PROCESS_,
                        p->name());
            }
        } else {
            p->ready();
        }
    }

    runUpdate();
    runDelta();

    for (auto ets: eventsToSchedule)
        eq->schedule(ets.first, ets.second);
    eventsToSchedule.clear();

    if (_started) {
        if (!runToTime && starved())
            scheduleStarvationEvent();
        kernel->status(::sc_core::SC_RUNNING);
    }

    initDone = true;

    status(StatusOther);

    scheduleTimeAdvancesEvent();
}

void
Scheduler::reg(Process *p)
{
    if (initDone) {
        // If not marked as dontInitialize, mark as ready.
        if (!p->dontInitialize())
            p->ready();
    } else {
        // Otherwise, record that this process should be initialized once we
        // get there.
        initList.pushLast(p);
    }
}

void
Scheduler::yield()
{
    // Pull a process from the active list.
    _current = getNextReady();
    if (!_current) {
        // There are no more processes, so return control to evaluate.
        Fiber::primaryFiber()->run();
    } else {
        _current->popListNode();
        _current->scheduled(false);
        // Switch to whatever Fiber is supposed to run this process. All
        // Fibers which aren't running should be parked at this line.
        _current->fiber()->run();
        // If the current process needs to be manually started, start it.
        if (_current && _current->needsStart()) {
            _current->needsStart(false);
            // If a process hasn't started yet, "resetting" it just starts it
            // and signals its reset event.
            if (_current->inReset())
                _current->resetEvent().notify();
            try {
                _current->run();
            } catch (...) {
                throwToScMain();
            }
        }
    }
    if (_current && !_current->needsStart()) {
        if (_current->excWrapper) {
            auto ew = _current->excWrapper;
            _current->excWrapper = nullptr;
            ew->throw_it();
        } else if (_current->inReset()) {
            _current->reset(false);
        }
    }
}

void
Scheduler::ready(Process *p)
{
    if (_stopNow)
        return;

    p->scheduled(true);

    if (p->procKind() == ::sc_core::SC_METHOD_PROC_)
        readyListMethods.pushLast(p);
    else
        readyListThreads.pushLast(p);

    if (!inEvaluate())
        scheduleReadyEvent();
}

void
Scheduler::resume(Process *p)
{
    if (initDone)
        ready(p);
    else
        initList.pushLast(p);
}

bool
listContains(ListNode *list, ListNode *target)
{
    ListNode *n = list->nextListNode;
    while (n != list)
        if (n == target)
            return true;
    return false;
}

bool
Scheduler::suspend(Process *p)
{
    bool was_ready;
    if (initDone) {
        // After initialization, check if we're on a ready list.
        was_ready = (p->nextListNode != nullptr);
        p->popListNode();
    } else {
        // Nothing is ready before init.
        was_ready = false;
    }
    return was_ready;
}

void
Scheduler::requestUpdate(Channel *c)
{
    updateList.pushLast(c);
    if (!inEvaluate())
        scheduleReadyEvent();
}

void
Scheduler::scheduleReadyEvent()
{
    // Schedule the evaluate and update phases.
    if (!readyEvent.scheduled()) {
        schedule(&readyEvent);
        if (starvationEvent.scheduled())
            deschedule(&starvationEvent);
    }
}

void
Scheduler::scheduleStarvationEvent()
{
    if (!starvationEvent.scheduled()) {
        schedule(&starvationEvent);
        if (readyEvent.scheduled())
            deschedule(&readyEvent);
    }
}

void
Scheduler::runReady()
{
    scheduleTimeAdvancesEvent();

    bool empty = readyListMethods.empty() && readyListThreads.empty();
    lastReadyTick = getCurTick();

    // The evaluation phase.
    status(StatusEvaluate);
    do {
        yield();
    } while (getNextReady());
    _current = nullptr;

    if (!empty) {
        _numCycles++;
        _changeStamp++;
    }

    if (_stopNow) {
        status(StatusOther);
        return;
    }

    runUpdate();
    if (!traceFiles.empty())
        trace(true);
    runDelta();

    if (!runToTime && starved())
        scheduleStarvationEvent();

    if (runOnce)
        schedulePause();

    status(StatusOther);
}

void
Scheduler::runUpdate()
{
    status(StatusUpdate);

    try {
        Channel *channel = updateList.getNext();
        while (channel) {
            channel->popListNode();
            channel->update();
            channel = updateList.getNext();
        }
    } catch (...) {
        throwToScMain();
    }
}

void
Scheduler::runDelta()
{
    status(StatusDelta);

    try {
        while (!deltas.empty())
            deltas.back()->run();
    } catch (...) {
        throwToScMain();
    }
}

void
Scheduler::pause()
{
    status(StatusPaused);
    kernel->status(::sc_core::SC_PAUSED);
    runOnce = false;
    if (scMainFiber.called() && !scMainFiber.finished())
        scMainFiber.run();
}

void
Scheduler::stop()
{
    status(StatusStopped);
    kernel->stop();

    clear();

    runOnce = false;
    if (scMainFiber.called() && !scMainFiber.finished())
        scMainFiber.run();
}

void
Scheduler::start(Tick max_tick, bool run_to_time)
{
    _started = true;
    status(StatusOther);
    runToTime = run_to_time;

    maxTick = max_tick;
    lastReadyTick = getCurTick();

    if (initDone) {
        if (!runToTime && starved())
            scheduleStarvationEvent();
        kernel->status(::sc_core::SC_RUNNING);
    }

    schedule(&maxTickEvent, maxTick);
    scheduleTimeAdvancesEvent();

    // Return to gem5 to let it run events, etc.
    Fiber::primaryFiber()->run();

    if (pauseEvent.scheduled())
        deschedule(&pauseEvent);
    if (stopEvent.scheduled())
        deschedule(&stopEvent);
    if (maxTickEvent.scheduled())
        deschedule(&maxTickEvent);
    if (starvationEvent.scheduled())
        deschedule(&starvationEvent);

    if (_throwToScMain) {
        const ::sc_core::sc_report *to_throw = _throwToScMain;
        _throwToScMain = nullptr;
        throw *to_throw;
    }
}

void
Scheduler::oneCycle()
{
    runOnce = true;
    scheduleReadyEvent();
    start(::MaxTick, false);
}

void
Scheduler::schedulePause()
{
    if (pauseEvent.scheduled())
        return;

    schedule(&pauseEvent);
}

void
Scheduler::throwToScMain()
{
    ::sc_core::sc_report report = reportifyException();
    _throwToScMain = &report;
    status(StatusOther);
    scMainFiber.run();
}

void
Scheduler::scheduleStop(bool finish_delta)
{
    if (stopEvent.scheduled())
        return;

    if (!finish_delta) {
        _stopNow = true;
        // If we're not supposed to finish the delta cycle, flush all
        // pending activity.
        clear();
    }
    schedule(&stopEvent);
}

void
Scheduler::trace(bool delta)
{
    for (auto tf: traceFiles)
        tf->trace(delta);
}

Scheduler scheduler;
Process *getCurrentProcess() { return scheduler.current(); }

namespace {

void
throwingReportHandler(const ::sc_core::sc_report &r,
                      const ::sc_core::sc_actions &)
{
    throw r;
}

} // anonymous namespace

const ::sc_core::sc_report
reportifyException()
{
    ::sc_core::sc_report_handler_proc old_handler = reportHandlerProc;
    ::sc_core::sc_report_handler::set_handler(&throwingReportHandler);

    try {
        try {
            // Rethrow the current exception so we can catch it and throw an
            // sc_report instead if it's not a type we recognize/can handle.
            throw;
        } catch (const ::sc_core::sc_report &) {
            // It's already a sc_report, so nothing to do.
            throw;
        } catch (const ::sc_core::sc_unwind_exception &) {
            panic("Kill/reset exception escaped a Process::run()");
        } catch (const std::exception &e) {
            SC_REPORT_ERROR(
                    sc_core::SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, e.what());
        } catch (const char *msg) {
            SC_REPORT_ERROR(
                    sc_core::SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, msg);
        } catch (...) {
            SC_REPORT_ERROR(
                    sc_core::SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_,
                    "UNKNOWN EXCEPTION");
        }
    } catch (const ::sc_core::sc_report &r) {
        ::sc_core::sc_report_handler::set_handler(old_handler);
        return r;
    }
    panic("No exception thrown in reportifyException.");
}

} // namespace sc_gem5
