/*
 * Copyright (c) 2014 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * 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: Andrew Bardsley
 */

#include <cstdlib>
#include <sstream>

#include "base/str.hh"
#include "debug/CxxConfig.hh"
#include "mem/mem_object.hh"
#include "sim/cxx_manager.hh"
#include "sim/serialize.hh"

CxxConfigManager::CxxConfigManager(CxxConfigFileBase &configFile_) :
    configFile(configFile_), flags(configFile_.getFlags()),
    simObjectResolver(*this)
{
}

const CxxConfigDirectoryEntry &
CxxConfigManager::findObjectType(const std::string &object_name,
    std::string &object_type)
{
    if (!configFile.objectExists(object_name))
        throw Exception(object_name, "Can't find sim object");

    if (!configFile.getParam(object_name, "type", object_type))
        throw Exception(object_name, "Sim object has no 'type' field");

    if (cxx_config_directory.find(object_type) ==
        cxx_config_directory.end())
    {
        throw Exception(object_name, csprintf(
            "No sim object type %s is available", object_type));
    }

    const CxxConfigDirectoryEntry *entry = cxx_config_directory[object_type];

    return *entry;
}

std::string
CxxConfigManager::rename(const std::string &from_name)
{
    for (auto i = renamings.begin(); i != renamings.end(); ++ i) {
        const Renaming &renaming = *i;

        if (from_name.find(renaming.fromPrefix) == 0) {
            return renaming.toPrefix +
                from_name.substr(renaming.fromPrefix.length());
        }
    }

    return from_name;
}

std::string
CxxConfigManager::unRename(const std::string &to_name)
{
    for (auto i = renamings.begin(); i != renamings.end(); ++ i) {
        const Renaming &renaming = *i;

        if (to_name.find(renaming.toPrefix) == 0) {
            return renaming.fromPrefix +
                to_name.substr(renaming.toPrefix.length());
        }
    }

    return to_name;
}

static
std::string formatParamList(const std::vector<std::string> &param_values)
{
    std::ostringstream params;

    auto i = param_values.begin();
    auto end_i = param_values.end();

    params << '[';
    while (i != end_i) {
        params << (*i);
        ++i;

        if (i != end_i)
            params << ", ";
    }
    params << ']';

    return params.str();
}

