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

#include <cassert>

#include "base/logging.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

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("(W509) module construction not properly completed: "
                "did you forget to add a sc_module_name parameter to "
                "your module constructor?", 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("(E533) module name stack is empty: "
                "did you forget to add a sc_module_name parameter to "
                "your module constructor?", nullptr);
    }
    return _new_module;
}

Module *
newModule()
{
    return _new_module;
}

std::list<Module *> allModules;

} // namespace sc_gem5
