sim, arch, base: Refactor the base remote GDB class.
[gem5.git] / src / sim / power / thermal_model.cc
1 /*
2 * Copyright (c) 2015 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: David Guillen Fandos
38 */
39
40 #include "sim/power/thermal_model.hh"
41
42 #include "base/statistics.hh"
43 #include "params/ThermalCapacitor.hh"
44 #include "params/ThermalReference.hh"
45 #include "params/ThermalResistor.hh"
46 #include "sim/clocked_object.hh"
47 #include "sim/linear_solver.hh"
48 #include "sim/power/thermal_domain.hh"
49 #include "sim/sim_object.hh"
50
51 /**
52 * ThermalReference
53 */
54 ThermalReference::ThermalReference(const Params *p)
55 : SimObject(p), _temperature(p->temperature), node(NULL)
56 {
57 }
58
59 ThermalReference *
60 ThermalReferenceParams::create()
61 {
62 return new ThermalReference(this);
63 }
64
65 void
66 ThermalReference::serialize(CheckpointOut &cp) const
67 {
68 SERIALIZE_SCALAR(_temperature);
69 }
70
71 void
72 ThermalReference::unserialize(CheckpointIn &cp)
73 {
74 UNSERIALIZE_SCALAR(_temperature);
75 }
76
77 LinearEquation
78 ThermalReference::getEquation(ThermalNode * n, unsigned nnodes,
79 double step) const {
80 // Just return an empty equation
81 return LinearEquation(nnodes);
82 }
83
84 /**
85 * ThermalResistor
86 */
87 ThermalResistor::ThermalResistor(const Params *p)
88 : SimObject(p), _resistance(p->resistance), node1(NULL), node2(NULL)
89 {
90 }
91
92 ThermalResistor *
93 ThermalResistorParams::create()
94 {
95 return new ThermalResistor(this);
96 }
97
98 void
99 ThermalResistor::serialize(CheckpointOut &cp) const
100 {
101 SERIALIZE_SCALAR(_resistance);
102 }
103
104 void
105 ThermalResistor::unserialize(CheckpointIn &cp)
106 {
107 UNSERIALIZE_SCALAR(_resistance);
108 }
109
110 LinearEquation
111 ThermalResistor::getEquation(ThermalNode * n, unsigned nnodes,
112 double step) const
113 {
114 // i[n] = (Vn2 - Vn1)/R
115 LinearEquation eq(nnodes);
116
117 if (n != node1 && n != node2)
118 return eq;
119
120 if (node1->isref)
121 eq[eq.cnt()] += -node1->temp / _resistance;
122 else
123 eq[node1->id] += -1.0f / _resistance;
124
125 if (node2->isref)
126 eq[eq.cnt()] += node2->temp / _resistance;
127 else
128 eq[node2->id] += 1.0f / _resistance;
129
130 // We've assumed n was node1, reverse if necessary
131 if (n == node2)
132 eq *= -1.0f;
133
134 return eq;
135 }
136
137 /**
138 * ThermalCapacitor
139 */
140 ThermalCapacitor::ThermalCapacitor(const Params *p)
141 : SimObject(p), _capacitance(p->capacitance), node1(NULL), node2(NULL)
142 {
143 }
144
145 ThermalCapacitor *
146 ThermalCapacitorParams::create()
147 {
148 return new ThermalCapacitor(this);
149 }
150
151 void
152 ThermalCapacitor::serialize(CheckpointOut &cp) const
153 {
154 SERIALIZE_SCALAR(_capacitance);
155 }
156
157 void
158 ThermalCapacitor::unserialize(CheckpointIn &cp)
159 {
160 UNSERIALIZE_SCALAR(_capacitance);
161 }
162
163 LinearEquation
164 ThermalCapacitor::getEquation(ThermalNode * n, unsigned nnodes,
165 double step) const
166 {
167 // i(t) = C * d(Vn2 - Vn1)/dt
168 // i[n] = C/step * (Vn2 - Vn1 - Vn2[n-1] + Vn1[n-1])
169 LinearEquation eq(nnodes);
170
171 if (n != node1 && n != node2)
172 return eq;
173
174 eq[eq.cnt()] += _capacitance / step * (node1->temp - node2->temp);
175
176 if (node1->isref)
177 eq[eq.cnt()] += _capacitance / step * (-node1->temp);
178 else
179 eq[node1->id] += -1.0f * _capacitance / step;
180
181 if (node2->isref)
182 eq[eq.cnt()] += _capacitance / step * (node2->temp);
183 else
184 eq[node2->id] += 1.0f * _capacitance / step;
185
186 // We've assumed n was node1, reverse if necessary
187 if (n == node2)
188 eq *= -1.0f;
189
190 return eq;
191 }
192
193 /**
194 * ThermalModel
195 */
196 ThermalModel::ThermalModel(const Params *p)
197 : ClockedObject(p), stepEvent([this]{ doStep(); }, name()), _step(p->step)
198 {
199 }
200
201 ThermalModel *
202 ThermalModelParams::create()
203 {
204 return new ThermalModel(this);
205 }
206
207 void
208 ThermalModel::serialize(CheckpointOut &cp) const
209 {
210 SERIALIZE_SCALAR(_step);
211 }
212
213 void
214 ThermalModel::unserialize(CheckpointIn &cp)
215 {
216 UNSERIALIZE_SCALAR(_step);
217 }
218
219 void
220 ThermalModel::doStep()
221 {
222 // Calculate new temperatures!
223 // For each node in the system, create the kirchhoff nodal equation
224 LinearSystem ls(eq_nodes.size());
225 for (unsigned i = 0; i < eq_nodes.size(); i++) {
226 auto n = eq_nodes[i];
227 LinearEquation node_equation (eq_nodes.size());
228 for (auto e : entities) {
229 LinearEquation eq = e->getEquation(n, eq_nodes.size(), _step);
230 node_equation = node_equation + eq;
231 }
232 ls[i] = node_equation;
233 }
234
235 // Get temperatures for this iteration
236 std::vector <double> temps = ls.solve();
237 for (unsigned i = 0; i < eq_nodes.size(); i++)
238 eq_nodes[i]->temp = temps[i];
239
240 // Schedule next computation
241 schedule(stepEvent, curTick() + SimClock::Int::s * _step);
242
243 // Notify everybody
244 for (auto dom : domains)
245 dom->emitUpdate();
246 }
247
248 void
249 ThermalModel::startup()
250 {
251 // Look for nodes connected to voltage references, these
252 // can be just set to the reference value (no nodal equation)
253 for (auto ref : references) {
254 ref->node->temp = ref->_temperature;
255 ref->node->isref = true;
256 }
257 // Setup the initial temperatures
258 for (auto dom : domains)
259 dom->getNode()->temp = dom->initialTemperature();
260
261 // Create a list of unknown temperature nodes
262 for (auto n : nodes) {
263 bool found = false;
264 for (auto ref : references)
265 if (ref->node == n) {
266 found = true;
267 break;
268 }
269 if (!found)
270 eq_nodes.push_back(n);
271 }
272
273 // Assign each node an ID
274 for (unsigned i = 0; i < eq_nodes.size(); i++)
275 eq_nodes[i]->id = i;
276
277 // Schedule first thermal update
278 schedule(stepEvent, curTick() + SimClock::Int::s * _step);
279 }
280
281 void ThermalModel::addDomain(ThermalDomain * d) {
282 domains.push_back(d);
283 entities.push_back(d);
284 }
285 void ThermalModel::addReference(ThermalReference * r) {
286 references.push_back(r);
287 entities.push_back(r);
288 }
289 void ThermalModel::addCapacitor(ThermalCapacitor * c) {
290 capacitors.push_back(c);
291 entities.push_back(c);
292 }
293 void ThermalModel::addResistor(ThermalResistor * r) {
294 resistors.push_back(r);
295 entities.push_back(r);
296 }
297
298 double ThermalModel::getTemp() const {
299 // Just pick the highest temperature
300 double temp = 0;
301 for (auto & n : eq_nodes)
302 temp = std::max(temp, n->temp);
303 return temp;
304 }