/*
 * 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.
 */

#include "systemc/core/scheduler.hh"

#include "base/fiber.hh"
#include "base/logging.hh"
#include "sim/eventq.hh"
#include "sim/sim_exit.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), _throwUp(nullptr),
    starvationEvent(this, false, StarvationPriority),
    _elaborationDone(false), _started(false), _stopNow(false),
    _status(StatusOther), maxTick(::MaxTick),
    maxTickEvent(this, false, MaxTickPriority),
    timeAdvancesEvent(this, false, TimeAdvancesPriority), _numCycles(0),
    _changeStamp(0), _current(nullptr), initDone(false), runToTime(true),
    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 &ts: timeSlots) {
        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()
{
    runUpdate();

    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();
        }
    }

    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 (...) {
                throwUp();
            }
        }
    }
    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::asyncRequestUpdate(Channel *c)
{
    std::lock_guard<std::mutex> lock(asyncListMutex);
    asyncUpdateList.pushLast(c);
    hasAsyncUpdate = true;
}

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);
    if (hasAsyncUpdate) {
        std::lock_guard<std::mutex> lock(asyncListMutex);
        Channel *channel;
        while ((channel = asyncUpdateList.getNext()) != nullptr)
            updateList.pushLast(channel);
        hasAsyncUpdate = false;
    }

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

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

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

void
Scheduler::pause()
{
    status(StatusPaused);
    kernel->status(::sc_core::SC_PAUSED);
    runOnce = false;
    if (scMainFiber.called()) {
        if (!scMainFiber.finished())
            scMainFiber.run();
    } else {
        if (scMainFiber.finished())
            fatal("Pausing systemc after sc_main completed.");
        else
            exitSimLoopNow("systemc pause");
    }
}

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

    clear();

    runOnce = false;
    if (scMainFiber.called()) {
        if (!scMainFiber.finished())
            scMainFiber.run();
    } else {
        if (scMainFiber.finished())
            fatal("Stopping systemc after sc_main completed.");
        else
            exitSimLoopNow("systemc stop");
    }
}

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 (_throwUp) {
        const ::sc_core::sc_report *to_throw = _throwUp;
        _throwUp = nullptr;
        throw *to_throw;
    }
}

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

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

    schedule(&pauseEvent);
}

void
Scheduler::throwUp()
{
    if (scMainFiber.called() && !scMainFiber.finished()) {
        ::sc_core::sc_report report = reportifyException();
        _throwUp = &report;
        status(StatusOther);
        scMainFiber.run();
    } else {
        reportHandlerProc(reportifyException(),
                ::sc_core::sc_report_handler::get_catch_actions());
    }
}

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
