/*
 * Copyright (c) 2013-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: Vasileios Spiliopoulos
 *          Akash Bagdia
 *          Stephan Diestelhorst
 */

/**
 * @file
 * DVFSHandler and DomainConfig class declaration used for managing voltage
 * and frequency scaling of the various DVFS domains in the system (with each
 * domain having their independent domain configuration information)
 */


#ifndef __SIM_DVFS_HANDLER_HH__
#define __SIM_DVFS_HANDLER_HH__

#include <vector>

#include "debug/DVFS.hh"
#include "params/ClockDomain.hh"
#include "params/DVFSHandler.hh"
#include "params/VoltageDomain.hh"
#include "sim/clock_domain.hh"
#include "sim/eventq.hh"
#include "sim/sim_object.hh"
#include "sim/voltage_domain.hh"

/**
 * DVFS Handler class, maintains a list of all the domains it can handle.
 * Each entry of that list is an object of the DomainConfig class, and the
 * handler uses the methods provided by that class to get access to the
 * configuration of each domain. The handler is responsible for setting/getting
 * clock periods and voltages from clock/voltage domains.
 * The handler acts the bridge between software configurable information
 * for each domain as provided to the controller and the hardware
 * implementation details for those domains.
 */
class DVFSHandler : public SimObject
{
  public:
    typedef DVFSHandlerParams Params;
    DVFSHandler(const Params *p);

    typedef SrcClockDomain::DomainID DomainID;
    typedef SrcClockDomain::PerfLevel PerfLevel;

    /**
     * Get the number of domains assigned to this DVFS handler.
     * @return Number of domains
     */
    uint32_t numDomains() const { return domainIDList.size(); }

    /**
     * Get the n-th domain ID, from the domains managed by this handler.
     * @return Domain ID
     */
    DomainID domainID(uint32_t index) const;

    /**
     * Check whether a domain ID is known to the handler or not.
     * @param domain_id Domain ID to check
     * @return Domain ID known to handler?
     */
    bool validDomainID(DomainID domain_id) const;

    /**
     * Get transition latency to switch between performance levels.
     * @return Transition latency
     */
    Tick transLatency() const { return _transLatency; }

    /**
     * Set a new performance level for the specified domain.  The actual update
     * will be delayed by transLatency().
     *
     * @param domain_id Software visible ID of the domain to be configured
     * @param perf_level Requested performance level (0 - fast, >0 slower)
     * @return status whether the setting was successful
     */
    bool perfLevel(DomainID domain_id, PerfLevel perf_level);

    /**
     * Get the current performance level of a domain.  While a change request is
     * in-flight, will return the current (i.e. old, unmodified) value.
     *
     * @param domain_id Domain ID to query
     * @return Current performance level of the specified domain
     */
    PerfLevel perfLevel(DomainID domain_id) const {
         assert(isEnabled());
         return findDomain(domain_id)->perfLevel();
    }

    /**
     * Read the clock period of the specified domain at the specified
     * performance level.
     * @param domain_id Domain ID to query
     * @param perf_level Performance level of interest
     * @return Clock period in ticks for the requested performance level of
     * the respective domain
     */
    Tick clkPeriodAtPerfLevel(DomainID domain_id, PerfLevel perf_level) const
    {
        SrcClockDomain *d = findDomain(domain_id);
        assert(d);
        PerfLevel n = d->numPerfLevels();
        if (perf_level < n)
            return d->clkPeriodAtPerfLevel(perf_level);

        warn("DVFSHandler %s reads illegal frequency level %u from "\
             "SrcClockDomain %s. Returning 0\n", name(), perf_level, d->name());
        return Tick(0);
    }

    /**
     * Read the voltage of the specified domain at the specified
     * performance level.
     * @param domain_id Domain ID to query
     * @param perf_level Performance level of interest
     * @return Voltage for the requested performance level of the respective
     * domain
     */
    double voltageAtPerfLevel(DomainID domain_id, PerfLevel perf_level) const
    {
        VoltageDomain *d = findDomain(domain_id)->voltageDomain();
        assert(d);
        PerfLevel n = d->numVoltages();
        if (perf_level < n)
            return d->voltage(perf_level);

        // Request outside of the range of the voltage domain
        if (n == 1) {
            DPRINTF(DVFS, "DVFS: Request for perf-level %i for single-point "\
                    "voltage domain %s.  Returning voltage at level 0: %.2f "\
                    "V\n", perf_level, d->name(), d->voltage(0));
            // Special case for single point voltage domain -> same voltage for
            // all points
            return d->voltage(0);
        }

        warn("DVFSHandler %s reads illegal voltage level %u from "\
             "VoltageDomain %s. Returning 0 V\n", name(), perf_level, d->name());
        return 0.;
    }

    /**
     * Get the total number of available performance levels.
     *
     * @param domain_id Domain ID to query
     * @return Number of performance levels that where configured for the
     * respective domain
     */
    PerfLevel numPerfLevels(PerfLevel domain_id) const
    {
        return findDomain(domain_id)->numPerfLevels();
    }

    /**
     * Check enable status of the DVFS handler, when the handler is disabled, no
     * request should be sent to the handler.
     * @return True, if the handler is enabled
     */
    bool isEnabled() const { return enableHandler; }

    void serialize(std::ostream &os);
    void unserialize(Checkpoint *cp, const std::string &section);

  private:
    typedef std::map<DomainID, SrcClockDomain*> Domains;
    Domains domains;

    /**
      * List of IDs avaiable in the domain list
      */
    std::vector<DomainID> domainIDList;

    /**
      * Clock domain of the system the handler is instantiated.
      */
    SrcClockDomain* sysClkDomain;

    /**
     * Search for a domain based on the domain ID.
     *
     * @param domain_id Domain ID to search for
     * @return Pointer to the source clock domain with matching ID.
     */
    SrcClockDomain *findDomain(DomainID domain_id) const {
        auto it = domains.find(domain_id);
        panic_if(it == domains.end(),
                 "DVFS: Could not find a domain for ID %d.\n",domain_id );
        return domains.find(domain_id)->second;
    }

    /**
     * Disabling the DVFS handler ensures that all the DVFS migration requests
     * are ignored. Domains remain at their default frequency and voltage.
     */
    bool enableHandler;


    /**
     * This corresponds to the maximum transition latency associated with the
     * hardware transitioning from a particular performance level to the other
     */
    const Tick _transLatency;



    /**
     * Update performance level event, encapsulates all the required information
     * for a future call to change a domain's performance level.
     */
    struct UpdateEvent : public Event {
        UpdateEvent() : Event(DVFS_Update_Pri), domainIDToSet(0),
                        perfLevelToSet(0) {}

        /**
         * Static pointer to the single DVFS hander for all the update events
         */
        static DVFSHandler *dvfsHandler;

        /**
         * ID of the domain that will be changed by the in-flight event
         */
        DomainID domainIDToSet;

        /**
         * Target performance level of the in-flight event
         */
        PerfLevel perfLevelToSet;

        /**
         * Updates the performance level by modifying the clock and the voltage
         * of the associated clocked objects.  Gets information from
         * domainIDToSet and perfLevelToSet for easier calling through an
         * event.
         */
        void updatePerfLevel();

        void process() { updatePerfLevel(); }
    };

    typedef std::map<DomainID, UpdateEvent> UpdatePerfLevelEvents;
    /**
     * Map from domain IDs -> perf level update events, records in-flight change
     * requests per domain ID.
     */
    UpdatePerfLevelEvents updatePerfLevelEvents;
};

#endif // __SIM_DVFS_HANDLER_HH__
