dvfs_handler.cc revision 10905
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(); 8410395Sstephan.diestelhorst@arm.com 8510395Sstephan.diestelhorst@arm.com // Add domain ID to the list of domains 8610395Sstephan.diestelhorst@arm.com domainIDList.push_back(d->domainID()); 8710249Sstephan.diestelhorst@arm.com } 8810249Sstephan.diestelhorst@arm.com UpdateEvent::dvfsHandler = this; 8910249Sstephan.diestelhorst@arm.com} 9010249Sstephan.diestelhorst@arm.com 9110249Sstephan.diestelhorst@arm.comDVFSHandler *DVFSHandler::UpdateEvent::dvfsHandler; 9210249Sstephan.diestelhorst@arm.com 9310395Sstephan.diestelhorst@arm.comDVFSHandler::DomainID 9410395Sstephan.diestelhorst@arm.comDVFSHandler::domainID(uint32_t index) const 9510395Sstephan.diestelhorst@arm.com{ 9610395Sstephan.diestelhorst@arm.com fatal_if(index >= numDomains(), "DVFS: Requested index out of "\ 9710395Sstephan.diestelhorst@arm.com "bound, max value %d\n", (domainIDList.size() - 1)); 9810395Sstephan.diestelhorst@arm.com 9910395Sstephan.diestelhorst@arm.com assert(domains.find(domainIDList[index]) != domains.end()); 10010395Sstephan.diestelhorst@arm.com 10110395Sstephan.diestelhorst@arm.com return domainIDList[index]; 10210395Sstephan.diestelhorst@arm.com} 10310395Sstephan.diestelhorst@arm.com 10410249Sstephan.diestelhorst@arm.combool 10510249Sstephan.diestelhorst@arm.comDVFSHandler::validDomainID(DomainID domain_id) const 10610249Sstephan.diestelhorst@arm.com{ 10710249Sstephan.diestelhorst@arm.com assert(isEnabled()); 10810249Sstephan.diestelhorst@arm.com // This is ensure that the domain id as requested by the software is 10910249Sstephan.diestelhorst@arm.com // availabe in the handler. 11010249Sstephan.diestelhorst@arm.com if (domains.find(domain_id) != domains.end()) 11110249Sstephan.diestelhorst@arm.com return true; 11210249Sstephan.diestelhorst@arm.com warn("DVFS: invalid domain ID %d, the DVFS handler does not handle this "\ 11310249Sstephan.diestelhorst@arm.com "domain\n", domain_id); 11410249Sstephan.diestelhorst@arm.com return false; 11510249Sstephan.diestelhorst@arm.com} 11610249Sstephan.diestelhorst@arm.com 11710249Sstephan.diestelhorst@arm.combool 11810249Sstephan.diestelhorst@arm.comDVFSHandler::perfLevel(DomainID domain_id, PerfLevel perf_level) 11910249Sstephan.diestelhorst@arm.com{ 12010249Sstephan.diestelhorst@arm.com assert(isEnabled()); 12110249Sstephan.diestelhorst@arm.com 12210249Sstephan.diestelhorst@arm.com DPRINTF(DVFS, "DVFS: setPerfLevel domain %d -> %d\n", domain_id, perf_level); 12310249Sstephan.diestelhorst@arm.com 12410249Sstephan.diestelhorst@arm.com auto d = findDomain(domain_id); 12510249Sstephan.diestelhorst@arm.com if (!d->validPerfLevel(perf_level)) { 12610249Sstephan.diestelhorst@arm.com warn("DVFS: invalid performance level %d for domain ID %d, request "\ 12710249Sstephan.diestelhorst@arm.com "ignored\n", perf_level, domain_id); 12810249Sstephan.diestelhorst@arm.com return false; 12910249Sstephan.diestelhorst@arm.com } 13010249Sstephan.diestelhorst@arm.com 13110249Sstephan.diestelhorst@arm.com UpdateEvent *update_event = &updatePerfLevelEvents[domain_id]; 13210249Sstephan.diestelhorst@arm.com // Drop an old DVFS change request once we have established that this is a 13310249Sstephan.diestelhorst@arm.com // reasonable request 13410249Sstephan.diestelhorst@arm.com if (update_event->scheduled()) { 13510249Sstephan.diestelhorst@arm.com DPRINTF(DVFS, "DVFS: Overwriting the previous DVFS event.\n"); 13610249Sstephan.diestelhorst@arm.com deschedule(update_event); 13710249Sstephan.diestelhorst@arm.com } 13810249Sstephan.diestelhorst@arm.com 13910249Sstephan.diestelhorst@arm.com update_event->perfLevelToSet = perf_level; 14010249Sstephan.diestelhorst@arm.com 14110249Sstephan.diestelhorst@arm.com // State changes that restore to the current state (and / or overwrite a not 14210249Sstephan.diestelhorst@arm.com // yet completed in-flight request) will be squashed 14310249Sstephan.diestelhorst@arm.com if (d->perfLevel() == perf_level) { 14410249Sstephan.diestelhorst@arm.com DPRINTF(DVFS, "DVFS: Ignoring ineffective performance level change "\ 14510249Sstephan.diestelhorst@arm.com "%d -> %d\n", d->perfLevel(), perf_level); 14610249Sstephan.diestelhorst@arm.com return false; 14710249Sstephan.diestelhorst@arm.com } 14810249Sstephan.diestelhorst@arm.com 14910249Sstephan.diestelhorst@arm.com // At this point, a new transition will certainly take place -> schedule 15010249Sstephan.diestelhorst@arm.com Tick when = curTick() + _transLatency; 15110249Sstephan.diestelhorst@arm.com DPRINTF(DVFS, "DVFS: Update for perf event scheduled for %ld\n", when); 15210249Sstephan.diestelhorst@arm.com 15310249Sstephan.diestelhorst@arm.com schedule(update_event, when); 15410249Sstephan.diestelhorst@arm.com return true; 15510249Sstephan.diestelhorst@arm.com} 15610249Sstephan.diestelhorst@arm.com 15710249Sstephan.diestelhorst@arm.comvoid 15810249Sstephan.diestelhorst@arm.comDVFSHandler::UpdateEvent::updatePerfLevel() 15910249Sstephan.diestelhorst@arm.com{ 16010249Sstephan.diestelhorst@arm.com // Perform explicit stats dump for power estimation before performance 16110249Sstephan.diestelhorst@arm.com // level migration 16210249Sstephan.diestelhorst@arm.com Stats::dump(); 16310249Sstephan.diestelhorst@arm.com Stats::reset(); 16410249Sstephan.diestelhorst@arm.com 16510249Sstephan.diestelhorst@arm.com // Update the performance level in the clock domain 16610249Sstephan.diestelhorst@arm.com auto d = dvfsHandler->findDomain(domainIDToSet); 16710249Sstephan.diestelhorst@arm.com assert(d->perfLevel() != perfLevelToSet); 16810249Sstephan.diestelhorst@arm.com 16910249Sstephan.diestelhorst@arm.com d->perfLevel(perfLevelToSet); 17010249Sstephan.diestelhorst@arm.com} 17110249Sstephan.diestelhorst@arm.com 17210249Sstephan.diestelhorst@arm.comvoid 17310905Sandreas.sandberg@arm.comDVFSHandler::serialize(CheckpointOut &cp) const 17410249Sstephan.diestelhorst@arm.com{ 17510249Sstephan.diestelhorst@arm.com //This is to ensure that the handler status is maintained during the 17610249Sstephan.diestelhorst@arm.com //entire simulation run and not changed from command line during checkpoint 17710249Sstephan.diestelhorst@arm.com //and restore 17810249Sstephan.diestelhorst@arm.com SERIALIZE_SCALAR(enableHandler); 17910249Sstephan.diestelhorst@arm.com 18010249Sstephan.diestelhorst@arm.com // Pull out the hashed data structure into easy-to-serialise arrays; 18110249Sstephan.diestelhorst@arm.com // ensuring that the data associated with any pending update event is saved 18210249Sstephan.diestelhorst@arm.com std::vector<DomainID> domain_ids; 18310249Sstephan.diestelhorst@arm.com std::vector<PerfLevel> perf_levels; 18410249Sstephan.diestelhorst@arm.com std::vector<Tick> whens; 18510905Sandreas.sandberg@arm.com for (const auto &ev_pair : updatePerfLevelEvents) { 18610905Sandreas.sandberg@arm.com DomainID id = ev_pair.first; 18710905Sandreas.sandberg@arm.com const UpdateEvent *event = &ev_pair.second; 18810249Sstephan.diestelhorst@arm.com 18910249Sstephan.diestelhorst@arm.com assert(id == event->domainIDToSet); 19010249Sstephan.diestelhorst@arm.com domain_ids.push_back(id); 19110249Sstephan.diestelhorst@arm.com perf_levels.push_back(event->perfLevelToSet); 19210249Sstephan.diestelhorst@arm.com whens.push_back(event->scheduled() ? event->when() : 0); 19310249Sstephan.diestelhorst@arm.com } 19410905Sandreas.sandberg@arm.com SERIALIZE_CONTAINER(domain_ids); 19510905Sandreas.sandberg@arm.com SERIALIZE_CONTAINER(perf_levels); 19610905Sandreas.sandberg@arm.com SERIALIZE_CONTAINER(whens); 19710249Sstephan.diestelhorst@arm.com} 19810249Sstephan.diestelhorst@arm.com 19910249Sstephan.diestelhorst@arm.comvoid 20010905Sandreas.sandberg@arm.comDVFSHandler::unserialize(CheckpointIn &cp) 20110249Sstephan.diestelhorst@arm.com{ 20210395Sstephan.diestelhorst@arm.com bool temp = enableHandler; 20310395Sstephan.diestelhorst@arm.com 20410249Sstephan.diestelhorst@arm.com UNSERIALIZE_SCALAR(enableHandler); 20510249Sstephan.diestelhorst@arm.com 20610395Sstephan.diestelhorst@arm.com if(temp != enableHandler) { 20710395Sstephan.diestelhorst@arm.com warn("DVFS: Forcing enable handler status to unserialized value of %d", 20810395Sstephan.diestelhorst@arm.com enableHandler); 20910395Sstephan.diestelhorst@arm.com } 21010395Sstephan.diestelhorst@arm.com 21110249Sstephan.diestelhorst@arm.com // Reconstruct the map of domain IDs and their scheduled events 21210249Sstephan.diestelhorst@arm.com std::vector<DomainID> domain_ids; 21310249Sstephan.diestelhorst@arm.com std::vector<PerfLevel> perf_levels; 21410249Sstephan.diestelhorst@arm.com std::vector<Tick> whens; 21510905Sandreas.sandberg@arm.com UNSERIALIZE_CONTAINER(domain_ids); 21610905Sandreas.sandberg@arm.com UNSERIALIZE_CONTAINER(perf_levels); 21710905Sandreas.sandberg@arm.com UNSERIALIZE_CONTAINER(whens); 21810249Sstephan.diestelhorst@arm.com 21910249Sstephan.diestelhorst@arm.com for (size_t i = 0; i < domain_ids.size(); ++i) {; 22010249Sstephan.diestelhorst@arm.com UpdateEvent *event = &updatePerfLevelEvents[domain_ids[i]]; 22110249Sstephan.diestelhorst@arm.com 22210249Sstephan.diestelhorst@arm.com event->domainIDToSet = domain_ids[i]; 22310249Sstephan.diestelhorst@arm.com event->perfLevelToSet = perf_levels[i]; 22410249Sstephan.diestelhorst@arm.com 22510249Sstephan.diestelhorst@arm.com // Schedule all previously scheduled events 22610249Sstephan.diestelhorst@arm.com if (whens[i]) 22710249Sstephan.diestelhorst@arm.com schedule(event, whens[i]); 22810249Sstephan.diestelhorst@arm.com } 22910249Sstephan.diestelhorst@arm.com UpdateEvent::dvfsHandler = this; 23010249Sstephan.diestelhorst@arm.com} 23110249Sstephan.diestelhorst@arm.com 23210249Sstephan.diestelhorst@arm.comDVFSHandler* 23310249Sstephan.diestelhorst@arm.comDVFSHandlerParams::create() 23410249Sstephan.diestelhorst@arm.com{ 23510249Sstephan.diestelhorst@arm.com return new DVFSHandler(this); 23610249Sstephan.diestelhorst@arm.com} 237