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