/*
 * 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 "base/logging.hh"
#include "systemc/core/process.hh"
#include "systemc/core/scheduler.hh"
#include "systemc/ext/core/sc_main.hh"
#include "systemc/ext/core/sc_process_handle.hh"

namespace sc_core
{

const char *
sc_unwind_exception::what() const throw()
{
    return _isReset ? "RESET" : "KILL";
}

bool
sc_unwind_exception::is_reset() const
{
    return _isReset;
}

sc_unwind_exception::sc_unwind_exception() : _isReset(false) {}
sc_unwind_exception::sc_unwind_exception(const sc_unwind_exception &e) :
    _isReset(e._isReset)
{}
sc_unwind_exception::~sc_unwind_exception() throw() {}


const char *
sc_process_b::name()
{
    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
    return "";
}

const char *
sc_process_b::kind()
{
    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
    return "";
}


sc_process_b *
sc_get_curr_process_handle()
{
    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
    return nullptr;
}


sc_process_handle::sc_process_handle() : _gem5_process(nullptr) {}

sc_process_handle::sc_process_handle(const sc_process_handle &handle) :
    _gem5_process(handle._gem5_process)
{
    if (_gem5_process)
        _gem5_process->incref();
}

sc_process_handle::sc_process_handle(sc_object *obj) :
    _gem5_process(dynamic_cast<::sc_gem5::Process *>(obj))
{
    if (_gem5_process)
        _gem5_process->incref();
}

sc_process_handle::~sc_process_handle()
{
    if (_gem5_process)
        _gem5_process->decref();
}


bool
sc_process_handle::valid() const
{
    return _gem5_process != nullptr;
}


sc_process_handle &
sc_process_handle::operator = (const sc_process_handle &handle)
{
    if (_gem5_process)
        _gem5_process->decref();
    _gem5_process = handle._gem5_process;
    if (_gem5_process)
        _gem5_process->incref();
    return *this;
}

bool
sc_process_handle::operator == (const sc_process_handle &handle) const
{
    return _gem5_process && handle._gem5_process &&
        (_gem5_process == handle._gem5_process);
}

bool
sc_process_handle::operator != (const sc_process_handle &handle) const
{
    return !(handle == *this);
}

bool
sc_process_handle::operator < (const sc_process_handle &other) const
{
    return _gem5_process < other._gem5_process;
}

void
sc_process_handle::swap(sc_process_handle &handle)
{
    ::sc_gem5::Process *temp = handle._gem5_process;
    handle._gem5_process = _gem5_process;
    _gem5_process = temp;
}


const char *
sc_process_handle::name() const
{
    return _gem5_process ? _gem5_process->name() : "";
}

sc_curr_proc_kind
sc_process_handle::proc_kind() const
{
    return _gem5_process ? _gem5_process->procKind() : SC_NO_PROC_;
}

const std::vector<sc_object *> &
sc_process_handle::get_child_objects() const
{
    static const std::vector<sc_object *> empty;
    return _gem5_process ? _gem5_process->get_child_objects() : empty;
}

const std::vector<sc_event *> &
sc_process_handle::get_child_events() const
{
    static const std::vector<sc_event *> empty;
    return _gem5_process ? _gem5_process->get_child_events() : empty;
}

sc_object *
sc_process_handle::get_parent_object() const
{
    return _gem5_process ? _gem5_process->get_parent_object() : nullptr;
}

sc_object *
sc_process_handle::get_process_object() const
{
    return _gem5_process;
}

bool
sc_process_handle::dynamic() const
{
    return _gem5_process ? _gem5_process->dynamic() : false;
}

bool
sc_process_handle::terminated() const
{
    return _gem5_process ? _gem5_process->terminated() : false;
}

const sc_event &
sc_process_handle::terminated_event() const
{
    static sc_event non_event;
    return _gem5_process ? _gem5_process->terminatedEvent() : non_event;
}


void
sc_process_handle::suspend(sc_descendent_inclusion_info include_descendants)
{
    if (!_gem5_process)
        return;
    _gem5_process->suspend(include_descendants == SC_INCLUDE_DESCENDANTS);
}

void
sc_process_handle::resume(sc_descendent_inclusion_info include_descendants)
{
    if (!_gem5_process)
        return;
    _gem5_process->resume(include_descendants == SC_INCLUDE_DESCENDANTS);
}

void
sc_process_handle::disable(sc_descendent_inclusion_info include_descendants)
{
    if (!_gem5_process)
        return;
    _gem5_process->disable(include_descendants == SC_INCLUDE_DESCENDANTS);
}

void
sc_process_handle::enable(sc_descendent_inclusion_info include_descendants)
{
    if (!_gem5_process)
        return;
    _gem5_process->enable(include_descendants == SC_INCLUDE_DESCENDANTS);
}

void
sc_process_handle::kill(sc_descendent_inclusion_info include_descendants)
{
    if (!_gem5_process)
        return;
    _gem5_process->kill(include_descendants == SC_INCLUDE_DESCENDANTS);
}

void
sc_process_handle::reset(sc_descendent_inclusion_info include_descendants)
{
    if (!_gem5_process)
        return;
    _gem5_process->reset(include_descendants == SC_INCLUDE_DESCENDANTS);
}

bool
sc_process_handle::is_unwinding()
{
    if (!_gem5_process) {
        //TODO This should generate a systemc style warning if the handle is
        //invalid.
        return false;
    } else {
        return _gem5_process->isUnwinding();
    }
}

const sc_event &
sc_process_handle::reset_event() const
{
    static sc_event non_event;
    return _gem5_process ? _gem5_process->resetEvent() : non_event;
}


void
sc_process_handle::sync_reset_on(
        sc_descendent_inclusion_info include_descendants)
{
    if (!_gem5_process)
        return;
    _gem5_process->syncResetOn(include_descendants == SC_INCLUDE_DESCENDANTS);
}

void
sc_process_handle::sync_reset_off(
        sc_descendent_inclusion_info include_descendants)
{
    if (!_gem5_process)
        return;
    _gem5_process->syncResetOff(include_descendants == SC_INCLUDE_DESCENDANTS);
}


sc_process_handle
sc_get_current_process_handle()
{
    if (sc_is_running())
        return sc_process_handle(::sc_gem5::scheduler.current());
    else
        return sc_process_handle(::sc_gem5::Process::newest());
}

bool
sc_is_unwinding()
{
    return sc_get_current_process_handle().is_unwinding();
}

bool sc_allow_process_control_corners;

} // namespace sc_core
