dvfs_handler.cc (10249:6bbb7ae309ac) dvfs_handler.cc (10395:77b9f96786c1)
1/*
2 * Copyright (c) 2013-2014 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Vasileios Spiliopoulos
38 * Akash Bagdia
39 * Stephan Diestelhorst
40 */
41
42#include <set>
43#include <utility>
44
45#include "base/misc.hh"
46#include "debug/DVFS.hh"
47#include "params/DVFSHandler.hh"
48#include "sim/clock_domain.hh"
49#include "sim/dvfs_handler.hh"
50#include "sim/stat_control.hh"
51#include "sim/voltage_domain.hh"
52
53//
54//
55// DVFSHandler methods implementation
56//
57
58DVFSHandler::DVFSHandler(const Params *p)
59 : SimObject(p),
60 sysClkDomain(p->sys_clk_domain),
61 enableHandler(p->enable),
62 _transLatency(p->transition_latency)
63{
64 // Check supplied list of domains for sanity and add them to the
65 // domain ID -> domain* hash
66 for(auto dit = p->domains.begin(); dit != p->domains.end(); ++dit) {
67 SrcClockDomain *d = *dit;
68 DomainID domain_id = d->domainID();
69
70 fatal_if(sysClkDomain == d, "DVFS: Domain config list has a "\
71 "system clk domain entry");
72 fatal_if(domain_id == SrcClockDomain::emptyDomainID,
73 "DVFS: Controlled domain %s needs to have a properly "\
74 " assigned ID.\n", d->name());
75
76 auto entry = std::make_pair(domain_id, d);
77 bool new_elem = domains.insert(entry).second;
78 fatal_if(!new_elem, "DVFS: Domain %s with ID %d does not have a "\
79 "unique ID.\n", d->name(), domain_id);
80
81 // Create a dedicated event slot per known domain ID
82 UpdateEvent *event = &updatePerfLevelEvents[domain_id];
83 event->domainIDToSet = d->domainID();
1/*
2 * Copyright (c) 2013-2014 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Vasileios Spiliopoulos
38 * Akash Bagdia
39 * Stephan Diestelhorst
40 */
41
42#include <set>
43#include <utility>
44
45#include "base/misc.hh"
46#include "debug/DVFS.hh"
47#include "params/DVFSHandler.hh"
48#include "sim/clock_domain.hh"
49#include "sim/dvfs_handler.hh"
50#include "sim/stat_control.hh"
51#include "sim/voltage_domain.hh"
52
53//
54//
55// DVFSHandler methods implementation
56//
57
58DVFSHandler::DVFSHandler(const Params *p)
59 : SimObject(p),
60 sysClkDomain(p->sys_clk_domain),
61 enableHandler(p->enable),
62 _transLatency(p->transition_latency)
63{
64 // Check supplied list of domains for sanity and add them to the
65 // domain ID -> domain* hash
66 for(auto dit = p->domains.begin(); dit != p->domains.end(); ++dit) {
67 SrcClockDomain *d = *dit;
68 DomainID domain_id = d->domainID();
69
70 fatal_if(sysClkDomain == d, "DVFS: Domain config list has a "\
71 "system clk domain entry");
72 fatal_if(domain_id == SrcClockDomain::emptyDomainID,
73 "DVFS: Controlled domain %s needs to have a properly "\
74 " assigned ID.\n", d->name());
75
76 auto entry = std::make_pair(domain_id, d);
77 bool new_elem = domains.insert(entry).second;
78 fatal_if(!new_elem, "DVFS: Domain %s with ID %d does not have a "\
79 "unique ID.\n", d->name(), domain_id);
80
81 // Create a dedicated event slot per known domain ID
82 UpdateEvent *event = &updatePerfLevelEvents[domain_id];
83 event->domainIDToSet = d->domainID();
84
85 // Add domain ID to the list of domains
86 domainIDList.push_back(d->domainID());
84 }
85 UpdateEvent::dvfsHandler = this;
86}
87
88DVFSHandler *DVFSHandler::UpdateEvent::dvfsHandler;
89
87 }
88 UpdateEvent::dvfsHandler = this;
89}
90
91DVFSHandler *DVFSHandler::UpdateEvent::dvfsHandler;
92
93DVFSHandler::DomainID
94DVFSHandler::domainID(uint32_t index) const
95{
96 fatal_if(index >= numDomains(), "DVFS: Requested index out of "\
97 "bound, max value %d\n", (domainIDList.size() - 1));
98
99 assert(domains.find(domainIDList[index]) != domains.end());
100
101 return domainIDList[index];
102}
103
90bool
91DVFSHandler::validDomainID(DomainID domain_id) const
92{
93 assert(isEnabled());
94 // This is ensure that the domain id as requested by the software is
95 // availabe in the handler.
96 if (domains.find(domain_id) != domains.end())
97 return true;
98 warn("DVFS: invalid domain ID %d, the DVFS handler does not handle this "\
99 "domain\n", domain_id);
100 return false;
101}
102
103bool
104DVFSHandler::perfLevel(DomainID domain_id, PerfLevel perf_level)
105{
106 assert(isEnabled());
107
108 DPRINTF(DVFS, "DVFS: setPerfLevel domain %d -> %d\n", domain_id, perf_level);
109
110 auto d = findDomain(domain_id);
111 if (!d->validPerfLevel(perf_level)) {
112 warn("DVFS: invalid performance level %d for domain ID %d, request "\
113 "ignored\n", perf_level, domain_id);
114 return false;
115 }
116
117 UpdateEvent *update_event = &updatePerfLevelEvents[domain_id];
118 // Drop an old DVFS change request once we have established that this is a
119 // reasonable request
120 if (update_event->scheduled()) {
121 DPRINTF(DVFS, "DVFS: Overwriting the previous DVFS event.\n");
122 deschedule(update_event);
123 }
124
125 update_event->perfLevelToSet = perf_level;
126
127 // State changes that restore to the current state (and / or overwrite a not
128 // yet completed in-flight request) will be squashed
129 if (d->perfLevel() == perf_level) {
130 DPRINTF(DVFS, "DVFS: Ignoring ineffective performance level change "\
131 "%d -> %d\n", d->perfLevel(), perf_level);
132 return false;
133 }
134
135 // At this point, a new transition will certainly take place -> schedule
136 Tick when = curTick() + _transLatency;
137 DPRINTF(DVFS, "DVFS: Update for perf event scheduled for %ld\n", when);
138
139 schedule(update_event, when);
140 return true;
141}
142
143void
144DVFSHandler::UpdateEvent::updatePerfLevel()
145{
146 // Perform explicit stats dump for power estimation before performance
147 // level migration
148 Stats::dump();
149 Stats::reset();
150
151 // Update the performance level in the clock domain
152 auto d = dvfsHandler->findDomain(domainIDToSet);
153 assert(d->perfLevel() != perfLevelToSet);
154
155 d->perfLevel(perfLevelToSet);
156}
157
158void
159DVFSHandler::serialize(std::ostream &os)
160{
161 //This is to ensure that the handler status is maintained during the
162 //entire simulation run and not changed from command line during checkpoint
163 //and restore
164 SERIALIZE_SCALAR(enableHandler);
165
166 // Pull out the hashed data structure into easy-to-serialise arrays;
167 // ensuring that the data associated with any pending update event is saved
168 std::vector<DomainID> domain_ids;
169 std::vector<PerfLevel> perf_levels;
170 std::vector<Tick> whens;
171 for (auto it = updatePerfLevelEvents.begin();
172 it != updatePerfLevelEvents.end(); ++it) {
173 DomainID id = it->first;
174 UpdateEvent *event = &it->second;
175
176 assert(id == event->domainIDToSet);
177 domain_ids.push_back(id);
178 perf_levels.push_back(event->perfLevelToSet);
179 whens.push_back(event->scheduled() ? event->when() : 0);
180 }
181 arrayParamOut(os, "domain_ids", domain_ids);
182 arrayParamOut(os, "perf_levels", perf_levels);
183 arrayParamOut(os, "whens", whens);
184}
185
186void
187DVFSHandler::unserialize(Checkpoint *cp, const std::string &section)
188{
104bool
105DVFSHandler::validDomainID(DomainID domain_id) const
106{
107 assert(isEnabled());
108 // This is ensure that the domain id as requested by the software is
109 // availabe in the handler.
110 if (domains.find(domain_id) != domains.end())
111 return true;
112 warn("DVFS: invalid domain ID %d, the DVFS handler does not handle this "\
113 "domain\n", domain_id);
114 return false;
115}
116
117bool
118DVFSHandler::perfLevel(DomainID domain_id, PerfLevel perf_level)
119{
120 assert(isEnabled());
121
122 DPRINTF(DVFS, "DVFS: setPerfLevel domain %d -> %d\n", domain_id, perf_level);
123
124 auto d = findDomain(domain_id);
125 if (!d->validPerfLevel(perf_level)) {
126 warn("DVFS: invalid performance level %d for domain ID %d, request "\
127 "ignored\n", perf_level, domain_id);
128 return false;
129 }
130
131 UpdateEvent *update_event = &updatePerfLevelEvents[domain_id];
132 // Drop an old DVFS change request once we have established that this is a
133 // reasonable request
134 if (update_event->scheduled()) {
135 DPRINTF(DVFS, "DVFS: Overwriting the previous DVFS event.\n");
136 deschedule(update_event);
137 }
138
139 update_event->perfLevelToSet = perf_level;
140
141 // State changes that restore to the current state (and / or overwrite a not
142 // yet completed in-flight request) will be squashed
143 if (d->perfLevel() == perf_level) {
144 DPRINTF(DVFS, "DVFS: Ignoring ineffective performance level change "\
145 "%d -> %d\n", d->perfLevel(), perf_level);
146 return false;
147 }
148
149 // At this point, a new transition will certainly take place -> schedule
150 Tick when = curTick() + _transLatency;
151 DPRINTF(DVFS, "DVFS: Update for perf event scheduled for %ld\n", when);
152
153 schedule(update_event, when);
154 return true;
155}
156
157void
158DVFSHandler::UpdateEvent::updatePerfLevel()
159{
160 // Perform explicit stats dump for power estimation before performance
161 // level migration
162 Stats::dump();
163 Stats::reset();
164
165 // Update the performance level in the clock domain
166 auto d = dvfsHandler->findDomain(domainIDToSet);
167 assert(d->perfLevel() != perfLevelToSet);
168
169 d->perfLevel(perfLevelToSet);
170}
171
172void
173DVFSHandler::serialize(std::ostream &os)
174{
175 //This is to ensure that the handler status is maintained during the
176 //entire simulation run and not changed from command line during checkpoint
177 //and restore
178 SERIALIZE_SCALAR(enableHandler);
179
180 // Pull out the hashed data structure into easy-to-serialise arrays;
181 // ensuring that the data associated with any pending update event is saved
182 std::vector<DomainID> domain_ids;
183 std::vector<PerfLevel> perf_levels;
184 std::vector<Tick> whens;
185 for (auto it = updatePerfLevelEvents.begin();
186 it != updatePerfLevelEvents.end(); ++it) {
187 DomainID id = it->first;
188 UpdateEvent *event = &it->second;
189
190 assert(id == event->domainIDToSet);
191 domain_ids.push_back(id);
192 perf_levels.push_back(event->perfLevelToSet);
193 whens.push_back(event->scheduled() ? event->when() : 0);
194 }
195 arrayParamOut(os, "domain_ids", domain_ids);
196 arrayParamOut(os, "perf_levels", perf_levels);
197 arrayParamOut(os, "whens", whens);
198}
199
200void
201DVFSHandler::unserialize(Checkpoint *cp, const std::string &section)
202{
203 bool temp = enableHandler;
204
189 UNSERIALIZE_SCALAR(enableHandler);
190
205 UNSERIALIZE_SCALAR(enableHandler);
206
207 if(temp != enableHandler) {
208 warn("DVFS: Forcing enable handler status to unserialized value of %d",
209 enableHandler);
210 }
211
191 // Reconstruct the map of domain IDs and their scheduled events
192 std::vector<DomainID> domain_ids;
193 std::vector<PerfLevel> perf_levels;
194 std::vector<Tick> whens;
195 arrayParamIn(cp, section, "domain_ids", domain_ids);
196 arrayParamIn(cp, section, "perf_levels", perf_levels);
197 arrayParamIn(cp, section, "whens", whens);
198
199 for (size_t i = 0; i < domain_ids.size(); ++i) {;
200 UpdateEvent *event = &updatePerfLevelEvents[domain_ids[i]];
201
202 event->domainIDToSet = domain_ids[i];
203 event->perfLevelToSet = perf_levels[i];
204
205 // Schedule all previously scheduled events
206 if (whens[i])
207 schedule(event, whens[i]);
208 }
209 UpdateEvent::dvfsHandler = this;
210}
211
212DVFSHandler*
213DVFSHandlerParams::create()
214{
215 return new DVFSHandler(this);
216}
212 // Reconstruct the map of domain IDs and their scheduled events
213 std::vector<DomainID> domain_ids;
214 std::vector<PerfLevel> perf_levels;
215 std::vector<Tick> whens;
216 arrayParamIn(cp, section, "domain_ids", domain_ids);
217 arrayParamIn(cp, section, "perf_levels", perf_levels);
218 arrayParamIn(cp, section, "whens", whens);
219
220 for (size_t i = 0; i < domain_ids.size(); ++i) {;
221 UpdateEvent *event = &updatePerfLevelEvents[domain_ids[i]];
222
223 event->domainIDToSet = domain_ids[i];
224 event->perfLevelToSet = perf_levels[i];
225
226 // Schedule all previously scheduled events
227 if (whens[i])
228 schedule(event, whens[i]);
229 }
230 UpdateEvent::dvfsHandler = this;
231}
232
233DVFSHandler*
234DVFSHandlerParams::create()
235{
236 return new DVFSHandler(this);
237}