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

/**
 * @file
 *
 *  C++-only configuration and instantiation support.  This allows a
 *  config to be read back from a config file and instantiated without
 *  Python.  Useful if you want to embed gem5 within a larger system
 *  without carrying the integration cost of the fully-featured
 *  configuration system.
 *
 *  This file contains the config loading/storing manager class
 */

#ifndef __SIM_CXX_MANAGER_HH__
#define __SIM_CXX_MANAGER_HH__

#include <list>
#include <map>
#include <set>
#include <string>
#include <vector>

#include "base/cprintf.hh"
#include "sim/cxx_config.hh"

class Checkpoint;

/** This class allows a config file to be read into gem5 (generating the
 *  appropriate SimObjects) from C++ */
class CxxConfigManager
{
  protected:
    /** Configuration file being read */
    CxxConfigFileBase &configFile;

    /** Flags to pass to affect param setting */
    CxxConfigParams::Flags flags;

  public:
    /** Exception for instantiate/post-instantiate errors */
    class Exception : public std::exception
    {
      public:
        std::string name;
        std::string message;

      public:
        Exception(const std::string &name_, const std::string &message_) :
            name(name_), message(message_)
        { }

        const char *what() const throw() { return message.c_str(); }

        ~Exception() throw() { }
    };

    /** Name substitution when instantiating any object whose name starts
     *  with fromPrefix.  Where both renamed and unrenamed names are used
     *  in the code, `object' as part of a name usually refers to the
     *  unrenamed name (the name as it appears in the config file) and
     *  `instance' is part of the renamed name */
    struct Renaming
    {
        std::string fromPrefix;
        std::string toPrefix;

        Renaming(const std::string &from_prefix,
            const std::string &to_prefix) :
            fromPrefix(from_prefix),
            toPrefix(to_prefix)
        { }
    };

  public:
    /** SimObject indexed by name */
    std::map<std::string, SimObject *> objectsByName;

    /** ...Params objects created by this manager */
    std::map<std::string, CxxConfigParams *> objectParamsByName;

    /** SimObjects in order.  This is populated by findAllObjects */
    std::list<SimObject *> objectsInOrder;

  protected:
    /** While configuring, inVisit contains names of SimObjects visited in
     *  this recursive configuration walk */
    std::set<std::string> inVisit;

    /** All the renamings applicable when instantiating objects */
    std::list<Renaming> renamings;

    /** Bind a single connection between two objects' ports */
    void bindPort(SimObject *masterObject, const std::string &masterPort,
        PortID masterPortIndex, SimObject *slaveObject,
        const std::string &slavePort, PortID slavePortIndex);

    /** Bind a single (possibly vectored) master port to peers from the
     *  unparsed list peers with elements in the .ini connection format:
     *  path(.path)*.port[index] */
    void bindMasterPort(SimObject *object,
        const CxxConfigDirectoryEntry::PortDesc &port,
        const std::vector<std::string> &peers);

    /** Apply the first matching renaming in renamings to the given name */
    std::string rename(const std::string &from_name);

    /** Apply the first matching renaming in reverse (toPrefix -> fromPrefix
     *  for the given name */
    std::string unRename(const std::string &to_name);

  protected:
    /** Bind the ports of all the objects in objectInOrder order.
     *  Also */
    void bindAllPorts();

    /** Class for resolving SimObject names to SimObjects usable by the
     *  checkpoint restore mechanism */
    class SimObjectResolver : public ::SimObjectResolver
    {
      protected:
        CxxConfigManager &configManager;

      public:
        SimObjectResolver(CxxConfigManager &configManager_) :
            configManager(configManager_)
        { }

        SimObject *resolveSimObject(const std::string &name)
        { return &(configManager.getObject<SimObject>(name)); }
    };

    /** Singleton instance of SimObjectResolver */
    SimObjectResolver simObjectResolver;

  public:
    CxxConfigManager(CxxConfigFileBase &configFile_);

    /** Find the type field for a named object and return both the
     *  name of the type to object_type and the object's directory
     *  entry as the return value */
    const CxxConfigDirectoryEntry &findObjectType(
        const std::string &object_name, std::string &object_type);

    /** Add a name prefix renaming to those currently applied.  Call this
     *  before trying to instantiate any object as the name mappings are
     *  not applied to the config tree read from the config file but are
     *  applied while processing instantiations */
    void addRenaming(const Renaming &renaming);

