dvfs_handler.cc revision 10249
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#include <set> 4310249Sstephan.diestelhorst@arm.com#include <utility> 4410249Sstephan.diestelhorst@arm.com 4510249Sstephan.diestelhorst@arm.com#include "base/misc.hh" 4610249Sstephan.diestelhorst@arm.com#include "debug/DVFS.hh" 4710249Sstephan.diestelhorst@arm.com#include "params/DVFSHandler.hh" 4810249Sstephan.diestelhorst@arm.com#include "sim/clock_domain.hh" 4910249Sstephan.diestelhorst@arm.com#include "sim/dvfs_handler.hh" 5010249Sstephan.diestelhorst@arm.com#include "sim/stat_control.hh" 5110249Sstephan.diestelhorst@arm.com#include "sim/voltage_domain.hh" 5210249Sstephan.diestelhorst@arm.com 5310249Sstephan.diestelhorst@arm.com// 5410249Sstephan.diestelhorst@arm.com// 5510249Sstephan.diestelhorst@arm.com// DVFSHandler methods implementation 5610249Sstephan.diestelhorst@arm.com// 5710249Sstephan.diestelhorst@arm.com 5810249Sstephan.diestelhorst@arm.comDVFSHandler::DVFSHandler(const Params *p) 5910249Sstephan.diestelhorst@arm.com : SimObject(p), 6010249Sstephan.diestelhorst@arm.com sysClkDomain(p->sys_clk_domain), 6110249Sstephan.diestelhorst@arm.com enableHandler(p->enable), 6210249Sstephan.diestelhorst@arm.com _transLatency(p->transition_latency) 6310249Sstephan.diestelhorst@arm.com{ 6410249Sstephan.diestelhorst@arm.com // Check supplied list of domains for sanity and add them to the 6510249Sstephan.diestelhorst@arm.com // domain ID -> domain* hash 6610249Sstephan.diestelhorst@arm.com for(auto dit = p->domains.begin(); dit != p->domains.end(); ++dit) { 6710249Sstephan.diestelhorst@arm.com SrcClockDomain *d = *dit; 6810249Sstephan.diestelhorst@arm.com DomainID domain_id = d->domainID(); 6910249Sstephan.diestelhorst@arm.com 7010249Sstephan.diestelhorst@arm.com fatal_if(sysClkDomain == d, "DVFS: Domain config list has a "\ 7110249Sstephan.diestelhorst@arm.com "system clk domain entry"); 7210249Sstephan.diestelhorst@arm.com fatal_if(domain_id == SrcClockDomain::emptyDomainID, 7310249Sstephan.diestelhorst@arm.com "DVFS: Controlled domain %s needs to have a properly "\ 7410249Sstephan.diestelhorst@arm.com " assigned ID.\n", d->name()); 7510249Sstephan.diestelhorst@arm.com 7610249Sstephan.diestelhorst@arm.com auto entry = std::make_pair(domain_id, d); 7710249Sstephan.diestelhorst@arm.com bool new_elem = domains.insert(entry).second; 7810249Sstephan.diestelhorst@arm.com fatal_if(!new_elem, "DVFS: Domain %s with ID %d does not have a "\ 7910249Sstephan.diestelhorst@arm.com "unique ID.\n", d->name(), domain_id); 8010249Sstephan.diestelhorst@arm.com 8110249Sstephan.diestelhorst@arm.com // Create a dedicated event slot per known domain ID 8210249Sstephan.diestelhorst@arm.com UpdateEvent *event = &updatePerfLevelEvents[domain_id]; 8310249Sstephan.diestelhorst@arm.com event->domainIDToSet = d->domainID(); 8410249Sstephan.diestelhorst@arm.com } 8510249Sstephan.diestelhorst@arm.com UpdateEvent::dvfsHandler = this; 8610249Sstephan.diestelhorst@arm.com} 8710249Sstephan.diestelhorst@arm.com 8810249Sstephan.diestelhorst@arm.comDVFSHandler *DVFSHandler::UpdateEvent::dvfsHandler; 8910249Sstephan.diestelhorst@arm.com 9010249Sstephan.diestelhorst@arm.combool 9110249Sstephan.diestelhorst@arm.comDVFSHandler::validDomainID(DomainID domain_id) const 9210249Sstephan.diestelhorst@arm.com{ 9310249Sstephan.diestelhorst@arm.com assert(isEnabled()); 9410249Sstephan.diestelhorst@arm.com // This is ensure that the domain id as requested by the software is 9510249Sstephan.diestelhorst@arm.com // availabe in the handler. 9610249Sstephan.diestelhorst@arm.com if (domains.find(domain_id) != domains.end()) 9710249Sstephan.diestelhorst@arm.com return true; 9810249Sstephan.diestelhorst@arm.com warn("DVFS: invalid domain ID %d, the DVFS handler does not handle this "\ 9910249Sstephan.diestelhorst@arm.com "domain\n", domain_id); 10010249Sstephan.diestelhorst@arm.com return false; 10110249Sstephan.diestelhorst@arm.com} 10210249Sstephan.diestelhorst@arm.com 10310249Sstephan.diestelhorst@arm.combool 10410249Sstephan.diestelhorst@arm.comDVFSHandler::perfLevel(DomainID domain_id, PerfLevel perf_level) 10510249Sstephan.diestelhorst@arm.com{ 10610249Sstephan.diestelhorst@arm.com assert(isEnabled()); 10710249Sstephan.diestelhorst@arm.com 10810249Sstephan.diestelhorst@arm.com DPRINTF(DVFS, "DVFS: setPerfLevel domain %d -> %d\n", domain_id, perf_level); 10910249Sstephan.diestelhorst@arm.com 11010249Sstephan.diestelhorst@arm.com auto d = findDomain(domain_id); 11110249Sstephan.diestelhorst@arm.com if (!d->validPerfLevel(perf_level)) { 11210249Sstephan.diestelhorst@arm.com warn("DVFS: invalid performance level %d for domain ID %d, request "\ 11310249Sstephan.diestelhorst@arm.com "ignored\n", perf_level, domain_id); 11410249Sstephan.diestelhorst@arm.com return false; 11510249Sstephan.diestelhorst@arm.com } 11610249Sstephan.diestelhorst@arm.com 11710249Sstephan.diestelhorst@arm.com UpdateEvent *update_event = &updatePerfLevelEvents[domain_id]; 11810249Sstephan.diestelhorst@arm.com // Drop an old DVFS change request once we have established that this is a 11910249Sstephan.diestelhorst@arm.com // reasonable request 12010249Sstephan.diestelhorst@arm.com if (update_event->scheduled()) { 12110249Sstephan.diestelhorst@arm.com DPRINTF(DVFS, "DVFS: Overwriting the previous DVFS event.\n"); 12210249Sstephan.diestelhorst@arm.com deschedule(update_event); 12310249Sstephan.diestelhorst@arm.com } 12410249Sstephan.diestelhorst@arm.com 12510249Sstephan.diestelhorst@arm.com update_event->perfLevelToSet = perf_level; 12610249Sstephan.diestelhorst@arm.com 12710249Sstephan.diestelhorst@arm.com // State changes that restore to the current state (and / or overwrite a not 12810249Sstephan.diestelhorst@arm.com // yet completed in-flight request) will be squashed 12910249Sstephan.diestelhorst@arm.com if (d->perfLevel() == perf_level) { 13010249Sstephan.diestelhorst@arm.com DPRINTF(DVFS, "DVFS: Ignoring ineffective performance level change "\ 13110249Sstephan.diestelhorst@arm.com "%d -> %d\n", d->perfLevel(), perf_level); 13210249Sstephan.diestelhorst@arm.com return false; 13310249Sstephan.diestelhorst@arm.com } 13410249Sstephan.diestelhorst@arm.com 13510249Sstephan.diestelhorst@arm.com // At this point, a new transition will certainly take place -> schedule 13610249Sstephan.diestelhorst@arm.com Tick when = curTick() + _transLatency; 13710249Sstephan.diestelhorst@arm.com DPRINTF(DVFS, "DVFS: Update for perf event scheduled for %ld\n", when); 13810249Sstephan.diestelhorst@arm.com 13910249Sstephan.diestelhorst@arm.com schedule(update_event, when); 14010249Sstephan.diestelhorst@arm.com return true; 14110249Sstephan.diestelhorst@arm.com} 14210249Sstephan.diestelhorst@arm.com 14310249Sstephan.diestelhorst@arm.comvoid 14410249Sstephan.diestelhorst@arm.comDVFSHandler::UpdateEvent::updatePerfLevel() 14510249Sstephan.diestelhorst@arm.com{ 14610249Sstephan.diestelhorst@arm.com // Perform explicit stats dump for power estimation before performance 14710249Sstephan.diestelhorst@arm.com // level migration 14810249Sstephan.diestelhorst@arm.com Stats::dump(); 14910249Sstephan.diestelhorst@arm.com Stats::reset(); 15010249Sstephan.diestelhorst@arm.com 15110249Sstephan.diestelhorst@arm.com // Update the performance level in the clock domain 15210249Sstephan.diestelhorst@arm.com auto d = dvfsHandler->findDomain(domainIDToSet); 15310249Sstephan.diestelhorst@arm.com assert(d->perfLevel() != perfLevelToSet); 15410249Sstephan.diestelhorst@arm.com 15510249Sstephan.diestelhorst@arm.com d->perfLevel(perfLevelToSet); 15610249Sstephan.diestelhorst@arm.com} 15710249Sstephan.diestelhorst@arm.com 15810249Sstephan.diestelhorst@arm.comvoid 15910249Sstephan.diestelhorst@arm.comDVFSHandler::serialize(std::ostream &os) 16010249Sstephan.diestelhorst@arm.com{ 16110249Sstephan.diestelhorst@arm.com //This is to ensure that the handler status is maintained during the 16210249Sstephan.diestelhorst@arm.com //entire simulation run and not changed from command line during checkpoint 16310249Sstephan.diestelhorst@arm.com //and restore 16410249Sstephan.diestelhorst@arm.com SERIALIZE_SCALAR(enableHandler); 16510249Sstephan.diestelhorst@arm.com 16610249Sstephan.diestelhorst@arm.com // Pull out the hashed data structure into easy-to-serialise arrays; 16710249Sstephan.diestelhorst@arm.com // ensuring that the data associated with any pending update event is saved 16810249Sstephan.diestelhorst@arm.com std::vector<DomainID> domain_ids; 16910249Sstephan.diestelhorst@arm.com std::vector<PerfLevel> perf_levels; 17010249Sstephan.diestelhorst@arm.com std::vector<Tick> whens; 17110249Sstephan.diestelhorst@arm.com for (auto it = updatePerfLevelEvents.begin(); 17210249Sstephan.diestelhorst@arm.com it != updatePerfLevelEvents.end(); ++it) { 17310249Sstephan.diestelhorst@arm.com DomainID id = it->first; 17410249Sstephan.diestelhorst@arm.com UpdateEvent *event = &it->second; 17510249Sstephan.diestelhorst@arm.com 17610249Sstephan.diestelhorst@arm.com assert(id == event->domainIDToSet); 17710249Sstephan.diestelhorst@arm.com domain_ids.push_back(id); 17810249Sstephan.diestelhorst@arm.com perf_levels.push_back(event->perfLevelToSet); 17910249Sstephan.diestelhorst@arm.com whens.push_back(event->scheduled() ? event->when() : 0); 18010249Sstephan.diestelhorst@arm.com } 18110249Sstephan.diestelhorst@arm.com arrayParamOut(os, "domain_ids", domain_ids); 18210249Sstephan.diestelhorst@arm.com arrayParamOut(os, "perf_levels", perf_levels); 18310249Sstephan.diestelhorst@arm.com arrayParamOut(os, "whens", whens); 18410249Sstephan.diestelhorst@arm.com} 18510249Sstephan.diestelhorst@arm.com 18610249Sstephan.diestelhorst@arm.comvoid 18710249Sstephan.diestelhorst@arm.comDVFSHandler::unserialize(Checkpoint *cp, const std::string §ion) 18810249Sstephan.diestelhorst@arm.com{ 18910249Sstephan.diestelhorst@arm.com UNSERIALIZE_SCALAR(enableHandler); 19010249Sstephan.diestelhorst@arm.com 19110249Sstephan.diestelhorst@arm.com // Reconstruct the map of domain IDs and their scheduled events 19210249Sstephan.diestelhorst@arm.com std::vector<DomainID> domain_ids; 19310249Sstephan.diestelhorst@arm.com std::vector<PerfLevel> perf_levels; 19410249Sstephan.diestelhorst@arm.com std::vector<Tick> whens; 19510249Sstephan.diestelhorst@arm.com arrayParamIn(cp, section, "domain_ids", domain_ids); 19610249Sstephan.diestelhorst@arm.com arrayParamIn(cp, section, "perf_levels", perf_levels); 19710249Sstephan.diestelhorst@arm.com arrayParamIn(cp, section, "whens", whens); 19810249Sstephan.diestelhorst@arm.com 19910249Sstephan.diestelhorst@arm.com for (size_t i = 0; i < domain_ids.size(); ++i) {; 20010249Sstephan.diestelhorst@arm.com UpdateEvent *event = &updatePerfLevelEvents[domain_ids[i]]; 20110249Sstephan.diestelhorst@arm.com 20210249Sstephan.diestelhorst@arm.com event->domainIDToSet = domain_ids[i]; 20310249Sstephan.diestelhorst@arm.com event->perfLevelToSet = perf_levels[i]; 20410249Sstephan.diestelhorst@arm.com 20510249Sstephan.diestelhorst@arm.com // Schedule all previously scheduled events 20610249Sstephan.diestelhorst@arm.com if (whens[i]) 20710249Sstephan.diestelhorst@arm.com schedule(event, whens[i]); 20810249Sstephan.diestelhorst@arm.com } 20910249Sstephan.diestelhorst@arm.com UpdateEvent::dvfsHandler = this; 21010249Sstephan.diestelhorst@arm.com} 21110249Sstephan.diestelhorst@arm.com 21210249Sstephan.diestelhorst@arm.comDVFSHandler* 21310249Sstephan.diestelhorst@arm.comDVFSHandlerParams::create() 21410249Sstephan.diestelhorst@arm.com{ 21510249Sstephan.diestelhorst@arm.com return new DVFSHandler(this); 21610249Sstephan.diestelhorst@arm.com} 217