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