SimObject *
CxxConfigManager::findObject(const std::string &object_name,
    bool visit_children)
{
    std::string instance_name = rename(object_name);

    if (object_name == "Null")
        return NULL;

    /* Already constructed */
    if (objectsByName.find(instance_name) != objectsByName.end())
        return objectsByName[instance_name];

    if (inVisit.find(instance_name) != inVisit.end())
        throw Exception(instance_name, "Cycle in configuration");

    std::string object_type;
    const CxxConfigDirectoryEntry &entry =
        findObjectType(object_name, object_type);

    SimObject *object = NULL;

    CxxConfigParams *object_params = findObjectParams(object_name);

    try {
        DPRINTF(CxxConfig, "Configuring sim object references for: %s"
            " (%s from object %s)\n", instance_name, object_type,
            object_name);

        /* Remember the path back to the top of the recursion to detect
         *  cycles */
        inVisit.insert(instance_name);

        /* Resolve pointed-to SimObjects by recursing into them */
        for (auto i = entry.parameters.begin();
            i != entry.parameters.end(); ++i)
        {
            const CxxConfigDirectoryEntry::ParamDesc *param = (*i).second;

            if (param->isSimObject) {
                if (param->isVector) {
                    std::vector<std::string> sub_object_names;

                    if (!configFile.getParamVector(object_name, param->name,
                        sub_object_names))
                    {
                        throw Exception(object_name, csprintf(
                            "Element not found: %s", param->name));
                    }

                    std::vector<SimObject *> sub_objects;

                    for (auto n = sub_object_names.begin();
                        n != sub_object_names.end(); ++n)
                    {
                        SimObject *sub_object = findObject(*n,
                            visit_children);

                        if (sub_object)
                            sub_objects.push_back(sub_object);
                    }

                    if (!object_params->setSimObjectVector(param->name,
                        sub_objects))
                    {
                        throw Exception(object_name, csprintf(
                            "Can't assign sim object element %s from \"%s\"",
                            param->name, formatParamList(sub_object_names)));
                    }

                    DPRINTF(CxxConfig, "Setting sim object(s): %s.%s=%s\n",
                        object_name, param->name,
                        formatParamList(sub_object_names));
                } else {
                    std::string sub_object_name;

                    if (!configFile.getParam(object_name, param->name,
                        sub_object_name))
                    {
                        throw Exception(object_name, csprintf(
                            "Element not found: %s", param->name));
                    }

                    SimObject *sub_object = findObject(sub_object_name,
                        visit_children);

                    if (sub_object) {
                        if (!object_params->setSimObject(param->name,
                            sub_object))
                        {
                            throw Exception(object_name, csprintf(
                                "Can't assign sim object element %s from"
                                " \"%s\"", param->name, sub_object_name));
                        }
                    }

                    DPRINTF(CxxConfig, "Setting sim object(s):"
                        " %s.%s=%s\n", object_name, param->name,
                        sub_object_name);
                }
            }
        }

        DPRINTF(CxxConfig, "Creating SimObject: %s\n", instance_name);
        object = object_params->simObjectCreate();

        if (!object) {
            throw Exception(object_name, csprintf("Couldn't create object of"
                " type: %s", object_type));
        }

        objectsByName[instance_name] = object;
        objectParamsByName[instance_name] = object_params;

        if (visit_children) {
            std::vector<std::string> children;
            configFile.getObjectChildren(object_name, children, true);

            /* Visit all your children */
            for (auto i = children.begin(); i != children.end(); ++i)
                findObject(*i, visit_children);
        }
    } catch (Exception &) {
        delete object_params;
        throw;
    }

    /* Mark that we've exited object
     *  construction and so 'find'ing this object again won't be a
     *  configuration loop */
    inVisit.erase(object_name);
    return object;
}

