thermal_model.cc revision 11420:b48c0ba4f524
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} 320