dvfs_handler.hh revision 10360
1/*
2 * Copyright (c) 2013-2014 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Vasileios Spiliopoulos
38 *          Akash Bagdia
39 *          Stephan Diestelhorst
40 */
41
42/**
43 * @file
44 * DVFSHandler and DomainConfig class declaration used for managing voltage
45 * and frequency scaling of the various DVFS domains in the system (with each
46 * domain having their independent domain configuration information)
47 */
48
49
50#ifndef __SIM_DVFS_HANDLER_HH__
51#define __SIM_DVFS_HANDLER_HH__
52
53#include <vector>
54
55#include "params/ClockDomain.hh"
56#include "params/DVFSHandler.hh"
57#include "params/VoltageDomain.hh"
58#include "sim/clock_domain.hh"
59#include "sim/eventq.hh"
60#include "sim/sim_object.hh"
61
62
63/**
64 * DVFS Handler class, maintains a list of all the domains it can handle.
65 * Each entry of that list is an object of the DomainConfig class, and the
66 * handler uses the methods provided by that class to get access to the
67 * configuration of each domain. The handler is responsible for setting/getting
68 * clock periods and voltages from clock/voltage domains.
69 * The handler acts the bridge between software configurable information
70 * for each domain as provided to the controller and the hardware
71 * implementation details for those domains.
72 */
73class DVFSHandler : public SimObject
74{
75  public:
76    typedef DVFSHandlerParams Params;
77    DVFSHandler(const Params *p);
78
79    typedef SrcClockDomain::DomainID DomainID;
80    typedef SrcClockDomain::PerfLevel PerfLevel;
81
82    /**
83     * Check whether a domain ID is known to the handler or not.
84     * @param domain_id Domain ID to check
85     * @return Domain ID known to handler?
86     */
87    bool validDomainID(DomainID domain_id) const;
88
89    /**
90     * Get transition latency to switch between performance levels.
91     * @return Transition latency
92     */
93    Tick transLatency() const { return _transLatency; }
94
95    /**
96     * Set a new performance level for the specified domain.  The actual update
97     * will be delayed by transLatency().
98     *
99     * @param domain_id Software visible ID of the domain to be configured
100     * @param perf_level Requested performance level (0 - fast, >0 slower)
101     * @return status whether the setting was successful
102     */
103    bool perfLevel(DomainID domain_id, PerfLevel perf_level);
104
105    /**
106     * Get the current performance level of a domain.  While a change request is
107     * in-flight, will return the current (i.e. old, unmodified) value.
108     *
109     * @param domain_id Domain ID to query
110     * @return Current performance level of the specified domain
111     */
112    PerfLevel perfLevel(DomainID domain_id) const {
113         assert(isEnabled());
114         return findDomain(domain_id)->perfLevel();
115    }
116
117    /**
118     * Read the clock period of the specified domain at the specified
119     * performance level.
120     * @param domain_id Domain ID to query
121     * @param perf_level Performance level of interest
122     * @return Clock period in ticks for the requested performance level of
123     * the respective domain
124     */
125    Tick clkPeriodAtPerfLevel(DomainID domain_id, PerfLevel perf_level) const
126    {
127        return findDomain(domain_id)->clkPeriodAtPerfLevel(perf_level);
128    }
129
130    /**
131     * Get the total number of available performance levels.
132     *
133     * @param domain_id Domain ID to query
134     * @return Number of performance levels that where configured for the
135     * respective domain
136     */
137    PerfLevel numPerfLevels(PerfLevel domain_id) const
138    {
139        return findDomain(domain_id)->numPerfLevels();
140    }
141
142    /**
143     * Check enable status of the DVFS handler, when the handler is disabled, no
144     * request should be sent to the handler.
145     * @return True, if the handler is enabled
146     */
147    bool isEnabled() const { return enableHandler; }
148
149    void serialize(std::ostream &os);
150    void unserialize(Checkpoint *cp, const std::string &section);
151
152  private:
153    typedef std::map<DomainID, SrcClockDomain*> Domains;
154    Domains domains;
155
156    /**
157      * Clock domain of the system the handler is instantiated.
158      */
159    SrcClockDomain* sysClkDomain;
160
161    /**
162     * Search for a domain based on the domain ID.
163     *
164     * @param domain_id Domain ID to search for
165     * @return Pointer to the source clock domain with matching ID.
166     */
167    SrcClockDomain *findDomain(DomainID domain_id) const {
168        auto it = domains.find(domain_id);
169        panic_if(it == domains.end(),
170                 "DVFS: Could not find a domain for ID %d.\n",domain_id );
171        return domains.find(domain_id)->second;
172    }
173
174    /**
175     * Disabling the DVFS handler ensures that all the DVFS migration requests
176     * are ignored. Domains remain at their default frequency and voltage.
177     */
178    bool enableHandler;
179
180
181    /**
182     * This corresponds to the maximum transition latency associated with the
183     * hardware transitioning from a particular performance level to the other
184     */
185    const Tick _transLatency;
186
187
188
189    /**
190     * Update performance level event, encapsulates all the required information
191     * for a future call to change a domain's performance level.
192     */
193    struct UpdateEvent : public Event {
194        UpdateEvent() : Event(DVFS_Update_Pri), domainIDToSet(0),
195                        perfLevelToSet(0) {}
196
197        /**
198         * Static pointer to the single DVFS hander for all the update events
199         */
200        static DVFSHandler *dvfsHandler;
201
202        /**
203         * ID of the domain that will be changed by the in-flight event
204         */
205        DomainID domainIDToSet;
206
207        /**
208         * Target performance level of the in-flight event
209         */
210        PerfLevel perfLevelToSet;
211
212        /**
213         * Updates the performance level by modifying the clock and the voltage
214         * of the associated clocked objects.  Gets information from
215         * domainIDToSet and perfLevelToSet for easier calling through an
216         * event.
217         */
218        void updatePerfLevel();
219
220        void process() { updatePerfLevel(); }
221    };
222
223    typedef std::map<DomainID, UpdateEvent> UpdatePerfLevelEvents;
224    /**
225     * Map from domain IDs -> perf level update events, records in-flight change
226     * requests per domain ID.
227     */
228    UpdatePerfLevelEvents updatePerfLevelEvents;
229};
230
231#endif // __SIM_DVFS_HANDLER_HH__
232