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