Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
uvahotspot
GitHub Repository: uvahotspot/HotSpot
Path: blob/master/temperature_block.c
612 views
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <string.h>
4
#ifdef _MSC_VER
5
#define strcasecmp _stricmp
6
#define strncasecmp _strnicmp
7
#else
8
#include <strings.h>
9
#endif
10
11
#include "temperature_block.h"
12
#include "flp.h"
13
#include "util.h"
14
15
/*
16
* allocate memory for the matrices. placeholder can be an empty
17
* floorplan frame with only the names of the functional units
18
*/
19
block_model_t *alloc_block_model(thermal_config_t *config, flp_t *placeholder)
20
{
21
/* shortcuts */
22
int n = placeholder->n_units;
23
int m = NL*n+EXTRA;
24
25
block_model_t *model = (block_model_t *) calloc (1, sizeof(block_model_t));
26
if (!model)
27
fatal("memory allocation error\n");
28
model->config = *config;
29
model->n_units = model->base_n_units = n;
30
model->n_nodes = m;
31
32
model->border = imatrix(n, 4);
33
model->len = dmatrix(n, n); /* len[i][j] = length of shared edge bet. i & j */
34
model->g = dmatrix(m, m); /* g[i][j] = conductance bet. nodes i & j */
35
model->gx = dvector(n); /* lumped conductances in x direction */
36
model->gy = dvector(n); /* lumped conductances in y direction */
37
model->gx_int = dvector(n); /* lateral conductances in the interface layer */
38
model->gy_int = dvector(n);
39
model->gx_sp = dvector(n); /* lateral conductances in the spreader layer */
40
model->gy_sp = dvector(n);
41
model->gx_hs = dvector(n); /* lateral conductances in the heatsink layer */
42
model->gy_hs = dvector(n);
43
/* vertical conductances to ambient */
44
model->g_amb = dvector(n+EXTRA);
45
model->t_vector = dvector(m);/* scratch pad */
46
model->p = ivector(m); /* permutation vector for b's LUP decomposition */
47
48
model->a = dvector(m); /* vertical Cs - diagonal matrix stored as a 1-d vector */
49
model->inva = dvector(m); /* inverse of the above */
50
/* B, C and LU are (NL*n+EXTRA)x(NL*n+EXTRA) matrices */
51
model->b = dmatrix(m, m);
52
model->c = dmatrix(m, m);
53
model->lu = dmatrix(m, m);
54
55
model->flp = placeholder;
56
return model;
57
}
58
59
/* creates matrices B and invB: BT = Power in the steady state.
60
* NOTE: EXTRA nodes: 4 heat spreader peripheral nodes, 4 heat
61
* sink inner peripheral nodes, 4 heat sink outer peripheral
62
* nodes(north, south, east and west) and 1 ambient node.
63
*/
64
void populate_R_model_block(block_model_t *model, flp_t *flp)
65
{
66
/* shortcuts */
67
double **b = model->b;
68
double *gx = model->gx, *gy = model->gy;
69
double *gx_int = model->gx_int, *gy_int = model->gy_int;
70
double *gx_sp = model->gx_sp, *gy_sp = model->gy_sp;
71
double *gx_hs = model->gx_hs, *gy_hs = model->gy_hs;
72
double *g_amb = model->g_amb;
73
double **len = model->len, **g = model->g, **lu = model->lu;
74
int **border = model->border;
75
int *p = model->p;
76
double t_chip = model->config.t_chip;
77
double r_convec = model->config.r_convec;
78
double s_sink = model->config.s_sink;
79
double t_sink = model->config.t_sink;
80
double s_spreader = model->config.s_spreader;
81
double t_spreader = model->config.t_spreader;
82
double t_interface = model->config.t_interface;
83
double k_chip = model->config.k_chip;
84
double k_sink = model->config.k_sink;
85
double k_spreader = model->config.k_spreader;
86
double k_interface = model->config.k_interface;
87
88
int i, j, n = flp->n_units;
89
double gn_sp=0, gs_sp=0, ge_sp=0, gw_sp=0;
90
double gn_hs=0, gs_hs=0, ge_hs=0, gw_hs=0;
91
double r_amb;
92
93
double w_chip = get_total_width (flp); /* x-axis */
94
double l_chip = get_total_height (flp); /* y-axis */
95
96
/* sanity check on floorplan sizes */
97
if (w_chip > s_sink || l_chip > s_sink ||
98
w_chip > s_spreader || l_chip > s_spreader) {
99
print_flp(flp, FALSE);
100
print_flp_fig(flp);
101
fatal("inordinate floorplan size!\n");
102
}
103
if(model->flp != flp || model->n_units != flp->n_units ||
104
model->n_nodes != NL * flp->n_units + EXTRA)
105
fatal("mismatch between the floorplan and the thermal model\n");
106
107
/* gx's and gy's of blocks */
108
for (i = 0; i < n; i++) {
109
/* at the silicon layer */
110
if (model->config.block_omit_lateral) {
111
gx[i] = gy[i] = 0;
112
}
113
else {
114
gx[i] = 1.0/getr(k_chip, flp->units[i].width / 2.0, flp->units[i].height * t_chip);
115
gy[i] = 1.0/getr(k_chip, flp->units[i].height / 2.0, flp->units[i].width * t_chip);
116
}
117
118
/* at the interface layer */
119
gx_int[i] = 1.0/getr(k_interface, flp->units[i].width / 2.0, flp->units[i].height * t_interface);
120
gy_int[i] = 1.0/getr(k_interface, flp->units[i].height / 2.0, flp->units[i].width * t_interface);
121
122
/* at the spreader layer */
123
gx_sp[i] = 1.0/getr(k_spreader, flp->units[i].width / 2.0, flp->units[i].height * t_spreader);
124
gy_sp[i] = 1.0/getr(k_spreader, flp->units[i].height / 2.0, flp->units[i].width * t_spreader);
125
126
/* at the heatsink layer */
127
gx_hs[i] = 1.0/getr(k_sink, flp->units[i].width / 2.0, flp->units[i].height * t_sink);
128
gy_hs[i] = 1.0/getr(k_sink, flp->units[i].height / 2.0, flp->units[i].width * t_sink);
129
}
130
131
/* shared lengths between blocks */
132
for (i = 0; i < n; i++)
133
for (j = i; j < n; j++)
134
len[i][j] = len[j][i] = get_shared_len(flp, i, j);
135
136
/* package R's */
137
populate_package_R(&model->pack, &model->config, w_chip, l_chip);
138
139
/* short the R's from block centers to a particular chip edge */
140
for (i = 0; i < n; i++) {
141
if (eq(flp->units[i].bottomy + flp->units[i].height, l_chip)) {
142
gn_sp += gy_sp[i];
143
gn_hs += gy_hs[i];
144
border[i][2] = 1; /* block is on northern border */
145
} else
146
border[i][2] = 0;
147
148
if (eq(flp->units[i].bottomy, 0)) {
149
gs_sp += gy_sp[i];
150
gs_hs += gy_hs[i];
151
border[i][3] = 1; /* block is on southern border */
152
} else
153
border[i][3] = 0;
154
155
if (eq(flp->units[i].leftx + flp->units[i].width, w_chip)) {
156
ge_sp += gx_sp[i];
157
ge_hs += gx_hs[i];
158
border[i][1] = 1; /* block is on eastern border */
159
} else
160
border[i][1] = 0;
161
162
if (eq(flp->units[i].leftx, 0)) {
163
gw_sp += gx_sp[i];
164
gw_hs += gx_hs[i];
165
border[i][0] = 1; /* block is on western border */
166
} else
167
border[i][0] = 0;
168
}
169
170
/* initialize g */
171
zero_dmatrix(g, NL*n+EXTRA, NL*n+EXTRA);
172
zero_dvector(g_amb, n+EXTRA);
173
174
/* overall Rs between nodes */
175
for (i = 0; i < n; i++) {
176
double area = (flp->units[i].height * flp->units[i].width);
177
/* amongst functional units in the various layers */
178
for (j = 0; j < n; j++) {
179
double part = 0, part_int = 0, part_sp = 0, part_hs = 0;
180
if (is_horiz_adj(flp, i, j)) {
181
part = gx[i] / flp->units[i].height;
182
part_int = gx_int[i] / flp->units[i].height;
183
part_sp = gx_sp[i] / flp->units[i].height;
184
part_hs = gx_hs[i] / flp->units[i].height;
185
}
186
else if (is_vert_adj(flp, i,j)) {
187
part = gy[i] / flp->units[i].width;
188
part_int = gy_int[i] / flp->units[i].width;
189
part_sp = gy_sp[i] / flp->units[i].width;
190
part_hs = gy_hs[i] / flp->units[i].width;
191
}
192
g[i][j] = part * len[i][j];
193
g[IFACE*n+i][IFACE*n+j] = part_int * len[i][j];
194
g[HSP*n+i][HSP*n+j] = part_sp * len[i][j];
195
g[HSINK*n+i][HSINK*n+j] = part_hs * len[i][j];
196
}
197
/* the 2.0 factor in the following equations is
198
* explained during the calculation of the B matrix
199
*/
200
/* vertical g's in the silicon layer */
201
g[i][IFACE*n+i]=g[IFACE*n+i][i]=2.0/getr(k_chip, t_chip, area);
202
/* vertical g's in the interface layer */
203
g[IFACE*n+i][HSP*n+i]=g[HSP*n+i][IFACE*n+i]=2.0/getr(k_interface, t_interface, area);
204
/* vertical g's in the spreader layer */
205
g[HSP*n+i][HSINK*n+i]=g[HSINK*n+i][HSP*n+i]=2.0/getr(k_spreader, t_spreader, area);
206
/* vertical g's in the heatsink core layer */
207
/* vertical R to ambient: divide r_convec proportional to area */
208
r_amb = r_convec * (s_sink * s_sink) / area;
209
g_amb[i] = 1.0 / (getr(k_sink, t_sink, area) + r_amb);
210
211
/* lateral g's from block center (spreader layer) to peripheral (n,s,e,w) spreader nodes */
212
g[HSP*n+i][NL*n+SP_N]=g[NL*n+SP_N][HSP*n+i]=2.0*border[i][2] /
213
((1.0/gy_sp[i])+model->pack.r_sp1_y*gn_sp/gy_sp[i]);
214
g[HSP*n+i][NL*n+SP_S]=g[NL*n+SP_S][HSP*n+i]=2.0*border[i][3] /
215
((1.0/gy_sp[i])+model->pack.r_sp1_y*gs_sp/gy_sp[i]);
216
g[HSP*n+i][NL*n+SP_E]=g[NL*n+SP_E][HSP*n+i]=2.0*border[i][1] /
217
((1.0/gx_sp[i])+model->pack.r_sp1_x*ge_sp/gx_sp[i]);
218
g[HSP*n+i][NL*n+SP_W]=g[NL*n+SP_W][HSP*n+i]=2.0*border[i][0] /
219
((1.0/gx_sp[i])+model->pack.r_sp1_x*gw_sp/gx_sp[i]);
220
221
/* lateral g's from block center (heatsink layer) to peripheral (n,s,e,w) heatsink nodes */
222
g[HSINK*n+i][NL*n+SINK_C_N]=g[NL*n+SINK_C_N][HSINK*n+i]=2.0*border[i][2] /
223
((1.0/gy_hs[i])+model->pack.r_hs1_y*gn_hs/gy_hs[i]);
224
g[HSINK*n+i][NL*n+SINK_C_S]=g[NL*n+SINK_C_S][HSINK*n+i]=2.0*border[i][3] /
225
((1.0/gy_hs[i])+model->pack.r_hs1_y*gs_hs/gy_hs[i]);
226
g[HSINK*n+i][NL*n+SINK_C_E]=g[NL*n+SINK_C_E][HSINK*n+i]=2.0*border[i][1] /
227
((1.0/gx_hs[i])+model->pack.r_hs1_x*ge_hs/gx_hs[i]);
228
g[HSINK*n+i][NL*n+SINK_C_W]=g[NL*n+SINK_C_W][HSINK*n+i]=2.0*border[i][0] /
229
((1.0/gx_hs[i])+model->pack.r_hs1_x*gw_hs/gx_hs[i]);
230
}
231
232
/* g's from peripheral(n,s,e,w) nodes */
233
/* vertical g's between peripheral spreader nodes and center peripheral heatsink nodes */
234
g[NL*n+SP_N][NL*n+SINK_C_N]=g[NL*n+SINK_C_N][NL*n+SP_N]=2.0/model->pack.r_sp_per_y;
235
g[NL*n+SP_S][NL*n+SINK_C_S]=g[NL*n+SINK_C_S][NL*n+SP_S]=2.0/model->pack.r_sp_per_y;
236
g[NL*n+SP_E][NL*n+SINK_C_E]=g[NL*n+SINK_C_E][NL*n+SP_E]=2.0/model->pack.r_sp_per_x;
237
g[NL*n+SP_W][NL*n+SINK_C_W]=g[NL*n+SINK_C_W][NL*n+SP_W]=2.0/model->pack.r_sp_per_x;
238
/* lateral g's between peripheral outer sink nodes and center peripheral sink nodes */
239
g[NL*n+SINK_C_N][NL*n+SINK_N]=g[NL*n+SINK_N][NL*n+SINK_C_N]=2.0/(model->pack.r_hs + model->pack.r_hs2_y);
240
g[NL*n+SINK_C_S][NL*n+SINK_S]=g[NL*n+SINK_S][NL*n+SINK_C_S]=2.0/(model->pack.r_hs + model->pack.r_hs2_y);
241
g[NL*n+SINK_C_E][NL*n+SINK_E]=g[NL*n+SINK_E][NL*n+SINK_C_E]=2.0/(model->pack.r_hs + model->pack.r_hs2_x);
242
g[NL*n+SINK_C_W][NL*n+SINK_W]=g[NL*n+SINK_W][NL*n+SINK_C_W]=2.0/(model->pack.r_hs + model->pack.r_hs2_x);
243
/* vertical g's between inner peripheral sink nodes and ambient */
244
g_amb[n+SINK_C_N] = g_amb[n+SINK_C_S] = 1.0 / (model->pack.r_hs_c_per_y+model->pack.r_amb_c_per_y);
245
g_amb[n+SINK_C_E] = g_amb[n+SINK_C_W] = 1.0 / (model->pack.r_hs_c_per_x+model->pack.r_amb_c_per_x);
246
/* vertical g's between outer peripheral sink nodes and ambient */
247
g_amb[n+SINK_N] = g_amb[n+SINK_S] = g_amb[n+SINK_E] =
248
g_amb[n+SINK_W] = 1.0 / (model->pack.r_hs_per+model->pack.r_amb_per);
249
250
/* calculate matrix B such that BT = POWER in steady state */
251
/* non-diagonal elements */
252
for (i = 0; i < NL*n+EXTRA; i++)
253
for (j = 0; j < i; j++)
254
if ((g[i][j] == 0.0) || (g[j][i] == 0.0))
255
b[i][j] = b[j][i] = 0.0;
256
else
257
/* here is why the 2.0 factor comes when calculating g[][] */
258
b[i][j] = b[j][i] = -1.0/((1.0/g[i][j])+(1.0/g[j][i]));
259
/* diagonal elements */
260
for (i = 0; i < NL*n+EXTRA; i++) {
261
/* functional blocks in the heat sink layer */
262
if (i >= HSINK*n && i < NL*n)
263
b[i][i] = g_amb[i%n];
264
/* heat sink peripheral nodes */
265
else if (i >= NL*n+SINK_C_W)
266
b[i][i] = g_amb[n+i-NL*n];
267
/* all other nodes that are not connected to the ambient */
268
else
269
b[i][i] = 0.0;
270
/* sum up the conductances */
271
for(j=0; j < NL*n+EXTRA; j++)
272
if (i != j)
273
b[i][i] -= b[i][j];
274
}
275
276
/* compute the LUP decomposition of B and store it too */
277
copy_dmatrix(lu, b, NL*n+EXTRA, NL*n+EXTRA);
278
/*
279
* B is a symmetric positive definite matrix. It is
280
* symmetric because if a node A is connected to B,
281
* then B is also connected to A with the same R value.
282
* It is positive definite because of the following
283
* informal argument from Professor Lieven Vandenberghe's
284
* lecture slides for the spring 2004-2005 EE 103 class
285
* at UCLA: http://www.ee.ucla.edu/~vandenbe/103/chol.pdf
286
* x^T*B*x = voltage^T * (B*x) = voltage^T * current
287
* = total power dissipated in the resistors > 0
288
* for x != 0.
289
*/
290
lupdcmp(lu, NL*n+EXTRA, p, 1);
291
292
/* done */
293
model->flp = flp;
294
model->r_ready = TRUE;
295
}
296
297
/* creates 2 matrices: invA, C: dT + A^-1*BT = A^-1*Power,
298
* C = A^-1 * B. note that A is a diagonal matrix (no lateral
299
* capacitances. all capacitances are to ground). also note that
300
* it is stored as a 1-d vector. so, for computing the inverse,
301
* inva[i] = 1/a[i] is just enough.
302
*/
303
void populate_C_model_block(block_model_t *model, flp_t *flp)
304
{
305
/* shortcuts */
306
double *inva = model->inva, **c = model->c;
307
double **b = model->b;
308
double *a = model->a;
309
double t_chip = model->config.t_chip;
310
double c_convec = model->config.c_convec;
311
double s_sink = model->config.s_sink;
312
double t_sink = model->config.t_sink;
313
double t_spreader = model->config.t_spreader;
314
double t_interface = model->config.t_interface;
315
double p_chip = model->config.p_chip;
316
double p_sink = model->config.p_sink;
317
double p_spreader = model->config.p_spreader;
318
double p_interface = model->config.p_interface;
319
double c_amb;
320
double w_chip, l_chip;
321
322
int i, n = flp->n_units;
323
324
if (!model->r_ready)
325
fatal("R model not ready\n");
326
if (model->flp != flp || model->n_units != flp->n_units ||
327
model->n_nodes != NL * flp->n_units + EXTRA)
328
fatal("different floorplans for R and C models!\n");
329
330
w_chip = get_total_width (flp); /* x-axis */
331
l_chip = get_total_height (flp); /* y-axis */
332
333
/* package C's */
334
populate_package_C(&model->pack, &model->config, w_chip, l_chip);
335
336
/* functional block C's */
337
for (i = 0; i < n; i++) {
338
double area = (flp->units[i].height * flp->units[i].width);
339
/* C's from functional units to ground */
340
a[i] = getcap(p_chip, t_chip, area);
341
/* C's from interface portion of the functional units to ground */
342
a[IFACE*n+i] = getcap(p_interface, t_interface, area);
343
/* C's from spreader portion of the functional units to ground */
344
a[HSP*n+i] = getcap(p_spreader, t_spreader, area);
345
/* C's from heatsink portion of the functional units to ground */
346
/* vertical C to ambient: divide c_convec proportional to area */
347
c_amb = C_FACTOR * c_convec / (s_sink * s_sink) * area;
348
a[HSINK*n+i] = getcap(p_sink, t_sink, area) + c_amb;
349
}
350
351
/* C's from peripheral(n,s,e,w) nodes */
352
/* from peripheral spreader nodes to ground */
353
a[NL*n+SP_N] = a[NL*n+SP_S] = model->pack.c_sp_per_y;
354
a[NL*n+SP_E] = a[NL*n+SP_W] = model->pack.c_sp_per_x;
355
/* from center peripheral sink nodes to ground
356
* NOTE: this treatment of capacitances (and
357
* the corresponding treatment of resistances
358
* in populate_R_model) as parallel (series)
359
* is only approximate and is done in order
360
* to avoid creating an extra layer of nodes
361
*/
362
a[NL*n+SINK_C_N] = a[NL*n+SINK_C_S] = model->pack.c_hs_c_per_y +
363
model->pack.c_amb_c_per_y;
364
a[NL*n+SINK_C_E] = a[NL*n+SINK_C_W] = model->pack.c_hs_c_per_x +
365
model->pack.c_amb_c_per_x;
366
/* from outer peripheral sink nodes to ground */
367
a[NL*n+SINK_N] = a[NL*n+SINK_S] = a[NL*n+SINK_E] = a[NL*n+SINK_W] =
368
model->pack.c_hs_per + model->pack.c_amb_per;
369
370
/* calculate A^-1 (for diagonal matrix A) such that A(dT) + BT = POWER */
371
for (i = 0; i < NL*n+EXTRA; i++)
372
inva[i] = 1.0/a[i];
373
374
/* we are always going to use the eqn dT + A^-1 * B T = A^-1 * POWER. so, store C = A^-1 * B */
375
diagmatmult(c, inva, b, NL*n+EXTRA);
376
377
/* done */
378
model->c_ready = TRUE;
379
}
380
381
/* setting package nodes' power numbers */
382
void set_internal_power_block(block_model_t *model, double *power)
383
{
384
int i;
385
zero_dvector(&power[IFACE*model->n_units], model->n_units);
386
zero_dvector(&power[HSP*model->n_units], model->n_units);
387
for(i=0; i < model->n_units + EXTRA; i++)
388
power[HSINK*model->n_units+i] = model->config.ambient * model->g_amb[i];
389
}
390
391
/* power and temp should both be alloced using hotspot_vector.
392
* 'b' is the 'thermal conductance' matrix. i.e, b * temp = power
393
* => temp = invb * power. instead of computing invb, we have
394
* stored the LUP decomposition of B in 'lu' and 'p'. Using
395
* forward and backward substitution, we can then solve the
396
* equation b * temp = power.
397
*/
398
void steady_state_temp_block(block_model_t *model, double *power, double *temp)
399
{
400
if (!model->r_ready)
401
fatal("R model not ready\n");
402
403
/* set power numbers for the virtual nodes */
404
set_internal_power_block(model, power);
405
406
/*
407
* find temperatures (spd flag is set to 1 by the same argument
408
* as mentioned in the populate_R_model_block function)
409
*/
410
lusolve(model->lu, model->n_nodes, model->p, power, temp, 1);
411
}
412
413
/* compute the slope vector dy for the transient equation
414
* dy + cy = p. useful in the transient solver
415
*/
416
void slope_fn_block(block_model_t *model, double *y, double *p, double *dy)
417
{
418
/* shortcuts */
419
int n = model->n_nodes;
420
double **c = model->c;
421
422
/* for our equation, dy = p - cy */
423
#if (MATHACCEL == MA_INTEL || MATHACCEL == MA_APPLE)
424
/* dy = p */
425
cblas_dcopy(n, p, 1, dy, 1);
426
/* dy = dy - c*y = p - c*y */
427
cblas_dgemv(CblasRowMajor, CblasNoTrans, n, n, -1, c[0],
428
n, y, 1, 1, dy, 1);
429
#elif (MATHACCEL == MA_AMD || MATHACCEL == MA_SUN)
430
/* dy = p */
431
dcopy(n, p, 1, dy, 1);
432
/* dy = dy - c*y = p - c*y */
433
dgemv('T', n, n, -1, c[0], n, y, 1, 1, dy, 1);
434
#else
435
int i;
436
double *t = dvector(n);
437
matvectmult(t, c, y, n);
438
for (i = 0; i < n; i++)
439
dy[i] = p[i]-t[i];
440
free_dvector(t);
441
#endif
442
}
443
444
/* compute_temp: solve for temperature from the equation dT + CT = inv_A * Power
445
* Given the temperature (temp) at time t, the power dissipation per cycle during the
446
* last interval (time_elapsed), find the new temperature at time t+time_elapsed.
447
* power and temp should both be alloced using hotspot_vector
448
*/
449
void compute_temp_block(block_model_t *model, double *power, double *temp, double time_elapsed)
450
{
451
double t, h, new_h;
452
453
#if VERBOSE > 1
454
unsigned int i = 0;
455
#endif
456
457
if (!model->r_ready || !model->c_ready)
458
fatal("block model not ready\n");
459
if (temp == model->t_vector)
460
fatal("output same as scratch pad\n");
461
462
/* set power numbers for the virtual nodes */
463
set_internal_power_block(model, power);
464
465
/* use the scratch pad vector to find (inv_A)*POWER */
466
diagmatvectmult(model->t_vector, model->inva, power, model->n_nodes);
467
468
/* Obtain temp at time (t+time_elapsed).
469
* Instead of getting the temperature at t+time_elapsed directly, we do it
470
* in multiple steps with the correct step size at each time
471
* provided by rk4
472
*/
473
for (t = 0, new_h = MIN_STEP; t < time_elapsed && new_h >= MIN_STEP*DELTA; t+=h) {
474
h = new_h;
475
new_h = rk4(model, temp, model->t_vector, model->n_nodes, &h,
476
/* the slope function callback is typecast accordingly */
477
temp, (slope_fn_ptr) slope_fn_block);
478
new_h = MIN(new_h, time_elapsed-t-h);
479
#if VERBOSE > 1
480
i++;
481
#endif
482
}
483
#if VERBOSE > 1
484
fprintf(stdout, "no. of rk4 calls during compute_temp: %d\n", i+1);
485
#endif
486
}
487
488
/* differs from 'dvector()' in that memory for internal nodes is also allocated */
489
double *hotspot_vector_block(block_model_t *model)
490
{
491
return dvector(model->n_nodes);
492
}
493
494
/* copy 'src' to 'dst' except for a window of 'size'
495
* elements starting at 'at'. useful in floorplan
496
* compaction
497
*/
498
void trim_hotspot_vector_block(block_model_t *model, double *dst, double *src,
499
int at, int size)
500
{
501
int i;
502
503
for (i=0; i < at && i < model->n_nodes; i++)
504
dst[i] = src[i];
505
for(i=at+size; i < model->n_nodes; i++)
506
dst[i-size] = src[i];
507
}
508
509
/* update the model's node count */
510
void resize_thermal_model_block(block_model_t *model, int n_units)
511
{
512
if (n_units > model->base_n_units)
513
fatal("resizing block model to more than the allocated space\n");
514
model->n_units = n_units;
515
model->n_nodes = NL * n_units + EXTRA;
516
/* resize the 2-d matrices whose no. of columns changes */
517
resize_dmatrix(model->len, model->n_units, model->n_units);
518
resize_dmatrix(model->g, model->n_nodes, model->n_nodes);
519
resize_dmatrix(model->b, model->n_nodes, model->n_nodes);
520
resize_dmatrix(model->c, model->n_nodes, model->n_nodes);
521
resize_dmatrix(model->lu, model->n_nodes, model->n_nodes);
522
}
523
524
/* sets the temperature of a vector 'temp' allocated using 'hotspot_vector' */
525
void set_temp_block(block_model_t *model, double *temp, double val)
526
{
527
int i;
528
for(i=0; i < model->n_nodes; i++)
529
temp[i] = val;
530
}
531
532
/* dump temperature vector alloced using 'hotspot_vector' to 'file' */
533
void dump_temp_block(block_model_t *model, double *temp, char *file)
534
{
535
flp_t *flp = model->flp;
536
int i;
537
char str[STR_SIZE];
538
FILE *fp;
539
540
if (!strcasecmp(file, "stdout"))
541
fp = stdout;
542
else if (!strcasecmp(file, "stderr"))
543
fp = stderr;
544
else
545
fp = fopen (file, "w");
546
547
if (!fp) {
548
sprintf (str,"error: %s could not be opened for writing\n", file);
549
fatal(str);
550
}
551
/* on chip temperatures */
552
for (i=0; i < flp->n_units; i++)
553
fprintf(fp, "%s\t%.2f\n", flp->units[i].name, temp[i]);
554
555
/* interface temperatures */
556
for (i=0; i < flp->n_units; i++)
557
fprintf(fp, "iface_%s\t%.2f\n", flp->units[i].name, temp[IFACE*flp->n_units+i]);
558
559
/* spreader temperatures */
560
for (i=0; i < flp->n_units; i++)
561
fprintf(fp, "hsp_%s\t%.2f\n", flp->units[i].name, temp[HSP*flp->n_units+i]);
562
563
/* heatsink temperatures */
564
for (i=0; i < flp->n_units; i++)
565
fprintf(fp, "hsink_%s\t%.2f\n", flp->units[i].name, temp[HSINK*flp->n_units+i]);
566
567
/* internal node temperatures */
568
for (i=0; i < EXTRA; i++) {
569
sprintf(str, "inode_%d", i);
570
fprintf(fp, "%s\t%.2f\n", str, temp[i+NL*flp->n_units]);
571
}
572
573
if(fp != stdout && fp != stderr)
574
fclose(fp);
575
}
576
577
void copy_temp_block(block_model_t *model, double *dst, double *src)
578
{
579
copy_dvector(dst, src, NL*model->flp->n_units+EXTRA);
580
}
581
582
/*
583
* read temperature vector alloced using 'hotspot_vector' from 'file'
584
* which was dumped using 'dump_temp'. values are clipped to thermal
585
* threshold based on 'clip'
586
*/
587
void read_temp_block(block_model_t *model, double *temp, char *file, int clip)
588
{
589
/* shortcuts */
590
flp_t *flp = model->flp;
591
double thermal_threshold = model->config.thermal_threshold;
592
double ambient = model->config.ambient;
593
594
int i, n, idx;
595
double max=0, val;
596
char *ptr, str1[LINE_SIZE], str2[LINE_SIZE];
597
char name[STR_SIZE], format[STR_SIZE];
598
FILE *fp;
599
600
if (!strcasecmp(file, "stdin"))
601
fp = stdin;
602
else
603
fp = fopen (file, "r");
604
605
if (!fp) {
606
sprintf (str1,"error: %s could not be opened for reading\n", file);
607
fatal(str1);
608
}
609
610
/* temperatures of the different layers */
611
for (n=0; n < NL; n++) {
612
switch(n)
613
{
614
case 0:
615
strcpy(format,"%s%lf");
616
break;
617
case IFACE:
618
strcpy(format,"iface_%s%lf");
619
break;
620
case HSP:
621
strcpy(format,"hsp_%s%lf");
622
break;
623
case HSINK:
624
strcpy(format,"hsink_%s%lf");
625
break;
626
default:
627
fatal("unknown layer\n");
628
break;
629
}
630
for (i=0; i < flp->n_units; i++) {
631
fgets(str1, LINE_SIZE, fp);
632
if (feof(fp))
633
fatal("not enough lines in temperature file\n");
634
strcpy(str2, str1);
635
636
/* ignore comments and empty lines */
637
ptr = strtok(str1, " \r\t\n");
638
if (!ptr || ptr[0] == '#') {
639
i--;
640
continue;
641
}
642
643
if (sscanf(str2, format, name, &val) != 2)
644
fatal("invalid temperature file format\n");
645
idx = get_blk_index(flp, name);
646
if (idx >= 0)
647
temp[idx + n*flp->n_units] = val;
648
else /* since get_blk_index calls fatal, the line below cannot be reached */
649
fatal ("unit in temperature file not found in floorplan\n");
650
651
/* find max temp on the chip */
652
if (n == 0 && temp[idx] > max)
653
max = temp[idx];
654
}
655
}
656
657
/* internal node temperatures */
658
for (i=0; i < EXTRA; i++) {
659
fgets(str1, LINE_SIZE, fp);
660
if (feof(fp))
661
fatal("not enough lines in temperature file\n");
662
strcpy(str2, str1);
663
/* ignore comments and empty lines */
664
ptr = strtok(str1, " \r\t\n");
665
if (!ptr || ptr[0] == '#') {
666
i--;
667
continue;
668
}
669
if (sscanf(str2, "%s%lf", name, &val) != 2)
670
fatal("invalid temperature file format\n");
671
sprintf(str1, "inode_%d", i);
672
if (strcasecmp(str1, name))
673
fatal("invalid temperature file format\n");
674
temp[i+NL*flp->n_units] = val;
675
}
676
677
fgets(str1, LINE_SIZE, fp);
678
if (!feof(fp))
679
fatal("too many lines in temperature file\n");
680
681
if(fp != stdin)
682
fclose(fp);
683
684
/* clipping */
685
if (clip && (max > thermal_threshold)) {
686
/* if max has to be brought down to thermal_threshold,
687
* (w.r.t the ambient) what is the scale down factor?
688
*/
689
double factor = (thermal_threshold - ambient) / (max - ambient);
690
691
/* scale down all temperature differences (from ambient) by the same factor */
692
for (i=0; i < NL*flp->n_units + EXTRA; i++)
693
temp[i] = (temp[i]-ambient)*factor + ambient;
694
}
695
}
696
697
/* dump power numbers to file */
698
void dump_power_block(block_model_t *model, double *power, char *file)
699
{
700
flp_t *flp = model->flp;
701
int i;
702
char str[STR_SIZE];
703
FILE *fp;
704
705
if (!strcasecmp(file, "stdout"))
706
fp = stdout;
707
else if (!strcasecmp(file, "stderr"))
708
fp = stderr;
709
else
710
fp = fopen (file, "w");
711
712
if (!fp) {
713
sprintf (str,"error: %s could not be opened for writing\n", file);
714
fatal(str);
715
}
716
for (i=0; i < flp->n_units; i++)
717
fprintf(fp, "%s\t%.6f\n", flp->units[i].name, power[i]);
718
if(fp != stdout && fp != stderr)
719
fclose(fp);
720
}
721
722
/*
723
* read power vector alloced using 'hotspot_vector' from 'file'
724
* which was dumped using 'dump_power'.
725
*/
726
void read_power_block (block_model_t *model, double *power, char *file)
727
{
728
flp_t *flp = model->flp;
729
int idx;
730
double val;
731
char *ptr, str1[LINE_SIZE], str2[LINE_SIZE], name[STR_SIZE];
732
FILE *fp;
733
734
if (!strcasecmp(file, "stdin"))
735
fp = stdin;
736
else
737
fp = fopen (file, "r");
738
739
if (!fp) {
740
sprintf (str1,"error: %s could not be opened for reading\n", file);
741
fatal(str1);
742
}
743
while(!feof(fp)) {
744
fgets(str1, LINE_SIZE, fp);
745
if (feof(fp))
746
break;
747
strcpy(str2, str1);
748
749
/* ignore comments and empty lines */
750
ptr = strtok(str1, " \r\t\n");
751
if (!ptr || ptr[0] == '#')
752
continue;
753
754
if (sscanf(str2, "%s%lf", name, &val) != 2)
755
fatal("invalid power file format\n");
756
idx = get_blk_index(flp, name);
757
if (idx >= 0)
758
power[idx] = val;
759
else /* since get_blk_index calls fatal, the line below cannot be reached */
760
fatal ("unit in power file not found in floorplan\n");
761
}
762
if(fp != stdin)
763
fclose(fp);
764
}
765
766
double find_max_temp_block(block_model_t *model, double *temp)
767
{
768
int i;
769
double max = 0.0;
770
for(i=0; i < model->n_units; i++) {
771
if (temp[i] < 0)
772
fatal("negative temperature!\n");
773
else if (max < temp[i])
774
max = temp[i];
775
}
776
777
return max;
778
}
779
780
double find_avg_temp_block(block_model_t *model, double *temp)
781
{
782
int i;
783
double sum = 0.0;
784
for(i=0; i < model->n_units; i++) {
785
if (temp[i] < 0)
786
fatal("negative temperature!\n");
787
else
788
sum += temp[i];
789
}
790
791
return (sum / model->n_units);
792
}
793
794
/* calculate avg sink temp for natural convection package model */
795
double calc_sink_temp_block(block_model_t *model, double *temp, thermal_config_t *config)
796
{
797
flp_t *flp = model->flp;
798
int i;
799
double sum = 0.0;
800
double width = get_total_width(flp);
801
double height = get_total_height(flp);
802
double spr_size = config->s_spreader*config->s_spreader;
803
double sink_size = config->s_sink*config->s_sink;
804
805
/* heatsink temperatures */
806
for (i=0; i < flp->n_units; i++)
807
if (temp[HSINK*flp->n_units+i] < 0)
808
fatal("negative temperature!\n");
809
else /* area-weighted average */
810
sum += temp[HSINK*flp->n_units+i]*(flp->units[i].width*flp->units[i].height);
811
812
for(i=SINK_C_W; i <= SINK_C_E; i++)
813
if (temp[i+NL*flp->n_units] < 0)
814
fatal("negative temperature!\n");
815
else
816
sum += temp[i+NL*flp->n_units]*0.25*(config->s_spreader+height)*(config->s_spreader-width);
817
818
for(i=SINK_C_N; i <= SINK_C_S; i++)
819
if (temp[i+NL*flp->n_units] < 0)
820
fatal("negative temperature!\n");
821
else
822
sum += temp[i+NL*flp->n_units]*0.25*(config->s_spreader+width)*(config->s_spreader-height);
823
824
for(i=SINK_W; i <= SINK_S; i++)
825
if (temp[i+NL*flp->n_units] < 0)
826
fatal("negative temperature!\n");
827
else
828
sum += temp[i+NL*flp->n_units]*0.25*(sink_size-spr_size);
829
830
return (sum / sink_size);
831
}
832
833
void delete_block_model(block_model_t *model)
834
{
835
free_dvector(model->a);
836
free_dvector(model->inva);
837
free_dmatrix(model->b);
838
free_dmatrix(model->c);
839
840
free_dvector(model->gx);
841
free_dvector(model->gy);
842
free_dvector(model->gx_int);
843
free_dvector(model->gy_int);
844
free_dvector(model->gx_sp);
845
free_dvector(model->gy_sp);
846
free_dvector(model->gx_hs);
847
free_dvector(model->gy_hs);
848
free_dvector(model->g_amb);
849
free_dvector(model->t_vector);
850
free_ivector(model->p);
851
852
free_dmatrix(model->len);
853
free_dmatrix(model->g);
854
free_dmatrix(model->lu);
855
856
free_imatrix(model->border);
857
858
free(model);
859
}
860
861
void debug_print_block(block_model_t *model)
862
{
863
fprintf(stdout, "printing block model information...\n");
864
fprintf(stdout, "n_nodes: %d\n", model->n_nodes);
865
fprintf(stdout, "n_units: %d\n", model->n_units);
866
fprintf(stdout, "base_n_units: %d\n", model->base_n_units);
867
fprintf(stdout, "r_ready: %d\n", model->r_ready);
868
fprintf(stdout, "c_ready: %d\n", model->c_ready);
869
870
debug_print_package_RC(&model->pack);
871
872
fprintf(stdout, "printing matrix b:\n");
873
dump_dmatrix(model->b, model->n_nodes, model->n_nodes);
874
fprintf(stdout, "printing vector a:\n");
875
dump_dvector(model->a, model->n_nodes);
876
fprintf(stdout, "printing vector inva:\n");
877
dump_dvector(model->inva, model->n_nodes);
878
fprintf(stdout, "printing matrix c:\n");
879
dump_dmatrix(model->c, model->n_nodes, model->n_nodes);
880
fprintf(stdout, "printing vector g_amb:\n");
881
dump_dvector(model->g_amb, model->n_units+EXTRA);
882
}
883
884