CxxConfigParams *
CxxConfigManager::findObjectParams(const std::string &object_name)
{
    std::string instance_name = rename(object_name);

    /* Already constructed */
    if (objectParamsByName.find(instance_name) != objectParamsByName.end())
        return objectParamsByName[instance_name];

    std::string object_type;
    const CxxConfigDirectoryEntry &entry =
        findObjectType(object_name, object_type);

    DPRINTF(CxxConfig, "Configuring parameters of object: %s (%s)\n",
        instance_name, object_type);

    CxxConfigParams *object_params = entry.makeParamsObject();

    try {
        /* Fill in the implicit parameters that don't necessarily
         *  appear in config files */
        object_params->setName(instance_name);

        /* Fill in parameters */
        for (auto i = entry.parameters.begin();
            i != entry.parameters.end(); ++i)
        {
            const CxxConfigDirectoryEntry::ParamDesc *param = (*i).second;

            if (!param->isSimObject) {
                /* Only handle non-SimObject parameters here (see below) */

                if (param->isVector) {
                    std::vector<std::string> param_values;

                    if (!configFile.getParamVector(object_name, param->name,
                        param_values))
                    {
                        throw Exception(object_name, csprintf(
                            "Element not found for parameter: %s",
                            param->name));
                    }

                    if (!object_params->setParamVector(param->name,
                        param_values, flags))
                    {
                        throw Exception(instance_name, csprintf(
                            "Bad parameter value: .%s=X=\"%s\"",
                            param->name, formatParamList(param_values)));
                    }

                    DPRINTF(CxxConfig, "Setting parameter"
                        " %s.%s=%s\n", instance_name, param->name,
                        formatParamList(param_values));
                } else {
                    std::string param_value;

                    if (!configFile.getParam(object_name, param->name,
                        param_value))
                    {
                        throw Exception(object_name, csprintf(
                            "Element not found for parameter: %s",
                            param->name));
                    }

                    if (!object_params->setParam(param->name, param_value,
                        flags))
                    {
                        throw Exception(instance_name, csprintf(
                            "Bad parameter value: .%s=X=\"%s\"",
                            param->name, param_value));
                    }

                    DPRINTF(CxxConfig, "Setting parameter %s.%s=%s\n",
                        instance_name, param->name, param_value);
                }
            }
        }

        /* Find the number of ports that will need binding and set the
         *  appropriate port_..._connection_count parameters */
        for (auto i = entry.ports.begin(); i != entry.ports.end(); ++i) {
            const CxxConfigDirectoryEntry::PortDesc *port = (*i).second;
            std::vector<std::string> peers;

            if (!configFile.getPortPeers(object_name, port->name, peers)) {
                DPRINTF(CxxConfig, "Port not found: %s.%s,"
                    " assuming there are no connections\n",
                    instance_name, port->name);
            }

            unsigned int peer_count = peers.size();

            /* It would be more efficient to split the peer list and
             *  save the values for peer binding later but that would
             *  require another annoying intermediate structure to
             *  hold for little performance increase */

            if (!object_params->setPortConnectionCount(port->name,
                peer_count))
            {
                throw Exception(instance_name, csprintf(
                    "Unconnected port: %s", port->name));
            }

            DPRINTF(CxxConfig, "Setting port connection count"
                " for: %s.%s to %d\n",
                instance_name, port->name, peer_count);
        }

        /* Set pointed-to SimObjects to NULL */
        for (auto i = entry.parameters.begin();
            i != entry.parameters.end(); ++i)
        {
            const CxxConfigDirectoryEntry::ParamDesc *param = (*i).second;

            if (param->isSimObject) {
                bool ret;

                DPRINTF(CxxConfig, "Nulling sim object reference: %s.%s\n",
                    instance_name, param->name);

                if (param->isVector) {
                    /* Clear the reference list. */
                    std::vector<SimObject *> empty;
                    ret = object_params->setSimObjectVector(param->name,
                        empty);
                } else {
                    ret = object_params->setSimObject(param->name, NULL);
                }

                if (!ret) {
                    throw Exception(instance_name, csprintf(
                        "Error nulling sim object reference(s): %s",
                        param->name));
                }
            }
        }
    } catch (Exception &) {
        delete object_params;
        throw;
    }

    objectParamsByName[instance_name] = object_params;

    return object_params;
}

void
CxxConfigManager::findAllObjects()
{
    std::vector<std::string> objects;
    configFile.getAllObjectNames(objects);

    /* Sort the object names to get a consistent initialisation order
     *  even with config file reorganisation */
    std::sort(objects.begin(), objects.end());

    for (auto i = objects.begin(); i != objects.end(); ++i)
        findObject(*i);

    /* Set the traversal order for further iterators */
    objectsInOrder.clear();
    findTraversalOrder("root");
}

void
CxxConfigManager::findTraversalOrder(const std::string &object_name)
{
    SimObject *object = findObject(object_name);

    if (object) {
        objectsInOrder.push_back(object);

        std::vector<std::string> children;
        configFile.getObjectChildren(object_name, children, true);

        /* Visit all your children */
        for (auto i = children.begin(); i != children.end(); ++i)
            findTraversalOrder(*i);
    }
}

void
CxxConfigManager::bindAllPorts()
{
    for (auto i = objectsInOrder.begin(); i != objectsInOrder.end(); ++i)
        bindObjectPorts(*i);
}

