/*
 * 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/sensitivity.hh"

#include "base/logging.hh"
#include "systemc/core/event.hh"
#include "systemc/core/port.hh"
#include "systemc/core/process.hh"
#include "systemc/core/scheduler.hh"
#include "systemc/ext/channel/sc_in.hh"
#include "systemc/ext/channel/sc_inout.hh"
#include "systemc/ext/channel/sc_out.hh"
#include "systemc/ext/core/sc_export.hh"
#include "systemc/ext/core/sc_interface.hh"
#include "systemc/ext/core/sc_port.hh"

namespace sc_gem5
{

/*
 * Common sensitivity interface.
 */

void
Sensitivity::satisfy()
{
    process->satisfySensitivity(this);
}

bool
Sensitivity::notify(Event *e)
{
    if (process->disabled())
        return false;
    satisfy();
    return true;
}

bool
Sensitivity::ofMethod()
{
    return process->procKind() == sc_core::SC_METHOD_PROC_;
}


/*
 * Dynamic vs. static sensitivity.
 */

void
DynamicSensitivity::addToEvent(const ::sc_core::sc_event *e)
{
    Event::getFromScEvent(e)->addSensitivity(this);
}

void
DynamicSensitivity::delFromEvent(const ::sc_core::sc_event *e)
{
    Event::getFromScEvent(e)->delSensitivity(this);
}

void
StaticSensitivity::addToEvent(const ::sc_core::sc_event *e)
{
    Event::getFromScEvent(e)->addSensitivity(this);
}

void
StaticSensitivity::delFromEvent(const ::sc_core::sc_event *e)
{
    Event::getFromScEvent(e)->delSensitivity(this);
}


/*
 * Static sensitivities.
 */

void
newStaticSensitivityEvent(Process *p, const sc_core::sc_event *e)
{
    auto s = new StaticSensitivityEvent(p, e);
    s->addToEvent(s->event);
    p->addStatic(s);
}

void
newStaticSensitivityInterface(Process *p, const sc_core::sc_interface *i)
{
    auto s = new StaticSensitivityInterface(p, i);
    s->addToEvent(s->event);
    p->addStatic(s);
}

void
newStaticSensitivityPort(Process *p, const sc_core::sc_port_base *pb)
{
    auto s = new StaticSensitivityPort(p);
    Port *port = Port::fromPort(pb);
    port->sensitive(s);
    p->addStatic(s);
}

void
newStaticSensitivityExport(Process *p, const sc_core::sc_export_base *exp)
{
    auto s = new StaticSensitivityExport(p, exp);
    s->addToEvent(s->event);
    p->addStatic(s);
}

void
newStaticSensitivityFinder(Process *p, const sc_core::sc_event_finder *f)
{
    auto s = new StaticSensitivityFinder(p, f);
    Port *port = Port::fromPort(f->port());
    port->sensitive(s);
    p->addStatic(s);
}


StaticSensitivityInterface::StaticSensitivityInterface(
        Process *p, const sc_core::sc_interface *i) :
    Sensitivity(p), StaticSensitivity(p),
    SensitivityEvent(p, &i->default_event())
{}

StaticSensitivityExport::StaticSensitivityExport(
        Process *p, const sc_core::sc_export_base *exp) :
    Sensitivity(p), StaticSensitivity(p),
    SensitivityEvent(p, &exp->get_interface()->default_event())
{}

const ::sc_core::sc_event &
StaticSensitivityFinder::find(::sc_core::sc_interface *i)
{
    return finder->find_event(i);
}


/*
 * Dynamic sensitivities.
 */

void
newDynamicSensitivityEvent(Process *p, const sc_core::sc_event *e)
{
    auto s = new DynamicSensitivityEvent(p, e);
    s->addToEvent(s->event);
    p->setDynamic(s);
}

void
newDynamicSensitivityEventOrList(
        Process *p, const sc_core::sc_event_or_list *eol)
{
    auto s = new DynamicSensitivityEventOrList(p, eol);
    for (auto event: s->events)
        s->addToEvent(event);
    p->setDynamic(s);
}

void newDynamicSensitivityEventAndList(
        Process *p, const sc_core::sc_event_and_list *eal)
{
    auto s = new DynamicSensitivityEventAndList(p, eal);
    for (auto event: s->events)
        s->addToEvent(event);
    p->setDynamic(s);
}


DynamicSensitivityEventOrList::DynamicSensitivityEventOrList(
        Process *p, const sc_core::sc_event_or_list *eol) :
    Sensitivity(p), DynamicSensitivity(p), SensitivityEvents(p, eol->events)
{}

bool
DynamicSensitivityEventOrList::notify(Event *e)
{
    if (process->disabled())
        return false;

    events.erase(e->sc_event());

    // All the other events need this deleted from their lists since this
    // sensitivity has been satisfied without them triggering.
    for (auto le: events)
        delFromEvent(le);

    satisfy();
    return true;
}

DynamicSensitivityEventAndList::DynamicSensitivityEventAndList(
        Process *p, const sc_core::sc_event_and_list *eal) :
    Sensitivity(p), DynamicSensitivity(p), SensitivityEvents(p, eal->events)
{}

bool
DynamicSensitivityEventAndList::notify(Event *e)
{
    if (process->disabled())
        return false;

    events.erase(e->sc_event());

    // This sensitivity is satisfied if all events have triggered.
    if (events.empty())
        satisfy();

    return true;
}

} // namespace sc_gem5
