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/DVFSHandler.hh"
5710249Sstephan.diestelhorst@arm.com#include "sim/clock_domain.hh"
5810249Sstephan.diestelhorst@arm.com#include "sim/eventq.hh"
5910249Sstephan.diestelhorst@arm.com#include "sim/sim_object.hh"
6010249Sstephan.diestelhorst@arm.com
6110249Sstephan.diestelhorst@arm.com/**
6210249Sstephan.diestelhorst@arm.com * DVFS Handler class, maintains a list of all the domains it can handle.
6310249Sstephan.diestelhorst@arm.com * Each entry of that list is an object of the DomainConfig class, and the
6410249Sstephan.diestelhorst@arm.com * handler uses the methods provided by that class to get access to the
6510249Sstephan.diestelhorst@arm.com * configuration of each domain. The handler is responsible for setting/getting
6610249Sstephan.diestelhorst@arm.com * clock periods and voltages from clock/voltage domains.
6710249Sstephan.diestelhorst@arm.com * The handler acts the bridge between software configurable information
6810249Sstephan.diestelhorst@arm.com * for each domain as provided to the controller and the hardware
6910249Sstephan.diestelhorst@arm.com * implementation details for those domains.
7010249Sstephan.diestelhorst@arm.com */
7110249Sstephan.diestelhorst@arm.comclass DVFSHandler : public SimObject
7210249Sstephan.diestelhorst@arm.com{
7310249Sstephan.diestelhorst@arm.com  public:
7410249Sstephan.diestelhorst@arm.com    typedef DVFSHandlerParams Params;
7510249Sstephan.diestelhorst@arm.com    DVFSHandler(const Params *p);
7610249Sstephan.diestelhorst@arm.com
7710249Sstephan.diestelhorst@arm.com    typedef SrcClockDomain::DomainID DomainID;
7810249Sstephan.diestelhorst@arm.com    typedef SrcClockDomain::PerfLevel PerfLevel;
7910249Sstephan.diestelhorst@arm.com
8010249Sstephan.diestelhorst@arm.com    /**
8110395Sstephan.diestelhorst@arm.com     * Get the number of domains assigned to this DVFS handler.
8210395Sstephan.diestelhorst@arm.com     * @return Number of domains
8310395Sstephan.diestelhorst@arm.com     */
8410395Sstephan.diestelhorst@arm.com    uint32_t numDomains() const { return domainIDList.size(); }
8510395Sstephan.diestelhorst@arm.com
8610395Sstephan.diestelhorst@arm.com    /**
8710395Sstephan.diestelhorst@arm.com     * Get the n-th domain ID, from the domains managed by this handler.
8810395Sstephan.diestelhorst@arm.com     * @return Domain ID
8910395Sstephan.diestelhorst@arm.com     */
9010395Sstephan.diestelhorst@arm.com    DomainID domainID(uint32_t index) const;
9110395Sstephan.diestelhorst@arm.com
9210395Sstephan.diestelhorst@arm.com    /**
9310249Sstephan.diestelhorst@arm.com     * Check whether a domain ID is known to the handler or not.
9410249Sstephan.diestelhorst@arm.com     * @param domain_id Domain ID to check
9510249Sstephan.diestelhorst@arm.com     * @return Domain ID known to handler?
9610249Sstephan.diestelhorst@arm.com     */
9710249Sstephan.diestelhorst@arm.com    bool validDomainID(DomainID domain_id) const;
9810249Sstephan.diestelhorst@arm.com
9910249Sstephan.diestelhorst@arm.com    /**
10010249Sstephan.diestelhorst@arm.com     * Get transition latency to switch between performance levels.
10110249Sstephan.diestelhorst@arm.com     * @return Transition latency
10210249Sstephan.diestelhorst@arm.com     */
10310249Sstephan.diestelhorst@arm.com    Tick transLatency() const { return _transLatency; }
10410249Sstephan.diestelhorst@arm.com
10510249Sstephan.diestelhorst@arm.com    /**
10610249Sstephan.diestelhorst@arm.com     * Set a new performance level for the specified domain.  The actual update
10710249Sstephan.diestelhorst@arm.com     * will be delayed by transLatency().
10810249Sstephan.diestelhorst@arm.com     *
10910249Sstephan.diestelhorst@arm.com     * @param domain_id Software visible ID of the domain to be configured
11010249Sstephan.diestelhorst@arm.com     * @param perf_level Requested performance level (0 - fast, >0 slower)
11110249Sstephan.diestelhorst@arm.com     * @return status whether the setting was successful
11210249Sstephan.diestelhorst@arm.com     */
11310249Sstephan.diestelhorst@arm.com    bool perfLevel(DomainID domain_id, PerfLevel perf_level);
11410249Sstephan.diestelhorst@arm.com
11510249Sstephan.diestelhorst@arm.com    /**
11610249Sstephan.diestelhorst@arm.com     * Get the current performance level of a domain.  While a change request is
11710249Sstephan.diestelhorst@arm.com     * in-flight, will return the current (i.e. old, unmodified) value.
11810249Sstephan.diestelhorst@arm.com     *
11910249Sstephan.diestelhorst@arm.com     * @param domain_id Domain ID to query
12010249Sstephan.diestelhorst@arm.com     * @return Current performance level of the specified domain
12110249Sstephan.diestelhorst@arm.com     */
12210249Sstephan.diestelhorst@arm.com    PerfLevel perfLevel(DomainID domain_id) const {
12310249Sstephan.diestelhorst@arm.com         assert(isEnabled());
12410249Sstephan.diestelhorst@arm.com         return findDomain(domain_id)->perfLevel();
12510249Sstephan.diestelhorst@arm.com    }
12610249Sstephan.diestelhorst@arm.com
12710249Sstephan.diestelhorst@arm.com    /**
12810249Sstephan.diestelhorst@arm.com     * Read the clock period of the specified domain at the specified
12910249Sstephan.diestelhorst@arm.com     * performance level.
13010249Sstephan.diestelhorst@arm.com     * @param domain_id Domain ID to query
13110249Sstephan.diestelhorst@arm.com     * @param perf_level Performance level of interest
13210249Sstephan.diestelhorst@arm.com     * @return Clock period in ticks for the requested performance level of
13310249Sstephan.diestelhorst@arm.com     * the respective domain
13410249Sstephan.diestelhorst@arm.com     */
13510249Sstephan.diestelhorst@arm.com    Tick clkPeriodAtPerfLevel(DomainID domain_id, PerfLevel perf_level) const
13610249Sstephan.diestelhorst@arm.com    {
13710398Sstephan.diestelhorst@arm.com        SrcClockDomain *d = findDomain(domain_id);
13810398Sstephan.diestelhorst@arm.com        assert(d);
13910398Sstephan.diestelhorst@arm.com        PerfLevel n = d->numPerfLevels();
14010398Sstephan.diestelhorst@arm.com        if (perf_level < n)
14110398Sstephan.diestelhorst@arm.com            return d->clkPeriodAtPerfLevel(perf_level);
14210398Sstephan.diestelhorst@arm.com
14310398Sstephan.diestelhorst@arm.com        warn("DVFSHandler %s reads illegal frequency level %u from "\
14410398Sstephan.diestelhorst@arm.com             "SrcClockDomain %s. Returning 0\n", name(), perf_level, d->name());
14510398Sstephan.diestelhorst@arm.com        return Tick(0);
14610249Sstephan.diestelhorst@arm.com    }
14710249Sstephan.diestelhorst@arm.com
14810249Sstephan.diestelhorst@arm.com    /**
14910395Sstephan.diestelhorst@arm.com     * Read the voltage of the specified domain at the specified
15010395Sstephan.diestelhorst@arm.com     * performance level.
15110395Sstephan.diestelhorst@arm.com     * @param domain_id Domain ID to query
15210395Sstephan.diestelhorst@arm.com     * @param perf_level Performance level of interest
15310395Sstephan.diestelhorst@arm.com     * @return Voltage for the requested performance level of the respective
15410395Sstephan.diestelhorst@arm.com     * domain
15510395Sstephan.diestelhorst@arm.com     */
15611800Sbrandon.potter@amd.com    double voltageAtPerfLevel(DomainID domain_id, PerfLevel perf_level) const;
15710395Sstephan.diestelhorst@arm.com
15810395Sstephan.diestelhorst@arm.com    /**
15910249Sstephan.diestelhorst@arm.com     * Get the total number of available performance levels.
16010249Sstephan.diestelhorst@arm.com     *
16110249Sstephan.diestelhorst@arm.com     * @param domain_id Domain ID to query
16210249Sstephan.diestelhorst@arm.com     * @return Number of performance levels that where configured for the
16310249Sstephan.diestelhorst@arm.com     * respective domain
16410249Sstephan.diestelhorst@arm.com     */
16510249Sstephan.diestelhorst@arm.com    PerfLevel numPerfLevels(PerfLevel domain_id) const
16610249Sstephan.diestelhorst@arm.com    {
16710249Sstephan.diestelhorst@arm.com        return findDomain(domain_id)->numPerfLevels();
16810249Sstephan.diestelhorst@arm.com    }
16910249Sstephan.diestelhorst@arm.com
17010249Sstephan.diestelhorst@arm.com    /**
17110249Sstephan.diestelhorst@arm.com     * Check enable status of the DVFS handler, when the handler is disabled, no
17210249Sstephan.diestelhorst@arm.com     * request should be sent to the handler.
17310249Sstephan.diestelhorst@arm.com     * @return True, if the handler is enabled
17410249Sstephan.diestelhorst@arm.com     */
17510249Sstephan.diestelhorst@arm.com    bool isEnabled() const { return enableHandler; }
17610249Sstephan.diestelhorst@arm.com
17711168Sandreas.hansson@arm.com    void serialize(CheckpointOut &cp) const override;
17811168Sandreas.hansson@arm.com    void unserialize(CheckpointIn &cp) override;
17910249Sstephan.diestelhorst@arm.com
18010249Sstephan.diestelhorst@arm.com  private:
18110249Sstephan.diestelhorst@arm.com    typedef std::map<DomainID, SrcClockDomain*> Domains;
18210249Sstephan.diestelhorst@arm.com    Domains domains;
18310249Sstephan.diestelhorst@arm.com
18410249Sstephan.diestelhorst@arm.com    /**
18510395Sstephan.diestelhorst@arm.com      * List of IDs avaiable in the domain list
18610395Sstephan.diestelhorst@arm.com      */
18710395Sstephan.diestelhorst@arm.com    std::vector<DomainID> domainIDList;
18810395Sstephan.diestelhorst@arm.com
18910395Sstephan.diestelhorst@arm.com    /**
19010249Sstephan.diestelhorst@arm.com      * Clock domain of the system the handler is instantiated.
19110249Sstephan.diestelhorst@arm.com      */
19210249Sstephan.diestelhorst@arm.com    SrcClockDomain* sysClkDomain;
19310249Sstephan.diestelhorst@arm.com
19410249Sstephan.diestelhorst@arm.com    /**
19510249Sstephan.diestelhorst@arm.com     * Search for a domain based on the domain ID.
19610249Sstephan.diestelhorst@arm.com     *
19710249Sstephan.diestelhorst@arm.com     * @param domain_id Domain ID to search for
19810249Sstephan.diestelhorst@arm.com     * @return Pointer to the source clock domain with matching ID.
19910249Sstephan.diestelhorst@arm.com     */
20010249Sstephan.diestelhorst@arm.com    SrcClockDomain *findDomain(DomainID domain_id) const {
20110249Sstephan.diestelhorst@arm.com        auto it = domains.find(domain_id);
20210249Sstephan.diestelhorst@arm.com        panic_if(it == domains.end(),
20310249Sstephan.diestelhorst@arm.com                 "DVFS: Could not find a domain for ID %d.\n",domain_id );
20410249Sstephan.diestelhorst@arm.com        return domains.find(domain_id)->second;
20510249Sstephan.diestelhorst@arm.com    }
20610249Sstephan.diestelhorst@arm.com
20710249Sstephan.diestelhorst@arm.com    /**
20810249Sstephan.diestelhorst@arm.com     * Disabling the DVFS handler ensures that all the DVFS migration requests
20910249Sstephan.diestelhorst@arm.com     * are ignored. Domains remain at their default frequency and voltage.
21010249Sstephan.diestelhorst@arm.com     */
21110249Sstephan.diestelhorst@arm.com    bool enableHandler;
21210249Sstephan.diestelhorst@arm.com
21310249Sstephan.diestelhorst@arm.com
21410249Sstephan.diestelhorst@arm.com    /**
21510249Sstephan.diestelhorst@arm.com     * This corresponds to the maximum transition latency associated with the
21610249Sstephan.diestelhorst@arm.com     * hardware transitioning from a particular performance level to the other
21710249Sstephan.diestelhorst@arm.com     */
21810249Sstephan.diestelhorst@arm.com    const Tick _transLatency;
21910249Sstephan.diestelhorst@arm.com
22010249Sstephan.diestelhorst@arm.com
22110249Sstephan.diestelhorst@arm.com
22210249Sstephan.diestelhorst@arm.com    /**
22310249Sstephan.diestelhorst@arm.com     * Update performance level event, encapsulates all the required information
22410249Sstephan.diestelhorst@arm.com     * for a future call to change a domain's performance level.
22510249Sstephan.diestelhorst@arm.com     */
22610249Sstephan.diestelhorst@arm.com    struct UpdateEvent : public Event {
22710360Sandreas.hansson@arm.com        UpdateEvent() : Event(DVFS_Update_Pri), domainIDToSet(0),
22810360Sandreas.hansson@arm.com                        perfLevelToSet(0) {}
22910249Sstephan.diestelhorst@arm.com
23010249Sstephan.diestelhorst@arm.com        /**
23110249Sstephan.diestelhorst@arm.com         * Static pointer to the single DVFS hander for all the update events
23210249Sstephan.diestelhorst@arm.com         */
23310249Sstephan.diestelhorst@arm.com        static DVFSHandler *dvfsHandler;
23410249Sstephan.diestelhorst@arm.com
23510249Sstephan.diestelhorst@arm.com        /**
23610249Sstephan.diestelhorst@arm.com         * ID of the domain that will be changed by the in-flight event
23710249Sstephan.diestelhorst@arm.com         */
23810249Sstephan.diestelhorst@arm.com        DomainID domainIDToSet;
23910249Sstephan.diestelhorst@arm.com
24010249Sstephan.diestelhorst@arm.com        /**
24110249Sstephan.diestelhorst@arm.com         * Target performance level of the in-flight event
24210249Sstephan.diestelhorst@arm.com         */
24310249Sstephan.diestelhorst@arm.com        PerfLevel perfLevelToSet;
24410249Sstephan.diestelhorst@arm.com
24510249Sstephan.diestelhorst@arm.com        /**
24610249Sstephan.diestelhorst@arm.com         * Updates the performance level by modifying the clock and the voltage
24710249Sstephan.diestelhorst@arm.com         * of the associated clocked objects.  Gets information from
24810249Sstephan.diestelhorst@arm.com         * domainIDToSet and perfLevelToSet for easier calling through an
24910249Sstephan.diestelhorst@arm.com         * event.
25010249Sstephan.diestelhorst@arm.com         */
25110249Sstephan.diestelhorst@arm.com        void updatePerfLevel();
25210249Sstephan.diestelhorst@arm.com
25310249Sstephan.diestelhorst@arm.com        void process() { updatePerfLevel(); }
25410249Sstephan.diestelhorst@arm.com    };
25510249Sstephan.diestelhorst@arm.com
25610249Sstephan.diestelhorst@arm.com    typedef std::map<DomainID, UpdateEvent> UpdatePerfLevelEvents;
25710249Sstephan.diestelhorst@arm.com    /**
25810249Sstephan.diestelhorst@arm.com     * Map from domain IDs -> perf level update events, records in-flight change
25910249Sstephan.diestelhorst@arm.com     * requests per domain ID.
26010249Sstephan.diestelhorst@arm.com     */
26110249Sstephan.diestelhorst@arm.com    UpdatePerfLevelEvents updatePerfLevelEvents;
26210249Sstephan.diestelhorst@arm.com};
26310249Sstephan.diestelhorst@arm.com
26410249Sstephan.diestelhorst@arm.com#endif // __SIM_DVFS_HANDLER_HH__
265