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

#include <cassert>

#include "base/logging.hh"
#include "systemc/ext/core/messages.hh"
#include "systemc/ext/core/sc_export.hh"
#include "systemc/ext/core/sc_port.hh"
#include "systemc/ext/utils/sc_report_handler.hh"

namespace sc_gem5
{

namespace
{

std::list<Module *> _modules;
Module *_new_module;

} // anonymous namespace

UniqueNameGen globalNameGen;

Module::Module(const char *name) :
    _name(name), _sc_mod(nullptr), _obj(nullptr), _ended(false),
    _deprecatedConstructor(false), bindingIndex(0)
{
    panic_if(_new_module, "Previous module not finished.\n");
    _new_module = this;
}

Module::~Module()
{
    // Aborted module construction?
    if (_new_module == this)
        _new_module = nullptr;

    // Attempt to pop now in case we're at the top of the stack, so that
    // a stale pointer to us isn't left floating around for somebody to trip
    // on.
    pop();

    allModules.remove(this);
}

void
Module::finish(Object *this_obj)
{
    assert(!_obj);
    _obj = this_obj;
    _modules.push_back(this);
    pushParentModule(this);
    try {
        _new_module = nullptr;
        // This is called from the constructor of this_obj, so it can't use
        // dynamic cast.
        sc_mod(static_cast<::sc_core::sc_module *>(this_obj->sc_obj()));
        allModules.emplace_back(this);
    } catch (...) {
        popParentModule();
        throw;
    }
}

void
Module::pop()
{
    if (_modules.empty() || _modules.back() != this)
        return;

    panic_if(_new_module, "Pop with unfinished module.\n");

    _modules.pop_back();
    popParentModule();
}

void
Module::bindPorts(std::vector<const ::sc_core::sc_bind_proxy *> &proxies)
{
    panic_if(proxies.size() > ports.size(),
            "Trying to bind %d interfaces/ports to %d ports.\n",
            proxies.size(), ports.size());

    auto proxyIt = proxies.begin();
    auto portIt = ports.begin();
    portIt += bindingIndex;
    for (; proxyIt != proxies.end(); proxyIt++, portIt++) {
        auto proxy = *proxyIt;
        auto port = *portIt;
        if (proxy->interface())
            port->vbind(*proxy->interface());
        else
            port->vbind(*proxy->port());
    }
    bindingIndex += proxies.size();
}

void
Module::beforeEndOfElaboration()
{
    pushParentModule(this);
    try {
        _sc_mod->before_end_of_elaboration();
        for (auto e: exports)
            e->before_end_of_elaboration();
    } catch (...) {
        popParentModule();
        throw;
    }
    popParentModule();
}

void
Module::endOfElaboration()
{
    if (_deprecatedConstructor && !_ended) {
        std::string msg = csprintf("module '%s'", name());
        SC_REPORT_WARNING(sc_core::SC_ID_END_MODULE_NOT_CALLED_, msg.c_str());
    }
    pushParentModule(this);
    try {
        _sc_mod->end_of_elaboration();
        for (auto e: exports)
            e->end_of_elaboration();
    } catch (...) {
        popParentModule();
        throw;
    }
    popParentModule();
}

void
Module::startOfSimulation()
{
    pushParentModule(this);
    try {
        _sc_mod->start_of_simulation();
        for (auto e: exports)
            e->start_of_simulation();
    } catch (...) {
        popParentModule();
        throw;
    }
    popParentModule();
}

void
Module::endOfSimulation()
{
    pushParentModule(this);
    try {
        _sc_mod->end_of_simulation();
        for (auto e: exports)
            e->end_of_simulation();
    } catch(...) {
        popParentModule();
        throw;
    }
    popParentModule();
}

Module *
currentModule()
{
    if (_modules.empty())
        return nullptr;
    return _modules.back();
}

Module *
newModuleChecked()
{
    if (!_new_module)
        SC_REPORT_ERROR(sc_core::SC_ID_MODULE_NAME_STACK_EMPTY_, "");
    return _new_module;
}

Module *
newModule()
{
    return _new_module;
}

std::list<Module *> allModules;

} // namespace sc_gem5
