dvfs_handler.hh revision 11168
110249Sstephan.diestelhorst@arm.com/*
210249Sstephan.diestelhorst@arm.com * Copyright (c) 2013-2014 ARM Limited
310249Sstephan.diestelhorst@arm.com * All rights reserved
410249Sstephan.diestelhorst@arm.com *
510249Sstephan.diestelhorst@arm.com * The license below extends only to copyright in the software and shall
610249Sstephan.diestelhorst@arm.com * not be construed as granting a license to any other intellectual
710249Sstephan.diestelhorst@arm.com * property including but not limited to intellectual property relating
810249Sstephan.diestelhorst@arm.com * to a hardware implementation of the functionality of the software
910249Sstephan.diestelhorst@arm.com * licensed hereunder.  You may use the software subject to the license
1010249Sstephan.diestelhorst@arm.com * terms below provided that you ensure that this notice is replicated
1110249Sstephan.diestelhorst@arm.com * unmodified and in its entirety in all distributions of the software,
1210249Sstephan.diestelhorst@arm.com * modified or unmodified, in source code or in binary form.
1310249Sstephan.diestelhorst@arm.com *
1410249Sstephan.diestelhorst@arm.com * Redistribution and use in source and binary forms, with or without
1510249Sstephan.diestelhorst@arm.com * modification, are permitted provided that the following conditions are
1610249Sstephan.diestelhorst@arm.com * met: redistributions of source code must retain the above copyright
1710249Sstephan.diestelhorst@arm.com * notice, this list of conditions and the following disclaimer;
1810249Sstephan.diestelhorst@arm.com * redistributions in binary form must reproduce the above copyright
1910249Sstephan.diestelhorst@arm.com * notice, this list of conditions and the following disclaimer in the
2010249Sstephan.diestelhorst@arm.com * documentation and/or other materials provided with the distribution;
2110249Sstephan.diestelhorst@arm.com * neither the name of the copyright holders nor the names of its
2210249Sstephan.diestelhorst@arm.com * contributors may be used to endorse or promote products derived from
2310249Sstephan.diestelhorst@arm.com * this software without specific prior written permission.
2410249Sstephan.diestelhorst@arm.com *
2510249Sstephan.diestelhorst@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2610249Sstephan.diestelhorst@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2710249Sstephan.diestelhorst@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2810249Sstephan.diestelhorst@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2910249Sstephan.diestelhorst@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3010249Sstephan.diestelhorst@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3110249Sstephan.diestelhorst@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3210249Sstephan.diestelhorst@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3310249Sstephan.diestelhorst@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3410249Sstephan.diestelhorst@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3510249Sstephan.diestelhorst@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3610249Sstephan.diestelhorst@arm.com *
3710249Sstephan.diestelhorst@arm.com * Authors: Vasileios Spiliopoulos
3810249Sstephan.diestelhorst@arm.com *          Akash Bagdia
3910249Sstephan.diestelhorst@arm.com *          Stephan Diestelhorst
4010249Sstephan.diestelhorst@arm.com */
4110249Sstephan.diestelhorst@arm.com
4210249Sstephan.diestelhorst@arm.com/**
4310249Sstephan.diestelhorst@arm.com * @file
4410249Sstephan.diestelhorst@arm.com * DVFSHandler and DomainConfig class declaration used for managing voltage
4510249Sstephan.diestelhorst@arm.com * and frequency scaling of the various DVFS domains in the system (with each
4610249Sstephan.diestelhorst@arm.com * domain having their independent domain configuration information)
4710249Sstephan.diestelhorst@arm.com */
4810249Sstephan.diestelhorst@arm.com
4910249Sstephan.diestelhorst@arm.com
5010249Sstephan.diestelhorst@arm.com#ifndef __SIM_DVFS_HANDLER_HH__
5110249Sstephan.diestelhorst@arm.com#define __SIM_DVFS_HANDLER_HH__
5210249Sstephan.diestelhorst@arm.com
5310249Sstephan.diestelhorst@arm.com#include <vector>
5410249Sstephan.diestelhorst@arm.com
5510395Sstephan.diestelhorst@arm.com#include "debug/DVFS.hh"
5610249Sstephan.diestelhorst@arm.com#include "params/ClockDomain.hh"
5710249Sstephan.diestelhorst@arm.com#include "params/DVFSHandler.hh"
5810249Sstephan.diestelhorst@arm.com#include "params/VoltageDomain.hh"
5910249Sstephan.diestelhorst@arm.com#include "sim/clock_domain.hh"
6010249Sstephan.diestelhorst@arm.com#include "sim/eventq.hh"
6110249Sstephan.diestelhorst@arm.com#include "sim/sim_object.hh"
6210395Sstephan.diestelhorst@arm.com#include "sim/voltage_domain.hh"
6310249Sstephan.diestelhorst@arm.com
6410249Sstephan.diestelhorst@arm.com/**
6510249Sstephan.diestelhorst@arm.com * DVFS Handler class, maintains a list of all the domains it can handle.
6610249Sstephan.diestelhorst@arm.com * Each entry of that list is an object of the DomainConfig class, and the
6710249Sstephan.diestelhorst@arm.com * handler uses the methods provided by that class to get access to the
6810249Sstephan.diestelhorst@arm.com * configuration of each domain. The handler is responsible for setting/getting
6910249Sstephan.diestelhorst@arm.com * clock periods and voltages from clock/voltage domains.
7010249Sstephan.diestelhorst@arm.com * The handler acts the bridge between software configurable information
7110249Sstephan.diestelhorst@arm.com * for each domain as provided to the controller and the hardware
7210249Sstephan.diestelhorst@arm.com * implementation details for those domains.
7310249Sstephan.diestelhorst@arm.com */
7410249Sstephan.diestelhorst@arm.comclass DVFSHandler : public SimObject
7510249Sstephan.diestelhorst@arm.com{
7610249Sstephan.diestelhorst@arm.com  public:
7710249Sstephan.diestelhorst@arm.com    typedef DVFSHandlerParams Params;
7810249Sstephan.diestelhorst@arm.com    DVFSHandler(const Params *p);
7910249Sstephan.diestelhorst@arm.com
8010249Sstephan.diestelhorst@arm.com    typedef SrcClockDomain::DomainID DomainID;
8110249Sstephan.diestelhorst@arm.com    typedef SrcClockDomain::PerfLevel PerfLevel;
8210249Sstephan.diestelhorst@arm.com
8310249Sstephan.diestelhorst@arm.com    /**
8410395Sstephan.diestelhorst@arm.com     * Get the number of domains assigned to this DVFS handler.
8510395Sstephan.diestelhorst@arm.com     * @return Number of domains
8610395Sstephan.diestelhorst@arm.com     */
8710395Sstephan.diestelhorst@arm.com    uint32_t numDomains() const { return domainIDList.size(); }
8810395Sstephan.diestelhorst@arm.com
8910395Sstephan.diestelhorst@arm.com    /**
9010395Sstephan.diestelhorst@arm.com     * Get the n-th domain ID, from the domains managed by this handler.
9110395Sstephan.diestelhorst@arm.com     * @return Domain ID
9210395Sstephan.diestelhorst@arm.com     */
9310395Sstephan.diestelhorst@arm.com    DomainID domainID(uint32_t index) const;
9410395Sstephan.diestelhorst@arm.com
9510395Sstephan.diestelhorst@arm.com    /**
9610249Sstephan.diestelhorst@arm.com     * Check whether a domain ID is known to the handler or not.
9710249Sstephan.diestelhorst@arm.com     * @param domain_id Domain ID to check
9810249Sstephan.diestelhorst@arm.com     * @return Domain ID known to handler?
9910249Sstephan.diestelhorst@arm.com     */
10010249Sstephan.diestelhorst@arm.com    bool validDomainID(DomainID domain_id) const;
10110249Sstephan.diestelhorst@arm.com
10210249Sstephan.diestelhorst@arm.com    /**
10310249Sstephan.diestelhorst@arm.com     * Get transition latency to switch between performance levels.
10410249Sstephan.diestelhorst@arm.com     * @return Transition latency
10510249Sstephan.diestelhorst@arm.com     */
10610249Sstephan.diestelhorst@arm.com    Tick transLatency() const { return _transLatency; }
10710249Sstephan.diestelhorst@arm.com
10810249Sstephan.diestelhorst@arm.com    /**
10910249Sstephan.diestelhorst@arm.com     * Set a new performance level for the specified domain.  The actual update
11010249Sstephan.diestelhorst@arm.com     * will be delayed by transLatency().
11110249Sstephan.diestelhorst@arm.com     *
11210249Sstephan.diestelhorst@arm.com     * @param domain_id Software visible ID of the domain to be configured
11310249Sstephan.diestelhorst@arm.com     * @param perf_level Requested performance level (0 - fast, >0 slower)
11410249Sstephan.diestelhorst@arm.com     * @return status whether the setting was successful
11510249Sstephan.diestelhorst@arm.com     */
11610249Sstephan.diestelhorst@arm.com    bool perfLevel(DomainID domain_id, PerfLevel perf_level);
11710249Sstephan.diestelhorst@arm.com
11810249Sstephan.diestelhorst@arm.com    /**
11910249Sstephan.diestelhorst@arm.com     * Get the current performance level of a domain.  While a change request is
12010249Sstephan.diestelhorst@arm.com     * in-flight, will return the current (i.e. old, unmodified) value.
12110249Sstephan.diestelhorst@arm.com     *
12210249Sstephan.diestelhorst@arm.com     * @param domain_id Domain ID to query
12310249Sstephan.diestelhorst@arm.com     * @return Current performance level of the specified domain
12410249Sstephan.diestelhorst@arm.com     */
12510249Sstephan.diestelhorst@arm.com    PerfLevel perfLevel(DomainID domain_id) const {
12610249Sstephan.diestelhorst@arm.com         assert(isEnabled());
12710249Sstephan.diestelhorst@arm.com         return findDomain(domain_id)->perfLevel();
12810249Sstephan.diestelhorst@arm.com    }
12910249Sstephan.diestelhorst@arm.com
13010249Sstephan.diestelhorst@arm.com    /**
13110249Sstephan.diestelhorst@arm.com     * Read the clock period of the specified domain at the specified
13210249Sstephan.diestelhorst@arm.com     * performance level.
13310249Sstephan.diestelhorst@arm.com     * @param domain_id Domain ID to query
13410249Sstephan.diestelhorst@arm.com     * @param perf_level Performance level of interest
13510249Sstephan.diestelhorst@arm.com     * @return Clock period in ticks for the requested performance level of
13610249Sstephan.diestelhorst@arm.com     * the respective domain
13710249Sstephan.diestelhorst@arm.com     */
13810249Sstephan.diestelhorst@arm.com    Tick clkPeriodAtPerfLevel(DomainID domain_id, PerfLevel perf_level) const
13910249Sstephan.diestelhorst@arm.com    {
14010398Sstephan.diestelhorst@arm.com        SrcClockDomain *d = findDomain(domain_id);
14110398Sstephan.diestelhorst@arm.com        assert(d);
14210398Sstephan.diestelhorst@arm.com        PerfLevel n = d->numPerfLevels();
14310398Sstephan.diestelhorst@arm.com        if (perf_level < n)
14410398Sstephan.diestelhorst@arm.com            return d->clkPeriodAtPerfLevel(perf_level);
14510398Sstephan.diestelhorst@arm.com
14610398Sstephan.diestelhorst@arm.com        warn("DVFSHandler %s reads illegal frequency level %u from "\
14710398Sstephan.diestelhorst@arm.com             "SrcClockDomain %s. Returning 0\n", name(), perf_level, d->name());
14810398Sstephan.diestelhorst@arm.com        return Tick(0);
14910249Sstephan.diestelhorst@arm.com    }
15010249Sstephan.diestelhorst@arm.com
15110249Sstephan.diestelhorst@arm.com    /**
15210395Sstephan.diestelhorst@arm.com     * Read the voltage of the specified domain at the specified
15310395Sstephan.diestelhorst@arm.com     * performance level.
15410395Sstephan.diestelhorst@arm.com     * @param domain_id Domain ID to query
15510395Sstephan.diestelhorst@arm.com     * @param perf_level Performance level of interest
15610395Sstephan.diestelhorst@arm.com     * @return Voltage for the requested performance level of the respective
15710395Sstephan.diestelhorst@arm.com     * domain
15810395Sstephan.diestelhorst@arm.com     */
15910395Sstephan.diestelhorst@arm.com    double voltageAtPerfLevel(DomainID domain_id, PerfLevel perf_level) const
16010395Sstephan.diestelhorst@arm.com    {
16110398Sstephan.diestelhorst@arm.com        VoltageDomain *d = findDomain(domain_id)->voltageDomain();
16210398Sstephan.diestelhorst@arm.com        assert(d);
16310398Sstephan.diestelhorst@arm.com        PerfLevel n = d->numVoltages();
16410398Sstephan.diestelhorst@arm.com        if (perf_level < n)
16510398Sstephan.diestelhorst@arm.com            return d->voltage(perf_level);
16610398Sstephan.diestelhorst@arm.com
16710398Sstephan.diestelhorst@arm.com        // Request outside of the range of the voltage domain
16810398Sstephan.diestelhorst@arm.com        if (n == 1) {
16910398Sstephan.diestelhorst@arm.com            DPRINTF(DVFS, "DVFS: Request for perf-level %i for single-point "\
17010398Sstephan.diestelhorst@arm.com                    "voltage domain %s.  Returning voltage at level 0: %.2f "\
17110398Sstephan.diestelhorst@arm.com                    "V\n", perf_level, d->name(), d->voltage(0));
17210398Sstephan.diestelhorst@arm.com            // Special case for single point voltage domain -> same voltage for
17310398Sstephan.diestelhorst@arm.com            // all points
17410398Sstephan.diestelhorst@arm.com            return d->voltage(0);
17510398Sstephan.diestelhorst@arm.com        }
17610398Sstephan.diestelhorst@arm.com
17710398Sstephan.diestelhorst@arm.com        warn("DVFSHandler %s reads illegal voltage level %u from "\
17810398Sstephan.diestelhorst@arm.com             "VoltageDomain %s. Returning 0 V\n", name(), perf_level, d->name());
17910398Sstephan.diestelhorst@arm.com        return 0.;
18010395Sstephan.diestelhorst@arm.com    }
18110395Sstephan.diestelhorst@arm.com
18210395Sstephan.diestelhorst@arm.com    /**
18310249Sstephan.diestelhorst@arm.com     * Get the total number of available performance levels.
18410249Sstephan.diestelhorst@arm.com     *
18510249Sstephan.diestelhorst@arm.com     * @param domain_id Domain ID to query
18610249Sstephan.diestelhorst@arm.com     * @return Number of performance levels that where configured for the
18710249Sstephan.diestelhorst@arm.com     * respective domain
18810249Sstephan.diestelhorst@arm.com     */
18910249Sstephan.diestelhorst@arm.com    PerfLevel numPerfLevels(PerfLevel domain_id) const
19010249Sstephan.diestelhorst@arm.com    {
19110249Sstephan.diestelhorst@arm.com        return findDomain(domain_id)->numPerfLevels();
19210249Sstephan.diestelhorst@arm.com    }
19310249Sstephan.diestelhorst@arm.com
19410249Sstephan.diestelhorst@arm.com    /**
19510249Sstephan.diestelhorst@arm.com     * Check enable status of the DVFS handler, when the handler is disabled, no
19610249Sstephan.diestelhorst@arm.com     * request should be sent to the handler.
19710249Sstephan.diestelhorst@arm.com     * @return True, if the handler is enabled
19810249Sstephan.diestelhorst@arm.com     */
19910249Sstephan.diestelhorst@arm.com    bool isEnabled() const { return enableHandler; }
20010249Sstephan.diestelhorst@arm.com
20111168Sandreas.hansson@arm.com    void serialize(CheckpointOut &cp) const override;
20211168Sandreas.hansson@arm.com    void unserialize(CheckpointIn &cp) override;
20310249Sstephan.diestelhorst@arm.com
20410249Sstephan.diestelhorst@arm.com  private:
20510249Sstephan.diestelhorst@arm.com    typedef std::map<DomainID, SrcClockDomain*> Domains;
20610249Sstephan.diestelhorst@arm.com    Domains domains;
20710249Sstephan.diestelhorst@arm.com
20810249Sstephan.diestelhorst@arm.com    /**
20910395Sstephan.diestelhorst@arm.com      * List of IDs avaiable in the domain list
21010395Sstephan.diestelhorst@arm.com      */
21110395Sstephan.diestelhorst@arm.com    std::vector<DomainID> domainIDList;
21210395Sstephan.diestelhorst@arm.com
21310395Sstephan.diestelhorst@arm.com    /**
21410249Sstephan.diestelhorst@arm.com      * Clock domain of the system the handler is instantiated.
21510249Sstephan.diestelhorst@arm.com      */
21610249Sstephan.diestelhorst@arm.com    SrcClockDomain* sysClkDomain;
21710249Sstephan.diestelhorst@arm.com
21810249Sstephan.diestelhorst@arm.com    /**
21910249Sstephan.diestelhorst@arm.com     * Search for a domain based on the domain ID.
22010249Sstephan.diestelhorst@arm.com     *
22110249Sstephan.diestelhorst@arm.com     * @param domain_id Domain ID to search for
22210249Sstephan.diestelhorst@arm.com     * @return Pointer to the source clock domain with matching ID.
22310249Sstephan.diestelhorst@arm.com     */
22410249Sstephan.diestelhorst@arm.com    SrcClockDomain *findDomain(DomainID domain_id) const {
22510249Sstephan.diestelhorst@arm.com        auto it = domains.find(domain_id);
22610249Sstephan.diestelhorst@arm.com        panic_if(it == domains.end(),
22710249Sstephan.diestelhorst@arm.com                 "DVFS: Could not find a domain for ID %d.\n",domain_id );
22810249Sstephan.diestelhorst@arm.com        return domains.find(domain_id)->second;
22910249Sstephan.diestelhorst@arm.com    }
23010249Sstephan.diestelhorst@arm.com
23110249Sstephan.diestelhorst@arm.com    /**
23210249Sstephan.diestelhorst@arm.com     * Disabling the DVFS handler ensures that all the DVFS migration requests
23310249Sstephan.diestelhorst@arm.com     * are ignored. Domains remain at their default frequency and voltage.
23410249Sstephan.diestelhorst@arm.com     */
23510249Sstephan.diestelhorst@arm.com    bool enableHandler;
23610249Sstephan.diestelhorst@arm.com
23710249Sstephan.diestelhorst@arm.com
23810249Sstephan.diestelhorst@arm.com    /**
23910249Sstephan.diestelhorst@arm.com     * This corresponds to the maximum transition latency associated with the
24010249Sstephan.diestelhorst@arm.com     * hardware transitioning from a particular performance level to the other
24110249Sstephan.diestelhorst@arm.com     */
24210249Sstephan.diestelhorst@arm.com    const Tick _transLatency;
24310249Sstephan.diestelhorst@arm.com
24410249Sstephan.diestelhorst@arm.com
24510249Sstephan.diestelhorst@arm.com
24610249Sstephan.diestelhorst@arm.com    /**
24710249Sstephan.diestelhorst@arm.com     * Update performance level event, encapsulates all the required information
24810249Sstephan.diestelhorst@arm.com     * for a future call to change a domain's performance level.
24910249Sstephan.diestelhorst@arm.com     */
25010249Sstephan.diestelhorst@arm.com    struct UpdateEvent : public Event {
25110360Sandreas.hansson@arm.com        UpdateEvent() : Event(DVFS_Update_Pri), domainIDToSet(0),
25210360Sandreas.hansson@arm.com                        perfLevelToSet(0) {}
25310249Sstephan.diestelhorst@arm.com
25410249Sstephan.diestelhorst@arm.com        /**
25510249Sstephan.diestelhorst@arm.com         * Static pointer to the single DVFS hander for all the update events
25610249Sstephan.diestelhorst@arm.com         */
25710249Sstephan.diestelhorst@arm.com        static DVFSHandler *dvfsHandler;
25810249Sstephan.diestelhorst@arm.com
25910249Sstephan.diestelhorst@arm.com        /**
26010249Sstephan.diestelhorst@arm.com         * ID of the domain that will be changed by the in-flight event
26110249Sstephan.diestelhorst@arm.com         */
26210249Sstephan.diestelhorst@arm.com        DomainID domainIDToSet;
26310249Sstephan.diestelhorst@arm.com
26410249Sstephan.diestelhorst@arm.com        /**
26510249Sstephan.diestelhorst@arm.com         * Target performance level of the in-flight event
26610249Sstephan.diestelhorst@arm.com         */
26710249Sstephan.diestelhorst@arm.com        PerfLevel perfLevelToSet;
26810249Sstephan.diestelhorst@arm.com
26910249Sstephan.diestelhorst@arm.com        /**
27010249Sstephan.diestelhorst@arm.com         * Updates the performance level by modifying the clock and the voltage
27110249Sstephan.diestelhorst@arm.com         * of the associated clocked objects.  Gets information from
27210249Sstephan.diestelhorst@arm.com         * domainIDToSet and perfLevelToSet for easier calling through an
27310249Sstephan.diestelhorst@arm.com         * event.
27410249Sstephan.diestelhorst@arm.com         */
27510249Sstephan.diestelhorst@arm.com        void updatePerfLevel();
27610249Sstephan.diestelhorst@arm.com
27710249Sstephan.diestelhorst@arm.com        void process() { updatePerfLevel(); }
27810249Sstephan.diestelhorst@arm.com    };
27910249Sstephan.diestelhorst@arm.com
28010249Sstephan.diestelhorst@arm.com    typedef std::map<DomainID, UpdateEvent> UpdatePerfLevelEvents;
28110249Sstephan.diestelhorst@arm.com    /**
28210249Sstephan.diestelhorst@arm.com     * Map from domain IDs -> perf level update events, records in-flight change
28310249Sstephan.diestelhorst@arm.com     * requests per domain ID.
28410249Sstephan.diestelhorst@arm.com     */
28510249Sstephan.diestelhorst@arm.com    UpdatePerfLevelEvents updatePerfLevelEvents;
28610249Sstephan.diestelhorst@arm.com};
28710249Sstephan.diestelhorst@arm.com
28810249Sstephan.diestelhorst@arm.com#endif // __SIM_DVFS_HANDLER_HH__
289