clock_domain.cc revision 11793
19793Sakash.bagdia@arm.com/* 210249Sstephan.diestelhorst@arm.com * Copyright (c) 2013-2014 ARM Limited 310000Sclt67@cornell.edu * Copyright (c) 2013 Cornell University 49793Sakash.bagdia@arm.com * All rights reserved 59793Sakash.bagdia@arm.com * 69793Sakash.bagdia@arm.com * The license below extends only to copyright in the software and shall 79793Sakash.bagdia@arm.com * not be construed as granting a license to any other intellectual 89793Sakash.bagdia@arm.com * property including but not limited to intellectual property relating 99793Sakash.bagdia@arm.com * to a hardware implementation of the functionality of the software 109793Sakash.bagdia@arm.com * licensed hereunder. You may use the software subject to the license 119793Sakash.bagdia@arm.com * terms below provided that you ensure that this notice is replicated 129793Sakash.bagdia@arm.com * unmodified and in its entirety in all distributions of the software, 139793Sakash.bagdia@arm.com * modified or unmodified, in source code or in binary form. 149793Sakash.bagdia@arm.com * 159793Sakash.bagdia@arm.com * Redistribution and use in source and binary forms, with or without 169793Sakash.bagdia@arm.com * modification, are permitted provided that the following conditions are 179793Sakash.bagdia@arm.com * met: redistributions of source code must retain the above copyright 189793Sakash.bagdia@arm.com * notice, this list of conditions and the following disclaimer; 199793Sakash.bagdia@arm.com * redistributions in binary form must reproduce the above copyright 209793Sakash.bagdia@arm.com * notice, this list of conditions and the following disclaimer in the 219793Sakash.bagdia@arm.com * documentation and/or other materials provided with the distribution; 229793Sakash.bagdia@arm.com * neither the name of the copyright holders nor the names of its 239793Sakash.bagdia@arm.com * contributors may be used to endorse or promote products derived from 249793Sakash.bagdia@arm.com * this software without specific prior written permission. 259793Sakash.bagdia@arm.com * 269793Sakash.bagdia@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 279793Sakash.bagdia@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 289793Sakash.bagdia@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 299793Sakash.bagdia@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 309793Sakash.bagdia@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 319793Sakash.bagdia@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 329793Sakash.bagdia@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 339793Sakash.bagdia@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 349793Sakash.bagdia@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 359793Sakash.bagdia@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 369793Sakash.bagdia@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 379793Sakash.bagdia@arm.com * 389793Sakash.bagdia@arm.com * Authors: Vasileios Spiliopoulos 399793Sakash.bagdia@arm.com * Akash Bagdia 409793Sakash.bagdia@arm.com * Andreas Hansson 4110000Sclt67@cornell.edu * Christopher Torng 4210249Sstephan.diestelhorst@arm.com * Stephan Diestelhorst 439793Sakash.bagdia@arm.com */ 449793Sakash.bagdia@arm.com 4511793Sbrandon.potter@amd.com#include "sim/clock_domain.hh" 4611793Sbrandon.potter@amd.com 4710249Sstephan.diestelhorst@arm.com#include <algorithm> 4810249Sstephan.diestelhorst@arm.com#include <functional> 4910249Sstephan.diestelhorst@arm.com 509793Sakash.bagdia@arm.com#include "debug/ClockDomain.hh" 519793Sakash.bagdia@arm.com#include "params/ClockDomain.hh" 529793Sakash.bagdia@arm.com#include "params/DerivedClockDomain.hh" 539793Sakash.bagdia@arm.com#include "params/SrcClockDomain.hh" 5411793Sbrandon.potter@amd.com#include "sim/clocked_object.hh" 559827Sakash.bagdia@arm.com#include "sim/voltage_domain.hh" 569793Sakash.bagdia@arm.com 5710021Sandreas.hansson@arm.comvoid 5810021Sandreas.hansson@arm.comClockDomain::regStats() 5910021Sandreas.hansson@arm.com{ 6011523Sdavid.guillen@arm.com SimObject::regStats(); 6111523Sdavid.guillen@arm.com 6210021Sandreas.hansson@arm.com using namespace Stats; 6310021Sandreas.hansson@arm.com 6410021Sandreas.hansson@arm.com // Expose the current clock period as a stat for observability in 6510021Sandreas.hansson@arm.com // the dumps 6610021Sandreas.hansson@arm.com currentClock 6710021Sandreas.hansson@arm.com .scalar(_clockPeriod) 6810021Sandreas.hansson@arm.com .name(params()->name + ".clock") 6910021Sandreas.hansson@arm.com .desc("Clock period in ticks") 7010021Sandreas.hansson@arm.com ; 7110021Sandreas.hansson@arm.com} 7210021Sandreas.hansson@arm.com 739827Sakash.bagdia@arm.comdouble 749827Sakash.bagdia@arm.comClockDomain::voltage() const 759827Sakash.bagdia@arm.com{ 769827Sakash.bagdia@arm.com return _voltageDomain->voltage(); 779827Sakash.bagdia@arm.com} 789827Sakash.bagdia@arm.com 799827Sakash.bagdia@arm.comSrcClockDomain::SrcClockDomain(const Params *p) : 8010249Sstephan.diestelhorst@arm.com ClockDomain(p, p->voltage_domain), 8110249Sstephan.diestelhorst@arm.com freqOpPoints(p->clock), 8210249Sstephan.diestelhorst@arm.com _domainID(p->domain_id), 8310249Sstephan.diestelhorst@arm.com _perfLevel(p->init_perf_level) 849793Sakash.bagdia@arm.com{ 8510249Sstephan.diestelhorst@arm.com VoltageDomain *vdom = p->voltage_domain; 8610249Sstephan.diestelhorst@arm.com 8710249Sstephan.diestelhorst@arm.com fatal_if(freqOpPoints.empty(), "DVFS: Empty set of frequencies for "\ 8810249Sstephan.diestelhorst@arm.com "domain %d %s\n", _domainID, name()); 8910249Sstephan.diestelhorst@arm.com 9010249Sstephan.diestelhorst@arm.com fatal_if(!vdom, "DVFS: Empty voltage domain specified for "\ 9110249Sstephan.diestelhorst@arm.com "domain %d %s\n", _domainID, name()); 9210249Sstephan.diestelhorst@arm.com 9310249Sstephan.diestelhorst@arm.com fatal_if((vdom->numVoltages() > 1) && 9410249Sstephan.diestelhorst@arm.com (vdom->numVoltages() != freqOpPoints.size()), 9510249Sstephan.diestelhorst@arm.com "DVFS: Number of frequency and voltage scaling points do "\ 9610249Sstephan.diestelhorst@arm.com "not match: %d:%d ID: %d %s.\n", vdom->numVoltages(), 9710249Sstephan.diestelhorst@arm.com freqOpPoints.size(), _domainID, name()); 9810249Sstephan.diestelhorst@arm.com 9910249Sstephan.diestelhorst@arm.com // Frequency (& voltage) points should be declared in descending order, 10010249Sstephan.diestelhorst@arm.com // NOTE: Frequency is inverted to ticks, so checking for ascending ticks 10110249Sstephan.diestelhorst@arm.com fatal_if(!std::is_sorted(freqOpPoints.begin(), freqOpPoints.end()), 10210249Sstephan.diestelhorst@arm.com "DVFS: Frequency operation points not in descending order for "\ 10310249Sstephan.diestelhorst@arm.com "domain with ID %d\n", _domainID); 10410249Sstephan.diestelhorst@arm.com 10510249Sstephan.diestelhorst@arm.com fatal_if(_perfLevel >= freqOpPoints.size(), "DVFS: Initial DVFS point %d "\ 10610249Sstephan.diestelhorst@arm.com "is outside of list for Domain ID: %d\n", _perfLevel, _domainID); 10710249Sstephan.diestelhorst@arm.com 10810249Sstephan.diestelhorst@arm.com clockPeriod(freqOpPoints[_perfLevel]); 10910249Sstephan.diestelhorst@arm.com 11010249Sstephan.diestelhorst@arm.com vdom->registerSrcClockDom(this); 1119793Sakash.bagdia@arm.com} 1129793Sakash.bagdia@arm.com 1139793Sakash.bagdia@arm.comvoid 1149793Sakash.bagdia@arm.comSrcClockDomain::clockPeriod(Tick clock_period) 1159793Sakash.bagdia@arm.com{ 1169793Sakash.bagdia@arm.com if (clock_period == 0) { 1179793Sakash.bagdia@arm.com fatal("%s has a clock period of zero\n", name()); 1189793Sakash.bagdia@arm.com } 1199793Sakash.bagdia@arm.com 12010000Sclt67@cornell.edu // Align all members to the current tick 12110000Sclt67@cornell.edu for (auto m = members.begin(); m != members.end(); ++m) { 12210000Sclt67@cornell.edu (*m)->updateClockPeriod(); 12310000Sclt67@cornell.edu } 12410000Sclt67@cornell.edu 1259793Sakash.bagdia@arm.com _clockPeriod = clock_period; 1269793Sakash.bagdia@arm.com 1279793Sakash.bagdia@arm.com DPRINTF(ClockDomain, 1289793Sakash.bagdia@arm.com "Setting clock period to %d ticks for source clock %s\n", 1299793Sakash.bagdia@arm.com _clockPeriod, name()); 1309793Sakash.bagdia@arm.com 1319793Sakash.bagdia@arm.com // inform any derived clocks they need to updated their period 1329793Sakash.bagdia@arm.com for (auto c = children.begin(); c != children.end(); ++c) { 1339793Sakash.bagdia@arm.com (*c)->updateClockPeriod(); 1349793Sakash.bagdia@arm.com } 1359793Sakash.bagdia@arm.com} 1369793Sakash.bagdia@arm.com 13710249Sstephan.diestelhorst@arm.comvoid 13810249Sstephan.diestelhorst@arm.comSrcClockDomain::perfLevel(PerfLevel perf_level) 13910249Sstephan.diestelhorst@arm.com{ 14010249Sstephan.diestelhorst@arm.com assert(validPerfLevel(perf_level)); 14110249Sstephan.diestelhorst@arm.com 14210395Sstephan.diestelhorst@arm.com if (perf_level == _perfLevel) { 14310395Sstephan.diestelhorst@arm.com // Silently ignore identical overwrites 14410395Sstephan.diestelhorst@arm.com return; 14510395Sstephan.diestelhorst@arm.com } 14610395Sstephan.diestelhorst@arm.com 14710249Sstephan.diestelhorst@arm.com DPRINTF(ClockDomain, "DVFS: Switching performance level of domain %s "\ 14810249Sstephan.diestelhorst@arm.com "(id: %d) from %d to %d\n", name(), domainID(), _perfLevel, 14910249Sstephan.diestelhorst@arm.com perf_level); 15010249Sstephan.diestelhorst@arm.com 15110249Sstephan.diestelhorst@arm.com _perfLevel = perf_level; 15210249Sstephan.diestelhorst@arm.com 15311416Ssascha.bischoff@ARM.com signalPerfLevelUpdate(); 15411416Ssascha.bischoff@ARM.com} 15511416Ssascha.bischoff@ARM.com 15611416Ssascha.bischoff@ARM.comvoid SrcClockDomain::signalPerfLevelUpdate() 15711416Ssascha.bischoff@ARM.com{ 15810249Sstephan.diestelhorst@arm.com // Signal the voltage domain that we have changed our perf level so that the 15910249Sstephan.diestelhorst@arm.com // voltage domain can recompute its performance level 16010249Sstephan.diestelhorst@arm.com voltageDomain()->sanitiseVoltages(); 16110249Sstephan.diestelhorst@arm.com 16210249Sstephan.diestelhorst@arm.com // Integrated switching of the actual clock value, too 16310249Sstephan.diestelhorst@arm.com clockPeriod(clkPeriodAtPerfLevel()); 16410249Sstephan.diestelhorst@arm.com} 16510249Sstephan.diestelhorst@arm.com 16610249Sstephan.diestelhorst@arm.comvoid 16710905Sandreas.sandberg@arm.comSrcClockDomain::serialize(CheckpointOut &cp) const 16810249Sstephan.diestelhorst@arm.com{ 16910249Sstephan.diestelhorst@arm.com SERIALIZE_SCALAR(_perfLevel); 17010905Sandreas.sandberg@arm.com ClockDomain::serialize(cp); 17110249Sstephan.diestelhorst@arm.com} 17210249Sstephan.diestelhorst@arm.com 17310249Sstephan.diestelhorst@arm.comvoid 17410905Sandreas.sandberg@arm.comSrcClockDomain::unserialize(CheckpointIn &cp) 17510249Sstephan.diestelhorst@arm.com{ 17610905Sandreas.sandberg@arm.com ClockDomain::unserialize(cp); 17710249Sstephan.diestelhorst@arm.com UNSERIALIZE_SCALAR(_perfLevel); 17810395Sstephan.diestelhorst@arm.com} 17910395Sstephan.diestelhorst@arm.com 18010395Sstephan.diestelhorst@arm.comvoid 18110395Sstephan.diestelhorst@arm.comSrcClockDomain::startup() 18210395Sstephan.diestelhorst@arm.com{ 18310395Sstephan.diestelhorst@arm.com // Perform proper clock update when all related components have been 18410395Sstephan.diestelhorst@arm.com // created (i.e. after unserialization / object creation) 18511416Ssascha.bischoff@ARM.com signalPerfLevelUpdate(); 18610249Sstephan.diestelhorst@arm.com} 18710249Sstephan.diestelhorst@arm.com 1889793Sakash.bagdia@arm.comSrcClockDomain * 1899793Sakash.bagdia@arm.comSrcClockDomainParams::create() 1909793Sakash.bagdia@arm.com{ 1919793Sakash.bagdia@arm.com return new SrcClockDomain(this); 1929793Sakash.bagdia@arm.com} 1939793Sakash.bagdia@arm.com 1949793Sakash.bagdia@arm.comDerivedClockDomain::DerivedClockDomain(const Params *p) : 1959827Sakash.bagdia@arm.com ClockDomain(p, p->clk_domain->voltageDomain()), 1969793Sakash.bagdia@arm.com parent(*p->clk_domain), 1979793Sakash.bagdia@arm.com clockDivider(p->clk_divider) 1989793Sakash.bagdia@arm.com{ 1999793Sakash.bagdia@arm.com // Ensure that clock divider setting works as frequency divider and never 2009793Sakash.bagdia@arm.com // work as frequency multiplier 2019793Sakash.bagdia@arm.com if (clockDivider < 1) { 2029793Sakash.bagdia@arm.com fatal("Clock divider param cannot be less than 1"); 2039793Sakash.bagdia@arm.com } 2049793Sakash.bagdia@arm.com 2059793Sakash.bagdia@arm.com // let the parent keep track of this derived domain so that it can 2069793Sakash.bagdia@arm.com // propagate changes 2079793Sakash.bagdia@arm.com parent.addDerivedDomain(this); 2089793Sakash.bagdia@arm.com 2099793Sakash.bagdia@arm.com // update our clock period based on the parents clock 2109793Sakash.bagdia@arm.com updateClockPeriod(); 2119793Sakash.bagdia@arm.com} 2129793Sakash.bagdia@arm.com 2139793Sakash.bagdia@arm.comvoid 2149793Sakash.bagdia@arm.comDerivedClockDomain::updateClockPeriod() 2159793Sakash.bagdia@arm.com{ 21610000Sclt67@cornell.edu // Align all members to the current tick 21710000Sclt67@cornell.edu for (auto m = members.begin(); m != members.end(); ++m) { 21810000Sclt67@cornell.edu (*m)->updateClockPeriod(); 21910000Sclt67@cornell.edu } 22010000Sclt67@cornell.edu 2219793Sakash.bagdia@arm.com // recalculate the clock period, relying on the fact that changes 2229793Sakash.bagdia@arm.com // propagate downwards in the tree 2239793Sakash.bagdia@arm.com _clockPeriod = parent.clockPeriod() * clockDivider; 2249793Sakash.bagdia@arm.com 2259793Sakash.bagdia@arm.com DPRINTF(ClockDomain, 2269793Sakash.bagdia@arm.com "Setting clock period to %d ticks for derived clock %s\n", 2279793Sakash.bagdia@arm.com _clockPeriod, name()); 2289793Sakash.bagdia@arm.com 2299793Sakash.bagdia@arm.com // inform any derived clocks 2309793Sakash.bagdia@arm.com for (auto c = children.begin(); c != children.end(); ++c) { 2319793Sakash.bagdia@arm.com (*c)->updateClockPeriod(); 2329793Sakash.bagdia@arm.com } 2339793Sakash.bagdia@arm.com} 2349793Sakash.bagdia@arm.com 2359793Sakash.bagdia@arm.comDerivedClockDomain * 2369793Sakash.bagdia@arm.comDerivedClockDomainParams::create() 2379793Sakash.bagdia@arm.com{ 2389793Sakash.bagdia@arm.com return new DerivedClockDomain(this); 2399793Sakash.bagdia@arm.com} 240