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 5011800Sbrandon.potter@amd.com#include "base/trace.hh" 519793Sakash.bagdia@arm.com#include "debug/ClockDomain.hh" 529793Sakash.bagdia@arm.com#include "params/ClockDomain.hh" 539793Sakash.bagdia@arm.com#include "params/DerivedClockDomain.hh" 549793Sakash.bagdia@arm.com#include "params/SrcClockDomain.hh" 5511793Sbrandon.potter@amd.com#include "sim/clocked_object.hh" 569827Sakash.bagdia@arm.com#include "sim/voltage_domain.hh" 579793Sakash.bagdia@arm.com 5810021Sandreas.hansson@arm.comvoid 5910021Sandreas.hansson@arm.comClockDomain::regStats() 6010021Sandreas.hansson@arm.com{ 6111523Sdavid.guillen@arm.com SimObject::regStats(); 6211523Sdavid.guillen@arm.com 6310021Sandreas.hansson@arm.com using namespace Stats; 6410021Sandreas.hansson@arm.com 6510021Sandreas.hansson@arm.com // Expose the current clock period as a stat for observability in 6610021Sandreas.hansson@arm.com // the dumps 6710021Sandreas.hansson@arm.com currentClock 6810021Sandreas.hansson@arm.com .scalar(_clockPeriod) 6910021Sandreas.hansson@arm.com .name(params()->name + ".clock") 7010021Sandreas.hansson@arm.com .desc("Clock period in ticks") 7110021Sandreas.hansson@arm.com ; 7210021Sandreas.hansson@arm.com} 7310021Sandreas.hansson@arm.com 749827Sakash.bagdia@arm.comdouble 759827Sakash.bagdia@arm.comClockDomain::voltage() const 769827Sakash.bagdia@arm.com{ 779827Sakash.bagdia@arm.com return _voltageDomain->voltage(); 789827Sakash.bagdia@arm.com} 799827Sakash.bagdia@arm.com 809827Sakash.bagdia@arm.comSrcClockDomain::SrcClockDomain(const Params *p) : 8110249Sstephan.diestelhorst@arm.com ClockDomain(p, p->voltage_domain), 8210249Sstephan.diestelhorst@arm.com freqOpPoints(p->clock), 8310249Sstephan.diestelhorst@arm.com _domainID(p->domain_id), 8410249Sstephan.diestelhorst@arm.com _perfLevel(p->init_perf_level) 859793Sakash.bagdia@arm.com{ 8610249Sstephan.diestelhorst@arm.com VoltageDomain *vdom = p->voltage_domain; 8710249Sstephan.diestelhorst@arm.com 8810249Sstephan.diestelhorst@arm.com fatal_if(freqOpPoints.empty(), "DVFS: Empty set of frequencies for "\ 8910249Sstephan.diestelhorst@arm.com "domain %d %s\n", _domainID, name()); 9010249Sstephan.diestelhorst@arm.com 9110249Sstephan.diestelhorst@arm.com fatal_if(!vdom, "DVFS: Empty voltage domain specified for "\ 9210249Sstephan.diestelhorst@arm.com "domain %d %s\n", _domainID, name()); 9310249Sstephan.diestelhorst@arm.com 9410249Sstephan.diestelhorst@arm.com fatal_if((vdom->numVoltages() > 1) && 9510249Sstephan.diestelhorst@arm.com (vdom->numVoltages() != freqOpPoints.size()), 9610249Sstephan.diestelhorst@arm.com "DVFS: Number of frequency and voltage scaling points do "\ 9710249Sstephan.diestelhorst@arm.com "not match: %d:%d ID: %d %s.\n", vdom->numVoltages(), 9810249Sstephan.diestelhorst@arm.com freqOpPoints.size(), _domainID, name()); 9910249Sstephan.diestelhorst@arm.com 10010249Sstephan.diestelhorst@arm.com // Frequency (& voltage) points should be declared in descending order, 10110249Sstephan.diestelhorst@arm.com // NOTE: Frequency is inverted to ticks, so checking for ascending ticks 10210249Sstephan.diestelhorst@arm.com fatal_if(!std::is_sorted(freqOpPoints.begin(), freqOpPoints.end()), 10310249Sstephan.diestelhorst@arm.com "DVFS: Frequency operation points not in descending order for "\ 10410249Sstephan.diestelhorst@arm.com "domain with ID %d\n", _domainID); 10510249Sstephan.diestelhorst@arm.com 10610249Sstephan.diestelhorst@arm.com fatal_if(_perfLevel >= freqOpPoints.size(), "DVFS: Initial DVFS point %d "\ 10710249Sstephan.diestelhorst@arm.com "is outside of list for Domain ID: %d\n", _perfLevel, _domainID); 10810249Sstephan.diestelhorst@arm.com 10910249Sstephan.diestelhorst@arm.com clockPeriod(freqOpPoints[_perfLevel]); 11010249Sstephan.diestelhorst@arm.com 11110249Sstephan.diestelhorst@arm.com vdom->registerSrcClockDom(this); 1129793Sakash.bagdia@arm.com} 1139793Sakash.bagdia@arm.com 1149793Sakash.bagdia@arm.comvoid 1159793Sakash.bagdia@arm.comSrcClockDomain::clockPeriod(Tick clock_period) 1169793Sakash.bagdia@arm.com{ 1179793Sakash.bagdia@arm.com if (clock_period == 0) { 1189793Sakash.bagdia@arm.com fatal("%s has a clock period of zero\n", name()); 1199793Sakash.bagdia@arm.com } 1209793Sakash.bagdia@arm.com 12110000Sclt67@cornell.edu // Align all members to the current tick 12210000Sclt67@cornell.edu for (auto m = members.begin(); m != members.end(); ++m) { 12310000Sclt67@cornell.edu (*m)->updateClockPeriod(); 12410000Sclt67@cornell.edu } 12510000Sclt67@cornell.edu 1269793Sakash.bagdia@arm.com _clockPeriod = clock_period; 1279793Sakash.bagdia@arm.com 1289793Sakash.bagdia@arm.com DPRINTF(ClockDomain, 1299793Sakash.bagdia@arm.com "Setting clock period to %d ticks for source clock %s\n", 1309793Sakash.bagdia@arm.com _clockPeriod, name()); 1319793Sakash.bagdia@arm.com 1329793Sakash.bagdia@arm.com // inform any derived clocks they need to updated their period 1339793Sakash.bagdia@arm.com for (auto c = children.begin(); c != children.end(); ++c) { 1349793Sakash.bagdia@arm.com (*c)->updateClockPeriod(); 1359793Sakash.bagdia@arm.com } 1369793Sakash.bagdia@arm.com} 1379793Sakash.bagdia@arm.com 13810249Sstephan.diestelhorst@arm.comvoid 13910249Sstephan.diestelhorst@arm.comSrcClockDomain::perfLevel(PerfLevel perf_level) 14010249Sstephan.diestelhorst@arm.com{ 14110249Sstephan.diestelhorst@arm.com assert(validPerfLevel(perf_level)); 14210249Sstephan.diestelhorst@arm.com 14310395Sstephan.diestelhorst@arm.com if (perf_level == _perfLevel) { 14410395Sstephan.diestelhorst@arm.com // Silently ignore identical overwrites 14510395Sstephan.diestelhorst@arm.com return; 14610395Sstephan.diestelhorst@arm.com } 14710395Sstephan.diestelhorst@arm.com 14810249Sstephan.diestelhorst@arm.com DPRINTF(ClockDomain, "DVFS: Switching performance level of domain %s "\ 14910249Sstephan.diestelhorst@arm.com "(id: %d) from %d to %d\n", name(), domainID(), _perfLevel, 15010249Sstephan.diestelhorst@arm.com perf_level); 15110249Sstephan.diestelhorst@arm.com 15210249Sstephan.diestelhorst@arm.com _perfLevel = perf_level; 15310249Sstephan.diestelhorst@arm.com 15411416Ssascha.bischoff@ARM.com signalPerfLevelUpdate(); 15511416Ssascha.bischoff@ARM.com} 15611416Ssascha.bischoff@ARM.com 15711416Ssascha.bischoff@ARM.comvoid SrcClockDomain::signalPerfLevelUpdate() 15811416Ssascha.bischoff@ARM.com{ 15910249Sstephan.diestelhorst@arm.com // Signal the voltage domain that we have changed our perf level so that the 16010249Sstephan.diestelhorst@arm.com // voltage domain can recompute its performance level 16110249Sstephan.diestelhorst@arm.com voltageDomain()->sanitiseVoltages(); 16210249Sstephan.diestelhorst@arm.com 16310249Sstephan.diestelhorst@arm.com // Integrated switching of the actual clock value, too 16410249Sstephan.diestelhorst@arm.com clockPeriod(clkPeriodAtPerfLevel()); 16510249Sstephan.diestelhorst@arm.com} 16610249Sstephan.diestelhorst@arm.com 16710249Sstephan.diestelhorst@arm.comvoid 16810905Sandreas.sandberg@arm.comSrcClockDomain::serialize(CheckpointOut &cp) const 16910249Sstephan.diestelhorst@arm.com{ 17010249Sstephan.diestelhorst@arm.com SERIALIZE_SCALAR(_perfLevel); 17110905Sandreas.sandberg@arm.com ClockDomain::serialize(cp); 17210249Sstephan.diestelhorst@arm.com} 17310249Sstephan.diestelhorst@arm.com 17410249Sstephan.diestelhorst@arm.comvoid 17510905Sandreas.sandberg@arm.comSrcClockDomain::unserialize(CheckpointIn &cp) 17610249Sstephan.diestelhorst@arm.com{ 17710905Sandreas.sandberg@arm.com ClockDomain::unserialize(cp); 17810249Sstephan.diestelhorst@arm.com UNSERIALIZE_SCALAR(_perfLevel); 17910395Sstephan.diestelhorst@arm.com} 18010395Sstephan.diestelhorst@arm.com 18110395Sstephan.diestelhorst@arm.comvoid 18210395Sstephan.diestelhorst@arm.comSrcClockDomain::startup() 18310395Sstephan.diestelhorst@arm.com{ 18410395Sstephan.diestelhorst@arm.com // Perform proper clock update when all related components have been 18510395Sstephan.diestelhorst@arm.com // created (i.e. after unserialization / object creation) 18611416Ssascha.bischoff@ARM.com signalPerfLevelUpdate(); 18710249Sstephan.diestelhorst@arm.com} 18810249Sstephan.diestelhorst@arm.com 1899793Sakash.bagdia@arm.comSrcClockDomain * 1909793Sakash.bagdia@arm.comSrcClockDomainParams::create() 1919793Sakash.bagdia@arm.com{ 1929793Sakash.bagdia@arm.com return new SrcClockDomain(this); 1939793Sakash.bagdia@arm.com} 1949793Sakash.bagdia@arm.com 1959793Sakash.bagdia@arm.comDerivedClockDomain::DerivedClockDomain(const Params *p) : 1969827Sakash.bagdia@arm.com ClockDomain(p, p->clk_domain->voltageDomain()), 1979793Sakash.bagdia@arm.com parent(*p->clk_domain), 1989793Sakash.bagdia@arm.com clockDivider(p->clk_divider) 1999793Sakash.bagdia@arm.com{ 2009793Sakash.bagdia@arm.com // Ensure that clock divider setting works as frequency divider and never 2019793Sakash.bagdia@arm.com // work as frequency multiplier 2029793Sakash.bagdia@arm.com if (clockDivider < 1) { 2039793Sakash.bagdia@arm.com fatal("Clock divider param cannot be less than 1"); 2049793Sakash.bagdia@arm.com } 2059793Sakash.bagdia@arm.com 2069793Sakash.bagdia@arm.com // let the parent keep track of this derived domain so that it can 2079793Sakash.bagdia@arm.com // propagate changes 2089793Sakash.bagdia@arm.com parent.addDerivedDomain(this); 2099793Sakash.bagdia@arm.com 2109793Sakash.bagdia@arm.com // update our clock period based on the parents clock 2119793Sakash.bagdia@arm.com updateClockPeriod(); 2129793Sakash.bagdia@arm.com} 2139793Sakash.bagdia@arm.com 2149793Sakash.bagdia@arm.comvoid 2159793Sakash.bagdia@arm.comDerivedClockDomain::updateClockPeriod() 2169793Sakash.bagdia@arm.com{ 21710000Sclt67@cornell.edu // Align all members to the current tick 21810000Sclt67@cornell.edu for (auto m = members.begin(); m != members.end(); ++m) { 21910000Sclt67@cornell.edu (*m)->updateClockPeriod(); 22010000Sclt67@cornell.edu } 22110000Sclt67@cornell.edu 2229793Sakash.bagdia@arm.com // recalculate the clock period, relying on the fact that changes 2239793Sakash.bagdia@arm.com // propagate downwards in the tree 2249793Sakash.bagdia@arm.com _clockPeriod = parent.clockPeriod() * clockDivider; 2259793Sakash.bagdia@arm.com 2269793Sakash.bagdia@arm.com DPRINTF(ClockDomain, 2279793Sakash.bagdia@arm.com "Setting clock period to %d ticks for derived clock %s\n", 2289793Sakash.bagdia@arm.com _clockPeriod, name()); 2299793Sakash.bagdia@arm.com 2309793Sakash.bagdia@arm.com // inform any derived clocks 2319793Sakash.bagdia@arm.com for (auto c = children.begin(); c != children.end(); ++c) { 2329793Sakash.bagdia@arm.com (*c)->updateClockPeriod(); 2339793Sakash.bagdia@arm.com } 2349793Sakash.bagdia@arm.com} 2359793Sakash.bagdia@arm.com 2369793Sakash.bagdia@arm.comDerivedClockDomain * 2379793Sakash.bagdia@arm.comDerivedClockDomainParams::create() 2389793Sakash.bagdia@arm.com{ 2399793Sakash.bagdia@arm.com return new DerivedClockDomain(this); 2409793Sakash.bagdia@arm.com} 241