X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fsim%2Fclock_domain.cc;h=8f45bba0930138397a24c0b7665c56c39f16dae0;hb=072f78471d11c31b6009beb572296f704912d0f7;hp=0d1836e83c00c1070d5f1799ce8c73eafdf44f3b;hpb=1d85e914a6b7a9b3550e84d2006ba775a27a0a44;p=gem5.git diff --git a/src/sim/clock_domain.cc b/src/sim/clock_domain.cc index 0d1836e83..8f45bba09 100644 --- a/src/sim/clock_domain.cc +++ b/src/sim/clock_domain.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 ARM Limited + * Copyright (c) 2013-2014 ARM Limited * Copyright (c) 2013 Cornell University * All rights reserved * @@ -39,8 +39,12 @@ * Akash Bagdia * Andreas Hansson * Christopher Torng + * Stephan Diestelhorst */ +#include +#include + #include "debug/ClockDomain.hh" #include "params/ClockDomain.hh" #include "params/DerivedClockDomain.hh" @@ -70,9 +74,37 @@ ClockDomain::voltage() const } SrcClockDomain::SrcClockDomain(const Params *p) : - ClockDomain(p, p->voltage_domain) + ClockDomain(p, p->voltage_domain), + freqOpPoints(p->clock), + _domainID(p->domain_id), + _perfLevel(p->init_perf_level) { - clockPeriod(p->clock); + VoltageDomain *vdom = p->voltage_domain; + + fatal_if(freqOpPoints.empty(), "DVFS: Empty set of frequencies for "\ + "domain %d %s\n", _domainID, name()); + + fatal_if(!vdom, "DVFS: Empty voltage domain specified for "\ + "domain %d %s\n", _domainID, name()); + + fatal_if((vdom->numVoltages() > 1) && + (vdom->numVoltages() != freqOpPoints.size()), + "DVFS: Number of frequency and voltage scaling points do "\ + "not match: %d:%d ID: %d %s.\n", vdom->numVoltages(), + freqOpPoints.size(), _domainID, name()); + + // Frequency (& voltage) points should be declared in descending order, + // NOTE: Frequency is inverted to ticks, so checking for ascending ticks + fatal_if(!std::is_sorted(freqOpPoints.begin(), freqOpPoints.end()), + "DVFS: Frequency operation points not in descending order for "\ + "domain with ID %d\n", _domainID); + + fatal_if(_perfLevel >= freqOpPoints.size(), "DVFS: Initial DVFS point %d "\ + "is outside of list for Domain ID: %d\n", _perfLevel, _domainID); + + clockPeriod(freqOpPoints[_perfLevel]); + + vdom->registerSrcClockDom(this); } void @@ -99,6 +131,52 @@ SrcClockDomain::clockPeriod(Tick clock_period) } } +void +SrcClockDomain::perfLevel(PerfLevel perf_level) +{ + assert(validPerfLevel(perf_level)); + + if (perf_level == _perfLevel) { + // Silently ignore identical overwrites + return; + } + + DPRINTF(ClockDomain, "DVFS: Switching performance level of domain %s "\ + "(id: %d) from %d to %d\n", name(), domainID(), _perfLevel, + perf_level); + + _perfLevel = perf_level; + + // Signal the voltage domain that we have changed our perf level so that the + // voltage domain can recompute its performance level + voltageDomain()->sanitiseVoltages(); + + // Integrated switching of the actual clock value, too + clockPeriod(clkPeriodAtPerfLevel()); +} + +void +SrcClockDomain::serialize(std::ostream &os) +{ + SERIALIZE_SCALAR(_perfLevel); + ClockDomain::serialize(os); +} + +void +SrcClockDomain::unserialize(Checkpoint *cp, const std::string §ion) +{ + ClockDomain::unserialize(cp, section); + UNSERIALIZE_SCALAR(_perfLevel); +} + +void +SrcClockDomain::startup() +{ + // Perform proper clock update when all related components have been + // created (i.e. after unserialization / object creation) + perfLevel(_perfLevel); +} + SrcClockDomain * SrcClockDomainParams::create() {