void
CxxConfigManager::bindPort(
    SimObject *master_object, const std::string &master_port_name,
    PortID master_port_index,
    SimObject *slave_object, const std::string &slave_port_name,
    PortID slave_port_index)
{
    MemObject *master_mem_object = dynamic_cast<MemObject *>(master_object);
    MemObject *slave_mem_object = dynamic_cast<MemObject *>(slave_object);

    if (!master_mem_object) {
        throw Exception(master_object->name(), csprintf(
            "Object isn't a mem object and so can have master port:"
            " %s[%d]", master_port_name, master_port_index));
    }

    if (!slave_mem_object) {
        throw Exception(slave_object->name(), csprintf(
            "Object isn't a mem object and so can have slave port:"
            " %s[%d]", slave_port_name, slave_port_index));
    }

    /* FIXME, check slave_port_index against connection_count
     *  defined for port, need getPortConnectionCount and a
     *  getCxxConfigDirectoryEntry for each object. */

    /* It would be nice to be able to catch the errors from these calls. */
    BaseMasterPort &master_port = master_mem_object->getMasterPort(
        master_port_name, master_port_index);
    BaseSlavePort &slave_port = slave_mem_object->getSlavePort(
        slave_port_name, slave_port_index);

    if (master_port.isConnected()) {
        throw Exception(master_object->name(), csprintf(
            "Master port: %s[%d] is already connected\n", master_port_name,
            master_port_index));
    }

    if (slave_port.isConnected()) {
        throw Exception(slave_object->name(), csprintf(
            "Slave port: %s[%d] is already connected\n", slave_port_name,
            slave_port_index));
    }

    DPRINTF(CxxConfig, "Binding port %s.%s[%d]"
        " to %s:%s[%d]\n",
        master_object->name(), master_port_name, master_port_index,
        slave_object->name(), slave_port_name, slave_port_index);

    master_port.bind(slave_port);
}

void
CxxConfigManager::bindMasterPort(SimObject *object,
    const CxxConfigDirectoryEntry::PortDesc &port,
    const std::vector<std::string> &peers)
{
    unsigned int master_port_index = 0;

    for (auto peer_i = peers.begin(); peer_i != peers.end();
        ++peer_i)
    {
        const std::string &peer = *peer_i;
        std::string slave_object_name;
        std::string slave_port_name;
        unsigned int slave_port_index;

        parsePort(peer, slave_object_name, slave_port_name,
            slave_port_index);

        std::string slave_instance_name = rename(slave_object_name);

        if (objectsByName.find(slave_instance_name) == objectsByName.end()) {
            throw Exception(object->name(), csprintf(
                "Can't find slave port object: %s", slave_instance_name));
        }

        SimObject *slave_object = objectsByName[slave_instance_name];

        bindPort(object, port.name, master_port_index,
            slave_object, slave_port_name, slave_port_index);

        master_port_index++;
    }
}

void
CxxConfigManager::bindObjectPorts(SimObject *object)
{
    /* We may want to separate object->name() from the name in configuration
     *  later to allow (for example) repetition of fragments of configs */
    const std::string &instance_name = object->name();

    std::string object_name = unRename(instance_name);

    std::string object_type;
    const CxxConfigDirectoryEntry &entry =
        findObjectType(object_name, object_type);

    DPRINTF(CxxConfig, "Binding ports of object: %s (%s)\n",
        instance_name, object_type);

    for (auto i = entry.ports.begin(); i != entry.ports.end(); ++i) {
        const CxxConfigDirectoryEntry::PortDesc *port = (*i).second;

        DPRINTF(CxxConfig, "Binding port: %s.%s\n", instance_name,
            port->name);

        std::vector<std::string> peers;
        configFile.getPortPeers(object_name, port->name, peers);

        /* Only handle master ports as binding only needs to happen once
         *  for each observed pair of ports */
        if (port->isMaster) {
            if (!port->isVector && peers.size() > 1) {
                throw Exception(instance_name, csprintf(
                    "Too many connections to non-vector port %s (%d)\n",
                    port->name, peers.size()));
            }

            bindMasterPort(object, *port, peers);
        }
    }
}

void
CxxConfigManager::parsePort(const std::string &inp,
    std::string &path, std::string &port, unsigned int &index)
{
    std::size_t dot_i = inp.rfind('.');
    std::size_t open_square_i = inp.rfind('[');

    if (dot_i == std::string::npos) {
        DPRINTF(CxxConfig, "Bad port string: %s\n", inp);
        path = "";
        port = "";
        index = 0;
    } else {
        path = std::string(inp, 0, dot_i);

        if (open_square_i == std::string::npos) {
            /* Singleton port */
            port = std::string(inp, dot_i + 1, inp.length() - dot_i);
            index = 0;
        } else {
            /* Vectored port elemnt */
            port = std::string(inp, dot_i + 1, (open_square_i - 1) - dot_i);
            index = std::atoi(inp.c_str() + open_square_i + 1);
        }
    }
}

