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

#include "systemc/core/scheduler.hh"
#include "systemc/ext/channel/messages.hh"
#include "systemc/ext/channel/sc_signal.hh"
#include "systemc/ext/core/sc_main.hh"

namespace sc_gem5
{

ScSignalBase::ScSignalBase(const char *name) :
    sc_core::sc_prim_channel(name), _changeStamp(~0ULL),
    _gem5WriterPort(nullptr)
{}

ScSignalBase::~ScSignalBase() {}

const sc_core::sc_event &
ScSignalBase::defaultEvent() const
{
    return valueChangedEvent();
}

const sc_core::sc_event &
ScSignalBase::valueChangedEvent() const
{
    return _valueChangedEvent;
}

bool
ScSignalBase::event() const
{
    return _changeStamp == getChangeStamp();
}

void
ScSignalBase::_signalChange()
{
    _changeStamp = getChangeStamp();
    _valueChangedEvent.notify(sc_core::SC_ZERO_TIME);
}

void
ScSignalBaseBinary::_signalPosedge()
{
    _posStamp = getChangeStamp();
    _posedgeEvent.notify(sc_core::SC_ZERO_TIME);
}

void
ScSignalBaseBinary::_signalNegedge()
{
    _negStamp = getChangeStamp();
    _negedgeEvent.notify(sc_core::SC_ZERO_TIME);
}

namespace
{

void
reportSignalError(ScSignalBase *sig, sc_core::sc_object *first,
        sc_core::sc_object *second, bool delta_conflict=false)
{
    std::ostringstream ss;
    ss << "\n signal " << "`" << sig->name() << "' (" << sig->kind() << ")";
    ss << "\n first driver `" << first->name() << "' (" <<
        first->kind() << ")";
    ss << "\n second driver `" << second->name() << "' (" <<
        second->kind() << ")";
    if (delta_conflict) {
        ss << "\n conflicting write in delta cycle " <<
            sc_core::sc_delta_count();
    }
    SC_REPORT_ERROR(sc_core::SC_ID_MORE_THAN_ONE_SIGNAL_DRIVER_,
            ss.str().c_str());
}

} // anonymous namespace

WriteChecker<sc_core::SC_ONE_WRITER>::WriteChecker(ScSignalBase *_sig) :
    sig(_sig), firstPort(nullptr), proc(nullptr), writeStamp(~0ULL)
{}

void
WriteChecker<sc_core::SC_ONE_WRITER>::checkPort(sc_core::sc_port_base &port,
        std::string iface_type_name, std::string out_name)
{
    if (iface_type_name == out_name) {
        if (firstPort)
            reportSignalError(sig, firstPort, &port);
        firstPort = &port;
    }
}

void
WriteChecker<sc_core::SC_ONE_WRITER>::checkWriter()
{
    Process *p = scheduler.current();
    if (!p)
        return;
    uint64_t stamp = getChangeStamp();
    if (proc && proc != p)
        reportSignalError(sig, proc, p);
    proc = p;
    writeStamp = stamp;
}

WriteChecker<sc_core::SC_MANY_WRITERS>::WriteChecker(ScSignalBase *_sig) :
    sig(_sig), proc(nullptr), writeStamp(~0ULL)
{}

void
WriteChecker<sc_core::SC_MANY_WRITERS>::checkPort(sc_core::sc_port_base &port,
        std::string iface_type_name, std::string out_name)
{
    return;
}

void
WriteChecker<sc_core::SC_MANY_WRITERS>::checkWriter()
{
    Process *p = scheduler.current();
    if (!p)
        return;
    uint64_t stamp = getChangeStamp();
    if (writeStamp == stamp && proc && proc != p)
        reportSignalError(sig, proc, p, writeStamp == stamp);
    proc = p;
    writeStamp = stamp;
}

ScSignalBaseBinary::ScSignalBaseBinary(const char *_name) :
    ScSignalBase(_name), _posStamp(~0ULL), _negStamp(~0ULL)
{}

const sc_core::sc_event &
ScSignalBaseBinary::posedgeEvent() const
{
    return _posedgeEvent;
}

const sc_core::sc_event &
ScSignalBaseBinary::negedgeEvent() const
{
    return _negedgeEvent;
}

bool
ScSignalBaseBinary::posedge() const
{
    return _posStamp == getChangeStamp();
}

bool
ScSignalBaseBinary::negedge() const
{
    return _negStamp == getChangeStamp();
}

void
ScSignalBaseBinary::_signalReset(sc_gem5::Reset *r)
{
    r->update();
}

void
ScSignalBaseBinary::_signalReset()
{
    for (auto r: _resets)
        _signalReset(r);
}

} // namespace sc_gem5