  public:
    /** Bind the ports of a single SimObject */
    void bindObjectPorts(SimObject *object);

    /** Walk the configuration starting with object object_name and fill
     *  in all the elements of this object on the way.  This involves:
     *  <ul>
     *    <li>Calling findObjectParams to make the ...Params object
     *      If findObjectParams has already been called for this object,
     *      the ...Params object generated by that called (stored in
     *      (objectParamsByName[object_name] will be used)</li>
     *    <li>Populating the ...Params object references to other
     *      SimObjects by recursively descending into the trees formed
     *      by SimObject references</li>
     *    <li>Building the final SimObject and adding it to
     *      objectsByName</li>
     *    <li>If visit_children is true, recursively visit all this
     *      object's children and build/find them too</li>
     *  </ul>
     *  After the first call, this function will return
     *  objectsByName[object_name] */
    SimObject *findObject(const std::string &object_name,
        bool visit_children = false);

    /** Find the parameters for the named object.  Returns NULL if the
     *  object isn't in the configuration.  For the first call with a
     *  particular object name, a new CxxConfigParams descended object
     *  is made with the configuration file contents for this object.
     *  This involves populating that ...Params object with:
     *  <ul>
     *    <li>parameter values from the configuration file</li>
     *    <li>port connection connection counts from the connection counts
     *      indicated by the number of peer ports in the configuration
     *      file</li>
     *    <li>nulled (or vector<>::clear'ed) SimObject references for
     *      SimObject-values parameters</li>
     *  </ul>
     *  The ...Params object is then added to objectParamsByName
     *  After the first call, this function will return
     *  objectParamsByName[object_name] */
    CxxConfigParams *findObjectParams(const std::string &object_name);

    /** Populate objectsInOrder with a preorder, depth first traversal from
     *  the given object name down through all its children */
    void findTraversalOrder(const std::string &object_name);

    /** Find an object from objectsByName with a type-checking cast.
     *  This function is provided for manipulating objects after
     *  instantiate as it assumes the named object exists. */
    template<typename SimObjectType>
    SimObjectType &
    getObject(const std::string &object_name)
    {
        if (objectsByName.find(object_name) == objectsByName.end()) {
            throw Exception("", csprintf("No sim object named: %s",
                object_name));
        }

        SimObjectType *object = dynamic_cast<SimObjectType *>(
            objectsByName[object_name]);

        if (!object) {
            throw Exception("", csprintf("Sim object: %s  has the wrong"
                " type", object_name));
        }

        return *object;
    }

    /** Perform mem_func on each SimObject */
    void forEachObject(void (SimObject::*mem_func)());

    /** Find all objects by iterating over the object names in the config
     *  file with findObject.  Also populate the traversal order */
    void findAllObjects();

    /** Parse a port string of the form 'path(.path)*.port[index]' into
     *  path, port and index */
    static void parsePort(const std::string &inp,
        std::string &path, std::string &port, unsigned int &index);

    /** Build all objects (if build_all is true, otherwise objects must
     *  have been individually findObject-ed and added to the traversal
     *  order) and perform all the configuration specific actions up to,
     *  but not including initState.
     *
     *  If you want to set some parameters before completing instantiation,
     *  call findObjectParams on the objects you want to modify, then call
     *  instantiate */
    void instantiate(bool build_all = true);

    /** Call initState on all objects */
    void initState();

    /** Call startup on all objects */
    void startup();

    /** Drain all objects */
    unsigned int drain(DrainManager *drain_manager);

    /** Resume from drain */
    void drainResume();

    /** Serialize (checkpoint) all objects to the given stream */
    void serialize(std::ostream &os);

    /** Load all objects' state from the given Checkpoint */
    void loadState(Checkpoint *checkpoint);

    /** Delete all objects and clear objectsByName and objectsByOrder */
    void deleteObjects();

    /** Get the resolver used to map SimObject names to SimObjects for
     *  checkpoint restore */
    SimObjectResolver &getSimObjectResolver() { return simObjectResolver; }

    /** Convenience functions for calling set... member functions on a
     *  CxxConfigParams for an object.  These functions throw Exception
     *  rather than return a bool on failure */
    void setParam(const std::string &object_name,
        const std::string &param_name, const std::string &param_value);
    void setParamVector(const std::string &object_name,
        const std::string &param_name,
        const std::vector<std::string> &param_values);
};

#endif // __SIM_CXX_MANAGER_HH__
