Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
uvahotspot
GitHub Repository: uvahotspot/HotSpot
Path: blob/master/hotspot.c
612 views
1
/*
2
* This is a trace-level thermal simulator. It reads power values
3
* from an input trace file and outputs the corresponding instantaneous
4
* temperature values to an output trace file. It also outputs the steady
5
* state temperature values to stdout.
6
*/
7
#include <stdio.h>
8
#include <stdlib.h>
9
#include <assert.h>
10
#include <string.h>
11
#include <ctype.h>
12
#include <math.h>
13
14
#include "flp.h"
15
#include "package.h"
16
#include "temperature.h"
17
#include "temperature_block.h"
18
#include "temperature_grid.h"
19
#include "util.h"
20
#include "hotspot.h"
21
#include "microchannel.h"
22
#include "materials.h"
23
24
// My stuff
25
#define PRINT_GRID_TRANSIENT 1
26
27
/* HotSpot thermal model is offered in two flavours - the block
28
* version and the grid version. The block model models temperature
29
* per functional block of the floorplan while the grid model
30
* chops the chip up into a matrix of grid cells and models the
31
* temperature of each cell. It is also capable of modeling a
32
* 3-d chip with multiple floorplans stacked on top of each
33
* other. The choice of which model to choose is done through
34
* a command line or configuration file parameter model_type.
35
* "-model_type block" chooses the block model while "-model_type grid"
36
* chooses the grid model.
37
*/
38
39
/* Guidelines for choosing the block or the grid model */
40
41
/**************************************************************************/
42
/* HotSpot contains two methods for solving temperatures: */
43
/* 1) Block Model -- the same as HotSpot 2.0 */
44
/* 2) Grid Model -- the die is divided into regular grid cells */
45
/**************************************************************************/
46
/* How the grid model works: */
47
/* The grid model first reads in floorplan and maps block-based power */
48
/* to each grid cell, then solves the temperatures for all the grid cells,*/
49
/* finally, converts the resulting grid temperatures back to block-based */
50
/* temperatures. */
51
/**************************************************************************/
52
/* The grid model is useful when */
53
/* 1) More detailed temperature distribution inside a functional unit */
54
/* is desired. */
55
/* 2) Too many functional units are included in the floorplan, resulting */
56
/* in extremely long computation time if using the Block Model */
57
/* 3) If temperature information is desired for many tiny units, */
58
/* such as individual register file entry. */
59
/**************************************************************************/
60
/* Comparisons between Grid Model and Block Model: */
61
/* In general, the grid model is more accurate, because it can deal */
62
/* with various floorplans and it provides temperature gradient across */
63
/* each functional unit. The block model models essentially the center */
64
/* temperature of each functional unit. But the block model is typically */
65
/* faster because there are less nodes to solve. */
66
/* Therefore, unless it is the case where the grid model is */
67
/* definitely needed, we suggest using the block model for computation */
68
/* efficiency. */
69
/**************************************************************************/
70
71
void usage(int argc, char **argv)
72
{
73
fprintf(stdout, "Usage: %s -f <file> -p <file> [-o <file>] [-c <file>] [-d <file>] [options]\n", argv[0]);
74
fprintf(stdout, "A thermal simulator that reads power trace from a file and outputs temperatures.\n");
75
fprintf(stdout, "Options:(may be specified in any order, within \"[]\" means optional)\n");
76
fprintf(stdout, " -f <file>\tfloorplan input file (e.g. ev6.flp) - overridden by the\n");
77
fprintf(stdout, " \tlayer configuration file (e.g. layer.lcf) when the\n");
78
fprintf(stdout, " \tlatter is specified\n");
79
fprintf(stdout, " -p <file>\tpower trace input file (e.g. gcc.ptrace)\n");
80
fprintf(stdout, " [-o <file>]\ttransient temperature trace output file - if not provided, only\n");
81
fprintf(stdout, " \tsteady state temperatures are output to stdout\n");
82
fprintf(stdout, " [-c <file>]\tinput configuration parameters from file (e.g. hotspot.config)\n");
83
fprintf(stdout, " [-d <file>]\toutput configuration parameters to file\n");
84
fprintf(stdout, " [options]\tzero or more options of the form \"-<name> <value>\",\n");
85
fprintf(stdout, " \toverride the options from config file. e.g. \"-model_type block\" selects\n");
86
fprintf(stdout, " \tthe block model while \"-model_type grid\" selects the grid model\n");
87
fprintf(stdout, " [-detailed_3D <on/off]>\tHeterogeneous R-C assignments for specified layers. Requires a .lcf file to be specified\n"); //BU_3D: added detailed_3D option
88
}
89
90
/*
91
* parse a table of name-value string pairs and add the configuration
92
* parameters to 'config'
93
*/
94
void global_config_from_strs(global_config_t *config, str_pair *table, int size)
95
{
96
int idx;
97
if ((idx = get_str_index(table, size, "f")) >= 0) {
98
if(sscanf(table[idx].value, "%s", config->flp_file) != 1)
99
fatal("invalid format for configuration parameter flp_file\n");
100
} else {
101
// If an LCF file is specified, an FLP file is not required
102
strcpy(config->flp_file, NULLFILE);
103
}
104
if ((idx = get_str_index(table, size, "p")) >= 0) {
105
if(sscanf(table[idx].value, "%s", config->p_infile) != 1)
106
fatal("invalid format for configuration parameter p_infile\n");
107
} else {
108
fatal("required parameter p_infile missing. check usage\n");
109
}
110
if ((idx = get_str_index(table, size, "o")) >= 0) {
111
if(sscanf(table[idx].value, "%s", config->t_outfile) != 1)
112
fatal("invalid format for configuration parameter t_outfile\n");
113
} else {
114
strcpy(config->t_outfile, NULLFILE);
115
}
116
if ((idx = get_str_index(table, size, "c")) >= 0) {
117
if(sscanf(table[idx].value, "%s", config->config) != 1)
118
fatal("invalid format for configuration parameter config\n");
119
} else {
120
strcpy(config->config, NULLFILE);
121
}
122
if ((idx = get_str_index(table, size, "d")) >= 0) {
123
if(sscanf(table[idx].value, "%s", config->dump_config) != 1)
124
fatal("invalid format for configuration parameter dump_config\n");
125
} else {
126
strcpy(config->dump_config, NULLFILE);
127
}
128
if ((idx = get_str_index(table, size, "detailed_3D")) >= 0) {
129
if(sscanf(table[idx].value, "%s", config->detailed_3D) != 1)
130
fatal("invalid format for configuration parameter lc\n");
131
} else {
132
strcpy(config->detailed_3D, "off");
133
}
134
if ((idx = get_str_index(table, size, "use_microchannels")) >= 0) {
135
if(sscanf(table[idx].value, "%d", &config->use_microchannels) != 1)
136
fatal("invalid format for configuration parameter use_microchannels\n");
137
} else {
138
config->use_microchannels = 0;
139
}
140
if ((idx = get_str_index(table, size, "materials_file")) >= 0) {
141
if(sscanf(table[idx].value, "%s", config->materials_file) != 1)
142
fatal("invalid format for configuration parameter materials_file\n");
143
} else {
144
strcpy(config->materials_file, NULLFILE);
145
}
146
}
147
148
/*
149
* convert config into a table of name-value pairs. returns the no.
150
* of parameters converted
151
*/
152
int global_config_to_strs(global_config_t *config, str_pair *table, int max_entries)
153
{
154
if (max_entries < 8)
155
fatal("not enough entries in table\n");
156
157
sprintf(table[0].name, "f");
158
sprintf(table[1].name, "p");
159
sprintf(table[2].name, "o");
160
sprintf(table[3].name, "c");
161
sprintf(table[4].name, "d");
162
sprintf(table[5].name, "detailed_3D");
163
sprintf(table[6].name, "use_microchannels");
164
sprintf(table[7].name, "materials_file");
165
166
sprintf(table[0].value, "%s", config->flp_file);
167
sprintf(table[1].value, "%s", config->p_infile);
168
sprintf(table[2].value, "%s", config->t_outfile);
169
sprintf(table[3].value, "%s", config->config);
170
sprintf(table[4].value, "%s", config->dump_config);
171
sprintf(table[5].value, "%s", config->detailed_3D);
172
sprintf(table[6].value, "%d", config->use_microchannels);
173
sprintf(table[7].value, "%s", config->materials_file);
174
175
return 8;
176
}
177
178
/*
179
* read a single line of trace file containing names
180
* of functional blocks
181
*/
182
int read_names(FILE *fp, char **names)
183
{
184
char line[LINE_SIZE], temp[LINE_SIZE], *src;
185
int i;
186
187
/* skip empty lines */
188
do {
189
/* read the entire line */
190
fgets(line, LINE_SIZE, fp);
191
if (feof(fp))
192
fatal("not enough names in trace file\n");
193
strcpy(temp, line);
194
src = strtok(temp, " \r\t\n");
195
} while (!src);
196
197
/* new line not read yet */
198
if(line[strlen(line)-1] != '\n')
199
fatal("line too long\n");
200
201
/* chop the names from the line read */
202
for(i=0,src=line; *src && i < MAX_UNITS; i++) {
203
if(!sscanf(src, "%s", names[i]))
204
fatal("invalid format of names\n");
205
src += strlen(names[i]);
206
while (isspace((int)*src))
207
src++;
208
}
209
if(*src && i == MAX_UNITS)
210
fatal("no. of units exceeded limit\n");
211
212
return i;
213
}
214
215
/* read a single line of power trace numbers */
216
int read_vals(FILE *fp, double *vals)
217
{
218
char line[LINE_SIZE], temp[LINE_SIZE], *src;
219
int i;
220
221
/* skip empty lines */
222
do {
223
/* read the entire line */
224
fgets(line, LINE_SIZE, fp);
225
if (feof(fp))
226
return 0;
227
strcpy(temp, line);
228
src = strtok(temp, " \r\t\n");
229
} while (!src);
230
231
/* new line not read yet */
232
if(line[strlen(line)-1] != '\n')
233
fatal("line too long\n");
234
235
/* chop the power values from the line read */
236
for(i=0,src=line; *src && i < MAX_UNITS; i++) {
237
if(!sscanf(src, "%s", temp) || !sscanf(src, "%lf", &vals[i]))
238
fatal("invalid format of values\n");
239
src += strlen(temp);
240
while (isspace((int)*src))
241
src++;
242
}
243
if(*src && i == MAX_UNITS)
244
fatal("no. of entries exceeded limit\n");
245
246
return i;
247
}
248
249
/* write a single line of functional unit names */
250
void write_names(FILE *fp, char **names, int size)
251
{
252
int i;
253
for(i=0; i < size-1; i++)
254
fprintf(fp, "%s\t", names[i]);
255
fprintf(fp, "%s\n", names[i]);
256
}
257
258
/* write a single line of temperature trace(in degree C) */
259
void write_vals(FILE *fp, double *vals, int size)
260
{
261
int i;
262
for(i=0; i < size-1; i++)
263
fprintf(fp, "%.2f\t", vals[i]);
264
fprintf(fp, "%.2f\n", vals[i]);
265
}
266
267
char **alloc_names(int nr, int nc)
268
{
269
int i;
270
char **m;
271
272
m = (char **) calloc (nr, sizeof(char *));
273
assert(m != NULL);
274
m[0] = (char *) calloc (nr * nc, sizeof(char));
275
assert(m[0] != NULL);
276
277
for (i = 1; i < nr; i++)
278
m[i] = m[0] + nc * i;
279
280
return m;
281
}
282
283
void free_names(char **m)
284
{
285
free(m[0]);
286
free(m);
287
}
288
289
void print_dashed_line(int length) {
290
int i;
291
for(i = 0; i < length; i++)
292
printf("-");
293
printf("\n");
294
}
295
296
#if VERBOSE>1
297
// TODO: Support summary for modeling secondary paths and for non-3D simulations
298
void print_simulation_summary(thermal_config_t thermal_config, RC_model_t *model) {
299
// This is currently only supported for 3D simulations
300
if(model->type != GRID_MODEL)
301
return;
302
303
grid_model_t *grid_model = model->grid;
304
int i;
305
int nl = grid_model->n_layers;
306
int hsidx = nl - DEFAULT_PACK_LAYERS + LAYER_SINK;
307
int spidx = nl - DEFAULT_PACK_LAYERS + LAYER_SP;
308
int intidx = LAYER_INT; // if lcf is not specified
309
int silidx = LAYER_SI; // if lcf is not specified
310
311
printf("\n\nSimulation Summary:\n");
312
print_dashed_line(25);
313
printf("Ambient at %.2f K\n", thermal_config.ambient);
314
print_dashed_line(25);
315
316
for(i = grid_model->n_layers - 1; i >= 0; i--) {
317
if(i == hsidx)
318
printf("Heat Sink : %.2f mm\n", grid_model->layers[i].thickness * 1e3);
319
else if(i == spidx)
320
printf("Heat Spreader : %.2f mm\n", grid_model->layers[i].thickness * 1e3);
321
else if(i == intidx && !grid_model->has_lcf)
322
printf("TIM : %.2f um\n", grid_model->layers[i].thickness * 1e6);
323
else if(i == silidx && !grid_model->has_lcf)
324
printf(" Chip : %.2f um\n", grid_model->layers[i].thickness * 1e6);
325
else if(grid_model->has_lcf)
326
printf("Layer %d : %.2f um\n", grid_model->layers[i].no, grid_model->layers[i].thickness * 1e6);
327
else
328
fatal("Unexpected error in print_simulation_summary\n");
329
330
printf(" conductivity = %lf W/(m-K)\n", grid_model->layers[i].k);
331
printf(" vol. heat capacity = %lf J/(m^3-K)\n", grid_model->layers[i].sp);
332
333
if(grid_model->layers[i].has_power)
334
printf(" dissipates power\n");
335
336
if(grid_model->layers[i].is_microchannel)
337
printf(" microfluidic cooling layer\n");
338
339
print_dashed_line(25);
340
}
341
printf("\n\n");
342
}
343
#endif
344
345
/*
346
* main function - reads instantaneous power values (in W) from a trace
347
* file (e.g. "gcc.ptrace") and outputs instantaneous temperature values (in K) to
348
* a trace file("gcc.ttrace"). also outputs steady state temperature values
349
* (including those of the internal nodes of the model) onto stdout. the
350
* trace files are 2-d matrices with each column representing a functional
351
* functional block and each row representing a time unit(sampling_intvl).
352
* columns are tab-separated and each row is a separate line. the first
353
* line contains the names of the functional blocks. the order in which
354
* the columns are specified doesn't have to match that of the floorplan
355
* file.
356
*/
357
int main(int argc, char **argv)
358
{
359
int i, j, idx, base = 0, count = 0, n = 0;
360
int num, size, lines = 0, do_transient = TRUE;
361
char **names;
362
double *vals;
363
/* trace file pointers */
364
FILE *pin, *tout = NULL;
365
/* floorplan */
366
flp_t *flp;
367
/* hotspot temperature model */
368
RC_model_t *model;
369
/* instantaneous temperature and power values */
370
double *temp = NULL, *power;
371
double total_power = 0.0;
372
373
/* steady state temperature and power values */
374
double *overall_power, *steady_temp;
375
/* thermal model configuration parameters */
376
thermal_config_t thermal_config;
377
/* default microchannel parameters */
378
microchannel_config_t *microchannel_config = malloc(sizeof(microchannel_config_t));
379
/* global configuration parameters */
380
global_config_t global_config;
381
/* table to hold options and configuration */
382
str_pair table[MAX_ENTRIES];
383
/* material properties */
384
materials_list_t materials_list;
385
386
/* variables for natural convection iterations */
387
int natural = 0;
388
double avg_sink_temp = 0;
389
int natural_convergence = 0;
390
double r_convec_old;
391
392
/*BU_3D: variable for heterogenous R-C model */
393
int do_detailed_3D = FALSE; //BU_3D: do_detailed_3D, false by default
394
int use_microchannels = FALSE;
395
if (!(argc >= 5 && argc % 2)) {
396
usage(argc, argv);
397
return 1;
398
}
399
400
printf("Parsing input files...\n");
401
size = parse_cmdline(table, MAX_ENTRIES, argc, argv);
402
global_config_from_strs(&global_config, table, size);
403
404
/* no transient simulation, only steady state */
405
if(!strcmp(global_config.t_outfile, NULLFILE))
406
do_transient = FALSE;
407
408
/* read configuration file */
409
if (strcmp(global_config.config, NULLFILE))
410
size += read_str_pairs(&table[size], MAX_ENTRIES, global_config.config);
411
412
/* earlier entries override later ones. so, command line options
413
* have priority over config file
414
*/
415
size = str_pairs_remove_duplicates(table, size);
416
417
/* BU_3D: check if heterogenous R-C modeling is on */
418
if(!strcmp(global_config.detailed_3D, "on")){
419
do_detailed_3D = TRUE;
420
}
421
else if(strcmp(global_config.detailed_3D, "off")){
422
//fatal("detailed_3D parameter should be either \'on\' or \'off\'\n");
423
do_detailed_3D = FALSE;
424
}//end->BU_3D
425
426
// fill in material properties
427
default_materials(&materials_list);
428
if(strncmp(global_config.materials_file, NULLFILE, STR_SIZE)) {
429
materials_add_from_file(&materials_list, global_config.materials_file);
430
}
431
432
/* get defaults */
433
thermal_config = default_thermal_config();
434
/* modify according to command line / config file */
435
thermal_config_add_from_strs(&thermal_config, &materials_list, table, size);
436
437
use_microchannels = global_config.use_microchannels;
438
if(use_microchannels) {
439
/* default microchannel config */
440
*microchannel_config = default_microchannel_config();
441
442
/* modify according to command line config file */
443
microchannel_config_add_from_strs(microchannel_config, &materials_list, table, size);
444
}
445
else {
446
microchannel_config = NULL;
447
}
448
449
/* if package model is used, run package model */
450
if (((idx = get_str_index(table, size, "package_model_used")) >= 0) && !(table[idx].value==0)) {
451
if (thermal_config.package_model_used) {
452
avg_sink_temp = thermal_config.ambient + SMALL_FOR_CONVEC;
453
natural = package_model(&thermal_config, table, size, avg_sink_temp);
454
if (thermal_config.r_convec<R_CONVEC_LOW || thermal_config.r_convec>R_CONVEC_HIGH)
455
printf("Warning: Heatsink convection resistance is not realistic, double-check your package settings...\n");
456
}
457
}
458
459
/* dump configuration if specified */
460
if (strcmp(global_config.dump_config, NULLFILE)) {
461
size = global_config_to_strs(&global_config, table, MAX_ENTRIES);
462
size += thermal_config_to_strs(&thermal_config, &table[size], MAX_ENTRIES-size);
463
if(use_microchannels)
464
size += microchannel_config_to_strs(microchannel_config, &table[size], MAX_ENTRIES-size);
465
/* prefix the name of the variable with a '-' */
466
dump_str_pairs(table, size, global_config.dump_config, "-");
467
}
468
469
/* initialization: the flp_file global configuration
470
* parameter is overridden by the layer configuration
471
* file in the grid model when the latter is specified.
472
*/
473
if(strcmp(thermal_config.grid_layer_file, NULLFILE)) {
474
flp = NULL;
475
476
if(strcmp(global_config.flp_file, NULLFILE)) {
477
fprintf(stderr, "Warning: Layer Configuration File %s specified. Overriding floorplan file %s\n", thermal_config.grid_layer_file, global_config.flp_file);
478
}
479
}
480
else if(strcmp(global_config.flp_file, NULLFILE)) {
481
flp = read_flp(global_config.flp_file, FALSE, FALSE);
482
}
483
else {
484
fatal("Either LCF or FLP file must be specified\n");
485
}
486
487
//BU_3D: added do_detailed_3D to alloc_RC_model. Detailed 3D modeling can only be used with grid-level modeling.
488
/* allocate and initialize the RC model */
489
model = alloc_RC_model(&thermal_config, flp, microchannel_config, &materials_list, do_detailed_3D, use_microchannels);
490
491
// Do some error checking on combination of inputs
492
if (model->type != GRID_MODEL && do_detailed_3D)
493
fatal("-do_detailed_3D can only be used with -model_type grid\n"); //end->BU_3D
494
if (model->type == GRID_MODEL && !model->grid->has_lcf && do_detailed_3D)
495
fatal("-do_detailed_3D can only be used in 3D mode (if a grid_layer_file is specified)\n");
496
if (use_microchannels && (model->type != GRID_MODEL || !do_detailed_3D))
497
fatal("-use_microchannels requires -model_type grid and do_detailed_3D on options\n");
498
if(model->type != GRID_MODEL && strcmp(model->config->grid_steady_file, NULLFILE)) {
499
warning("Ignoring -grid_steady_file because grid model is not being used\n");
500
strcpy(model->config->grid_steady_file, NULLFILE);
501
}
502
if(model->type != GRID_MODEL && strcmp(model->config->grid_transient_file, NULLFILE)) {
503
warning("Ignoring -grid_transient_file because grid model is not being used\n");
504
strcpy(model->config->grid_transient_file, NULLFILE);
505
}
506
507
#if VERBOSE > 1
508
print_simulation_summary(thermal_config, model);
509
#endif
510
511
printf("Creating thermal circuit...\n");
512
populate_R_model(model, flp);
513
514
if (do_transient)
515
populate_C_model(model, flp);
516
517
#if VERBOSE > 2
518
debug_print_model(model);
519
#endif
520
521
/* allocate the temp and power arrays */
522
/* using hotspot_vector to internally allocate any extra nodes needed */
523
if (do_transient)
524
temp = hotspot_vector(model);
525
power = hotspot_vector(model);
526
steady_temp = hotspot_vector(model);
527
overall_power = hotspot_vector(model);
528
529
/* set up initial instantaneous temperatures */
530
if (do_transient && strcmp(model->config->init_file, NULLFILE)) {
531
if (!model->config->dtm_used) /* initial T = steady T for no DTM */
532
read_temp(model, temp, model->config->init_file, FALSE);
533
else /* initial T = clipped steady T with DTM */
534
read_temp(model, temp, model->config->init_file, TRUE);
535
} else if (do_transient) /* no input file - use init_temp as the common temperature */
536
set_temp(model, temp, model->config->init_temp);
537
538
539
/* n is the number of functional blocks in the block model
540
* while it is the sum total of the number of functional blocks
541
* of all the floorplans in the power dissipating layers of the
542
* grid model.
543
*/
544
if (model->type == BLOCK_MODEL)
545
n = model->block->flp->n_units;
546
else if (model->type == GRID_MODEL) {
547
for(i=0; i < model->grid->n_layers; i++)
548
if (model->grid->layers[i].has_power)
549
n += model->grid->layers[i].flp->n_units;
550
} else
551
fatal("unknown model type\n");
552
553
if(!(pin = fopen(global_config.p_infile, "r")))
554
fatal("unable to open power trace input file\n");
555
if(do_transient && !(tout = fopen(global_config.t_outfile, "w")))
556
fatal("unable to open temperature trace file for output\n");
557
558
/* names of functional units */
559
names = alloc_names(MAX_UNITS, STR_SIZE);
560
if(read_names(pin, names) != n)
561
fatal("no. of units in floorplan and trace file differ\n");
562
563
/* header line of temperature trace */
564
if (do_transient)
565
write_names(tout, names, n);
566
567
/* read the instantaneous power trace */
568
vals = dvector(MAX_UNITS);
569
while ((num=read_vals(pin, vals)) != 0) {
570
if(num != n)
571
fatal("invalid trace file format\n");
572
573
/* permute the power numbers according to the floorplan order */
574
if (model->type == BLOCK_MODEL)
575
for(i=0; i < n; i++)
576
power[get_blk_index(flp, names[i])] = vals[i];
577
else
578
for(i=0, base=0, count=0; i < model->grid->n_layers; i++) {
579
if(model->grid->layers[i].has_power) {
580
for(j=0; j < model->grid->layers[i].flp->n_units; j++) {
581
idx = get_blk_index(model->grid->layers[i].flp, names[count+j]);
582
power[base+idx] = vals[count+j];
583
}
584
count += model->grid->layers[i].flp->n_units;
585
}
586
base += model->grid->layers[i].flp->n_units;
587
}
588
589
/* compute temperature */
590
if (do_transient) {
591
/* if natural convection is considered, update transient convection resistance first */
592
if (natural) {
593
avg_sink_temp = calc_sink_temp(model, temp);
594
natural = package_model(model->config, table, size, avg_sink_temp);
595
populate_R_model(model, flp);
596
}
597
598
printf("Computing temperatures for t = %e...\n", lines*model->config->sampling_intvl);
599
600
/* for the grid model, only the first call to compute_temp
601
* passes a non-null 'temp' array. if 'temp' is NULL,
602
* compute_temp remembers it from the last non-null call.
603
* this is used to maintain the internal grid temperatures
604
* across multiple calls of compute_temp
605
*/
606
if (model->type == BLOCK_MODEL || lines == 0)
607
compute_temp(model, power, temp, model->config->sampling_intvl);
608
else
609
compute_temp(model, power, NULL, model->config->sampling_intvl);
610
611
612
// Print grid transient temperatures to file if one has been specified
613
if(model->type == GRID_MODEL && strcmp(model->config->grid_transient_file, NULLFILE)) {
614
dump_transient_temp_grid(model->grid, lines, model->config->sampling_intvl, model->config->grid_transient_file);
615
}
616
/* permute back to the trace file order */
617
if (model->type == BLOCK_MODEL)
618
for(i=0; i < n; i++)
619
vals[i] = temp[get_blk_index(flp, names[i])];
620
else
621
for(i=0, base=0, count=0; i < model->grid->n_layers; i++) {
622
if(model->grid->layers[i].has_power) {
623
for(j=0; j < model->grid->layers[i].flp->n_units; j++) {
624
idx = get_blk_index(model->grid->layers[i].flp, names[count+j]);
625
vals[count+j] = temp[base+idx];
626
}
627
count += model->grid->layers[i].flp->n_units;
628
}
629
base += model->grid->layers[i].flp->n_units;
630
}
631
/* output instantaneous temperature trace */
632
write_vals(tout, vals, n);
633
}
634
635
/* for computing average */
636
if (model->type == BLOCK_MODEL)
637
for(i=0; i < n; i++)
638
overall_power[i] += power[i];
639
else
640
for(i=0, base=0; i < model->grid->n_layers; i++) {
641
if(model->grid->layers[i].has_power)
642
for(j=0; j < model->grid->layers[i].flp->n_units; j++)
643
overall_power[base+j] += power[base+j];
644
base += model->grid->layers[i].flp->n_units;
645
}
646
647
lines++;
648
}
649
if(!lines)
650
fatal("no power numbers in trace file\n");
651
652
/* for computing average */
653
if (model->type == BLOCK_MODEL)
654
for(i=0; i < n; i++) {
655
overall_power[i] /= lines;
656
total_power += overall_power[i];
657
}
658
else
659
for(i=0, base=0; i < model->grid->n_layers; i++) {
660
if(model->grid->layers[i].has_power)
661
for(j=0; j < model->grid->layers[i].flp->n_units; j++) {
662
overall_power[base+j] /= lines;
663
total_power += overall_power[base+j];
664
}
665
base += model->grid->layers[i].flp->n_units;
666
}
667
/* natural convection r_convec iteration, for steady-state only */
668
natural_convergence = 0;
669
if (natural) { /* natural convection is used */
670
while (!natural_convergence) {
671
r_convec_old = model->config->r_convec;
672
/* steady state temperature */
673
steady_state_temp(model, overall_power, steady_temp);
674
avg_sink_temp = calc_sink_temp(model, steady_temp) + SMALL_FOR_CONVEC;
675
natural = package_model(model->config, table, size, avg_sink_temp);
676
populate_R_model(model, flp);
677
if (avg_sink_temp > MAX_SINK_TEMP)
678
fatal("too high power for a natural convection package -- possible thermal runaway\n");
679
if (fabs(model->config->r_convec-r_convec_old)<NATURAL_CONVEC_TOL)
680
natural_convergence = 1;
681
}
682
} else {/* natural convection is not used, no need for iterations */
683
fprintf(stderr, "Computing steady-state temperatures...\n");
684
steady_state_temp(model, overall_power, steady_temp);
685
}
686
687
/* dump steady state temperatures on to file if needed */
688
if (strcmp(model->config->steady_file, NULLFILE))
689
dump_temp(model, steady_temp, model->config->steady_file);
690
/* for the grid model, optionally dump the most recent
691
* steady state temperatures of the grid cells
692
*/
693
if (model->type == GRID_MODEL &&
694
strcmp(model->config->grid_steady_file, NULLFILE))
695
dump_steady_temp_grid(model->grid, model->config->grid_steady_file);
696
697
698
#if VERBOSE > 2
699
if (model->type == BLOCK_MODEL) {
700
if (do_transient) {
701
fprintf(stdout, "printing temp...\n");
702
dump_dvector(temp, model->block->n_nodes);
703
}
704
fprintf(stdout, "printing steady_temp...\n");
705
dump_dvector(steady_temp, model->block->n_nodes);
706
} else {
707
if (do_transient) {
708
fprintf(stdout, "printing temp...\n");
709
dump_dvector(temp, model->grid->total_n_blocks + EXTRA);
710
}
711
fprintf(stdout, "printing steady_temp...\n");
712
dump_dvector(steady_temp, model->grid->total_n_blocks + EXTRA);
713
}
714
#endif
715
716
/* cleanup */
717
fclose(pin);
718
if (do_transient)
719
fclose(tout);
720
if(!model->grid->has_lcf)
721
free_flp(flp, FALSE, FALSE);
722
delete_RC_model(model);
723
if (do_transient)
724
free_dvector(temp);
725
free_materials(&materials_list);
726
free_microchannel(microchannel_config);
727
free_dvector(power);
728
free_dvector(steady_temp);
729
free_dvector(overall_power);
730
free_names(names);
731
free_dvector(vals);
732
733
printf("Simulation complete.\n");
734
return 0;
735
}
736
737