void
CxxConfigManager::forEachObject(void (SimObject::*mem_func)())
{
    for (auto i = objectsInOrder.begin(); i != objectsInOrder.end(); ++i)
        ((*i)->*mem_func)();
}

void
CxxConfigManager::instantiate(bool build_all)
{
    if (build_all) {
        findAllObjects();
        bindAllPorts();
    }

    DPRINTF(CxxConfig, "Initialising all objects\n");
    forEachObject(&SimObject::init);

    DPRINTF(CxxConfig, "Registering stats\n");
    forEachObject(&SimObject::regStats);

    DPRINTF(CxxConfig, "Registering probe points\n");
    forEachObject(&SimObject::regProbePoints);

    DPRINTF(CxxConfig, "Connecting probe listeners\n");
    forEachObject(&SimObject::regProbeListeners);
}

void
CxxConfigManager::initState()
{
    DPRINTF(CxxConfig, "Calling initState on all objects\n");
    forEachObject(&SimObject::initState);
}

void
CxxConfigManager::startup()
{
    DPRINTF(CxxConfig, "Starting up all objects\n");
    forEachObject(&SimObject::startup);
}

unsigned int
CxxConfigManager::drain(DrainManager *drain_manager)
{
    unsigned int ret = 0;

    for (auto i = objectsInOrder.begin(); i != objectsInOrder.end(); ++ i)
        ret += (*i)->drain(drain_manager);

    return ret;
}

void
CxxConfigManager::drainResume()
{
    forEachObject(&SimObject::drainResume);
}

void
CxxConfigManager::serialize(std::ostream &os)
{
    for (auto i = objectsInOrder.begin(); i != objectsInOrder.end(); ++ i) {
        // (*i)->nameOut(os); FIXME, change access spec. for nameOut
        os << '[' << (*i)->name() << "]\n";
        (*i)->serialize(os);
    }
}

void
CxxConfigManager::loadState(Checkpoint *checkpoint)
{
    for (auto i = objectsInOrder.begin(); i != objectsInOrder.end(); ++ i)
        (*i)->loadState(checkpoint);
}

void
CxxConfigManager::deleteObjects()
{
    for (auto i = objectsInOrder.rbegin(); i != objectsInOrder.rend(); ++i) {
        DPRINTF(CxxConfig, "Freeing sim object: %s\n", (*i)->name());
        delete *i;
    }

    for (auto i = objectParamsByName.rbegin();
        i != objectParamsByName.rend(); ++i)
    {
        CxxConfigParams *params = (*i).second;

        DPRINTF(CxxConfig, "Freeing sim object params: %s\n",
            params->getName());
        delete params;
    }

    objectsInOrder.clear();
    objectsByName.clear();
}

void
CxxConfigManager::setParam(const std::string &object_name,
    const std::string &param_name, const std::string &param_value)
{
    CxxConfigParams *params = findObjectParams(object_name);

    if (!params->setParam(param_name, param_value, flags)) {
        throw Exception(object_name, csprintf("Bad parameter value:"
            " .%s=X=\"%s\"", param_name, param_value));
    } else {
        std::string instance_name = rename(object_name);

        DPRINTF(CxxConfig, "Setting parameter %s.%s=%s\n",
            instance_name, param_name, param_value);
    }
}

void
CxxConfigManager::setParamVector(const std::string &object_name,
    const std::string &param_name,
    const std::vector<std::string> &param_values)
{
    CxxConfigParams *params = findObjectParams(object_name);

    if (!params->setParamVector(param_name, param_values, flags)) {
        throw Exception(object_name, csprintf("Bad vector parameter value:"
            " .%s=X=\"%s\"", param_name, formatParamList(param_values)));
    } else {
        std::string instance_name = rename(object_name);

        DPRINTF(CxxConfig, "Setting parameter %s.%s=\"%s\"\n",
            instance_name, param_name, formatParamList(param_values));
    }
}

void CxxConfigManager::addRenaming(const Renaming &renaming)
{
    renamings.push_back(renaming);
}
