Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
uvahotspot
GitHub Repository: uvahotspot/HotSpot
Path: blob/master/flp.c
612 views
1
#include <stdio.h>
2
#include <string.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
#include <stdlib.h>
11
#include <math.h>
12
13
#include "flp.h"
14
#include "npe.h"
15
#include "shape.h"
16
#include "util.h"
17
#include "temperature.h"
18
#include "temperature_block.h"
19
20
/*
21
* this is the metric function used for the floorplanning.
22
* in order to enable a different metric, just change the
23
* return statement of this function to return an appropriate
24
* metric. The current metric used is a linear function of
25
* area (A), temperature (T) and wire length (W):
26
* lambdaA * A + lambdaT * T + lambdaW * W
27
* thermal model and power density are passed as parameters
28
* since temperature is used in the metric.
29
*/
30
double flp_evaluate_metric(flp_t *flp, RC_model_t *model, double *power,
31
double lambdaA, double lambdaT, double lambdaW)
32
{
33
double tmax, area, wire_length;
34
double *temp;
35
36
temp = hotspot_vector(model);
37
populate_R_model(model, flp);
38
steady_state_temp(model, power, temp);
39
tmax = find_max_temp(model, temp);
40
area = get_total_area(flp);
41
wire_length = get_wire_metric(flp);
42
free_dvector(temp);
43
44
/* can return any arbitrary function of area, tmax and wire_length */
45
return (lambdaA * area + lambdaT * tmax + lambdaW * wire_length);
46
}
47
48
49
/* default flp_config */
50
flp_config_t default_flp_config(void)
51
{
52
flp_config_t config;
53
54
/* wrap around L2? */
55
config.wrap_l2 = TRUE;
56
strcpy(config.l2_label, "L2");
57
58
/* model dead space around the rim of the chip? */
59
config.model_rim = FALSE;
60
config.rim_thickness = 50e-6;
61
62
/* area ratio below which to ignore dead space */
63
config.compact_ratio = 0.005;
64
65
/*
66
* no. of discrete orientations for a shape curve.
67
* should be an even number greater than 1
68
*/
69
config.n_orients = 300;
70
71
/* annealing parameters */
72
config.P0 = 0.99; /* initial acceptance probability */
73
/*
74
* average change (delta) in cost. varies according to
75
* the metric. need not be very accurate. just the right
76
* order of magnitude is enough. for instance, if the
77
* metric is flp area, this Davg is the average difference
78
* in the area of successive slicing floorplan attempts.
79
* since the areas are in the order of mm^2, the delta
80
* is also in the same ball park.
81
*/
82
config.Davg = 1.0; /* for our a*A + b*T + c*W metric */
83
config.Kmoves = 7.0; /* no. of moves to try in each step */
84
config.Rcool = 0.99; /* ratio for the cooling schedule */
85
config.Rreject = 0.99; /* ratio of rejects at which to stop annealing */
86
config.Nmax = 1000; /* absolute max no. of annealing steps */
87
88
/* weights for the metric: lambdaA * A + lambdaT * T + lambdaW * W
89
* the weights incorporate two things:
90
* 1) the conversion of A to mm^2, T to K and W to mm.
91
* 2) weighing the relative importance of A, T and K
92
*/
93
config.lambdaA = 5.0e+6;
94
config.lambdaT = 1.0;
95
config.lambdaW = 350;
96
97
return config;
98
}
99
100
/*
101
* parse a table of name-value string pairs and add the configuration
102
* parameters to 'config'
103
*/
104
void flp_config_add_from_strs(flp_config_t *config, str_pair *table, int size)
105
{
106
int idx;
107
if ((idx = get_str_index(table, size, "wrap_l2")) >= 0)
108
if(sscanf(table[idx].value, "%d", &config->wrap_l2) != 1)
109
fatal("invalid format for configuration parameter wrap_l2\n");
110
if ((idx = get_str_index(table, size, "l2_label")) >= 0)
111
if(sscanf(table[idx].value, "%s", config->l2_label) != 1)
112
fatal("invalid format for configuration parameter l2_label\n");
113
if ((idx = get_str_index(table, size, "model_rim")) >= 0)
114
if(sscanf(table[idx].value, "%d", &config->model_rim) != 1)
115
fatal("invalid format for configuration parameter model_rim\n");
116
if ((idx = get_str_index(table, size, "rim_thickness")) >= 0)
117
if(sscanf(table[idx].value, "%lf", &config->rim_thickness) != 1)
118
fatal("invalid format for configuration parameter rim_thickness\n");
119
if ((idx = get_str_index(table, size, "compact_ratio")) >= 0)
120
if(sscanf(table[idx].value, "%lf", &config->compact_ratio) != 1)
121
fatal("invalid format for configuration parameter compact_ratio\n");
122
if ((idx = get_str_index(table, size, "n_orients")) >= 0)
123
if(sscanf(table[idx].value, "%d", &config->n_orients) != 1)
124
fatal("invalid format for configuration parameter n_orients\n");
125
if ((idx = get_str_index(table, size, "P0")) >= 0)
126
if(sscanf(table[idx].value, "%lf", &config->P0) != 1)
127
fatal("invalid format for configuration parameter P0\n");
128
if ((idx = get_str_index(table, size, "Davg")) >= 0)
129
if(sscanf(table[idx].value, "%lf", &config->Davg) != 1)
130
fatal("invalid format for configuration parameter Davg\n");
131
if ((idx = get_str_index(table, size, "Kmoves")) >= 0)
132
if(sscanf(table[idx].value, "%lf", &config->Kmoves) != 1)
133
fatal("invalid format for configuration parameter Kmoves\n");
134
if ((idx = get_str_index(table, size, "Rcool")) >= 0)
135
if(sscanf(table[idx].value, "%lf", &config->Rcool) != 1)
136
fatal("invalid format for configuration parameter Rcool\n");
137
if ((idx = get_str_index(table, size, "Rreject")) >= 0)
138
if(sscanf(table[idx].value, "%lf", &config->Rreject) != 1)
139
fatal("invalid format for configuration parameter Rreject\n");
140
if ((idx = get_str_index(table, size, "Nmax")) >= 0)
141
if(sscanf(table[idx].value, "%d", &config->Nmax) != 1)
142
fatal("invalid format for configuration parameter Nmax\n");
143
if ((idx = get_str_index(table, size, "lambdaA")) >= 0)
144
if(sscanf(table[idx].value, "%lf", &config->lambdaA) != 1)
145
fatal("invalid format for configuration parameter lambdaA\n");
146
if ((idx = get_str_index(table, size, "lambdaT")) >= 0)
147
if(sscanf(table[idx].value, "%lf", &config->lambdaT) != 1)
148
fatal("invalid format for configuration parameter lambdaT\n");
149
if ((idx = get_str_index(table, size, "lambdaW")) >= 0)
150
if(sscanf(table[idx].value, "%lf", &config->lambdaW) != 1)
151
fatal("invalid format for configuration parameter lambdaW\n");
152
153
if (config->rim_thickness <= 0)
154
fatal("rim thickness should be greater than zero\n");
155
if ((config->compact_ratio < 0) || (config->compact_ratio > 1))
156
fatal("compact_ratio should be between 0 and 1\n");
157
if ((config->n_orients <= 1) || (config->n_orients & 1))
158
fatal("n_orients should be an even number greater than 1\n");
159
if (config->Kmoves < 0)
160
fatal("Kmoves should be non-negative\n");
161
if ((config->P0 < 0) || (config->P0 > 1))
162
fatal("P0 should be between 0 and 1\n");
163
if ((config->Rcool < 0) || (config->Rcool > 1))
164
fatal("Rcool should be between 0 and 1\n");
165
if ((config->Rreject < 0) || (config->Rreject > 1))
166
fatal("Rreject should be between 0 and 1\n");
167
if (config->Nmax < 0)
168
fatal("Nmax should be non-negative\n");
169
}
170
171
/*
172
* convert config into a table of name-value pairs. returns the no.
173
* of parameters converted
174
*/
175
int flp_config_to_strs(flp_config_t *config, str_pair *table, int max_entries)
176
{
177
if (max_entries < 15)
178
fatal("not enough entries in table\n");
179
180
sprintf(table[0].name, "wrap_l2");
181
sprintf(table[1].name, "l2_label");
182
sprintf(table[2].name, "model_rim");
183
sprintf(table[3].name, "rim_thickness");
184
sprintf(table[4].name, "compact_ratio");
185
sprintf(table[5].name, "n_orients");
186
sprintf(table[6].name, "P0");
187
sprintf(table[7].name, "Davg");
188
sprintf(table[8].name, "Kmoves");
189
sprintf(table[9].name, "Rcool");
190
sprintf(table[10].name, "Rreject");
191
sprintf(table[11].name, "Nmax");
192
sprintf(table[12].name, "lambdaA");
193
sprintf(table[13].name, "lambdaT");
194
sprintf(table[14].name, "lambdaW");
195
196
sprintf(table[0].value, "%d", config->wrap_l2);
197
sprintf(table[1].value, "%s", config->l2_label);
198
sprintf(table[2].value, "%d", config->model_rim);
199
sprintf(table[3].value, "%lg", config->rim_thickness);
200
sprintf(table[4].value, "%lg", config->compact_ratio);
201
sprintf(table[5].value, "%d", config->n_orients);
202
sprintf(table[6].value, "%lg", config->P0);
203
sprintf(table[7].value, "%lg", config->Davg);
204
sprintf(table[8].value, "%lg", config->Kmoves);
205
sprintf(table[9].value, "%lg", config->Rcool);
206
sprintf(table[10].value, "%lg", config->Rreject);
207
sprintf(table[11].value, "%d", config->Nmax);
208
sprintf(table[12].value, "%lg", config->lambdaA);
209
sprintf(table[13].value, "%lg", config->lambdaT);
210
sprintf(table[14].value, "%lg", config->lambdaW);
211
212
return 15;
213
}
214
215
/*
216
* copy L2 connectivity from 'from' of flp_desc to 'to'
217
* of flp. 'size' elements are copied. the arms are not
218
* connected amidst themselves or with L2 base block
219
*/
220
void copy_l2_info (flp_t *flp, int to, flp_desc_t *flp_desc, int from, int size)
221
{
222
int j, count;
223
224
for(count=0; count < L2_ARMS + 1; count++, to++) {
225
/* copy names */
226
strcpy(flp->units[to].name, flp_desc->units[from].name);
227
for(j=0; j < size; j++) {
228
/* rows */
229
flp->wire_density[to][j] = flp_desc->wire_density[from][j];
230
/* columns */
231
flp->wire_density[j][to] = flp_desc->wire_density[j][from];
232
}
233
}
234
/* fix the names of the arms */
235
strcat(flp->units[to-L2_ARMS+L2_LEFT].name, L2_LEFT_STR);
236
strcat(flp->units[to-L2_ARMS+L2_RIGHT].name, L2_RIGHT_STR);
237
}
238
239
240
/* create a floorplan placeholder from description */
241
flp_t *flp_placeholder(flp_desc_t *flp_desc)
242
{
243
int i, j, count, n_dead;
244
flp_t *flp;
245
246
/* wrap L2 around? */
247
int wrap_l2 = FALSE;
248
if (flp_desc->config.wrap_l2 &&
249
!strcasecmp(flp_desc->units[flp_desc->n_units-1].name, flp_desc->config.l2_label))
250
wrap_l2 = TRUE;
251
252
flp = (flp_t *) calloc (1, sizeof(flp_t));
253
if(!flp)
254
fatal("memory allocation error\n");
255
/*
256
* number of dead blocks = no. of core blocks - 1.
257
* (one per vertical or horizontal cut). if L2 is
258
* wrapped around, core blocks = flp_desc->n_units-1
259
*/
260
n_dead = flp_desc->n_units - !!(wrap_l2) - 1;
261
flp->n_units = flp_desc->n_units + n_dead;
262
263
/* wrap L2 around - extra arms are added */
264
if (wrap_l2)
265
flp->n_units += L2_ARMS;
266
267
/*
268
* model the dead space in the edge. let us make
269
* one dead block per corner edge of a block. so,
270
* no. of rim blocks could be at most 2*n+2 where
271
* n is the total no. of blocks (the worst case
272
* is just all blocks lined up side-by-side)
273
*/
274
if (flp_desc->config.model_rim)
275
flp->n_units += (2*flp->n_units + 2);
276
277
flp->units = (unit_t *) calloc (flp->n_units, sizeof(unit_t));
278
flp->wire_density = (double **) calloc(flp->n_units, sizeof(double *));
279
if (!flp->units || !flp->wire_density)
280
fatal("memory allocation error\n");
281
for (i=0; i < flp->n_units; i++) {
282
flp->wire_density[i] = (double *) calloc(flp->n_units, sizeof(double));
283
if (!flp->wire_density[i])
284
fatal("memory allocation error\n");
285
}
286
287
/* copy connectivity (only for non-dead core blocks) */
288
for(i=0; i < flp_desc->n_units-!!(wrap_l2); i++) {
289
strcpy(flp->units[i].name, flp_desc->units[i].name);
290
for (j=0; j < flp_desc->n_units-!!(wrap_l2); j++) {
291
flp->wire_density[i][j] = flp_desc->wire_density[i][j];
292
}
293
}
294
295
/* name the dead blocks */
296
for(count=0; count < n_dead; count++, i++)
297
sprintf(flp->units[i].name, DEAD_PREFIX"%d", count);
298
299
/* L2 connectivity info */
300
if (wrap_l2)
301
copy_l2_info(flp, i, flp_desc, flp_desc->n_units-1, flp_desc->n_units-1);
302
303
return flp;
304
}
305
306
/*
307
* note that if wrap_l2 is true, L2 is beyond the boundary in flp_desc
308
* but flp contains it within its boundaries.
309
*/
310
void restore_dead_blocks(flp_t *flp, flp_desc_t *flp_desc,
311
int compacted, int wrap_l2,
312
int model_rim, int rim_blocks)
313
{
314
int i, j, idx=0;
315
/* remove L2 and rim blocks and restore the compacted blocks */
316
if(model_rim)
317
flp->n_units -= rim_blocks;
318
if (wrap_l2)
319
flp->n_units -= (L2_ARMS+1);
320
flp->n_units += compacted;
321
322
/* reinitialize the dead blocks */
323
for(i=0; i < flp_desc->n_units-1; i++) {
324
idx = flp_desc->n_units + i;
325
sprintf(flp->units[idx].name, DEAD_PREFIX"%d", i);
326
flp->units[idx].leftx = flp->units[idx].bottomy = 0;
327
flp->units[idx].width = flp->units[idx].height = 0;
328
for(j=0; j < flp->n_units; j++)
329
flp->wire_density[idx][j] = flp->wire_density[j][idx] = 0;
330
}
331
}
332
333
/* translate the floorplan to new origin (x,y) */
334
void flp_translate(flp_t *flp, double x, double y)
335
{
336
int i;
337
double minx = flp->units[0].leftx;
338
double miny = flp->units[0].bottomy;
339
340
for (i=1; i < flp->n_units; i++) {
341
if (minx > flp->units[i].leftx)
342
minx = flp->units[i].leftx;
343
if (miny > flp->units[i].bottomy)
344
miny = flp->units[i].bottomy;
345
}
346
for (i=0; i < flp->n_units; i++) {
347
flp->units[i].leftx += (x - minx);
348
flp->units[i].bottomy += (y - miny);
349
}
350
}
351
352
/* scale the floorplan by a factor 'factor' */
353
void flp_scale(flp_t *flp, double factor)
354
{
355
int i;
356
double minx = flp->units[0].leftx;
357
double miny = flp->units[0].bottomy;
358
359
for (i=1; i < flp->n_units; i++) {
360
if (minx > flp->units[i].leftx)
361
minx = flp->units[i].leftx;
362
if (miny > flp->units[i].bottomy)
363
miny = flp->units[i].bottomy;
364
}
365
for(i=0; i < flp->n_units; i++) {
366
flp->units[i].leftx = (flp->units[i].leftx - minx) * factor + minx;
367
flp->units[i].bottomy = (flp->units[i].bottomy - miny) * factor + miny;
368
flp->units[i].width *= factor;
369
flp->units[i].height *= factor;
370
}
371
}
372
373
/*
374
* change the orientation of the floorplan by
375
* rotating and/or flipping. the target orientation
376
* is specified in 'target'. 'width', 'height', 'xorig'
377
* and 'yorig' are those of 'flp' respectively.
378
*/
379
void flp_change_orient(flp_t *flp, double xorig, double yorig,
380
double width, double height, orient_t target)
381
{
382
int i;
383
384
for(i=0; i < flp->n_units; i++) {
385
double leftx, bottomy, rightx, topy;
386
/* all co-ordinate calculations are
387
* done assuming (0,0) as the center.
388
* so, shift accordingly
389
*/
390
leftx = flp->units[i].leftx - (xorig + width / 2.0);
391
bottomy = flp->units[i].bottomy - (yorig + height / 2.0);
392
rightx = leftx + flp->units[i].width;
393
topy = bottomy + flp->units[i].height;
394
/* when changing orientation, leftx and
395
* bottomy of a rectangle could change
396
* to one of the other three corners.
397
* also, signs of the co-ordinates
398
* change according to the rotation
399
* or reflection. Further x & y are
400
* swapped for rotations that are
401
* odd multiples of 90 degrees
402
*/
403
switch(target) {
404
case ROT_0:
405
flp->units[i].leftx = leftx;
406
flp->units[i].bottomy = bottomy;
407
break;
408
case ROT_90:
409
flp->units[i].leftx = -topy;
410
flp->units[i].bottomy = leftx;
411
swap_dval(&(flp->units[i].width), &(flp->units[i].height));
412
break;
413
case ROT_180:
414
flp->units[i].leftx = -rightx;
415
flp->units[i].bottomy = -topy;
416
break;
417
case ROT_270:
418
flp->units[i].leftx = bottomy;
419
flp->units[i].bottomy = -rightx;
420
swap_dval(&(flp->units[i].width), &(flp->units[i].height));
421
break;
422
case FLIP_0:
423
flp->units[i].leftx = -rightx;
424
flp->units[i].bottomy = bottomy;
425
break;
426
case FLIP_90:
427
flp->units[i].leftx = bottomy;
428
flp->units[i].bottomy = leftx;
429
swap_dval(&(flp->units[i].width), &(flp->units[i].height));
430
break;
431
case FLIP_180:
432
flp->units[i].leftx = leftx;
433
flp->units[i].bottomy = -topy;
434
break;
435
case FLIP_270:
436
flp->units[i].leftx = -topy;
437
flp->units[i].bottomy = -rightx;
438
swap_dval(&(flp->units[i].width), &(flp->units[i].height));
439
break;
440
default:
441
fatal("unknown orientation\n");
442
break;
443
}
444
/* translate back to original origin */
445
flp->units[i].leftx += (xorig + width / 2.0);
446
flp->units[i].bottomy += (yorig + height / 2.0);
447
}
448
}
449
450
/*
451
* create a non-uniform grid-like floorplan equivalent to this.
452
* this function is mainly useful when using the HotSpot block
453
* model to model floorplans of drastically differing aspect
454
* ratios and granularity. an example for such a floorplan
455
* would be the standard ev6 floorplan that comes with HotSpot,
456
* where the register file is subdivided into say 128 entries.
457
* the HotSpot block model could result in inaccuracies while
458
* trying to model such floorplans of differing granularity.
459
* if such inaccuracies occur, use this function to create an
460
* equivalent floorplan that can be modeled accurately in
461
* HotSpot. 'map', if non-NULL, is an output parameter to store
462
* the 2-d array allocated by the function.
463
*/
464
flp_t *flp_create_grid(flp_t *flp, int ***map)
465
{
466
double x[MAX_UNITS], y[MAX_UNITS];
467
int i, j, n, xsize=0, ysize=0, count=0, found, **ptr;
468
flp_t *grid;
469
470
/* sort the units' boundary co-ordinates */
471
for(i=0; i < flp->n_units; i++) {
472
double r, t;
473
r = flp->units[i].leftx + flp->units[i].width;
474
t = flp->units[i].bottomy + flp->units[i].height;
475
if(bsearch_insert_double(x, xsize, flp->units[i].leftx))
476
xsize++;
477
if(bsearch_insert_double(y, ysize, flp->units[i].bottomy))
478
ysize++;
479
if(bsearch_insert_double(x, xsize, r))
480
xsize++;
481
if(bsearch_insert_double(y, ysize, t))
482
ysize++;
483
}
484
485
/*
486
* the grid formed by the lines from x and y arrays
487
* is our desired floorplan. allocate memory for it
488
*/
489
grid = (flp_t *) calloc (1, sizeof(flp_t));
490
if(!grid)
491
fatal("memory allocation error\n");
492
grid->n_units = (xsize-1) * (ysize-1);
493
grid->units = (unit_t *) calloc (grid->n_units, sizeof(unit_t));
494
grid->wire_density = (double **) calloc(grid->n_units, sizeof(double *));
495
if (!grid->units || !grid->wire_density)
496
fatal("memory allocation error\n");
497
for (i=0; i < grid->n_units; i++) {
498
grid->wire_density[i] = (double *) calloc(grid->n_units, sizeof(double));
499
if (!grid->wire_density[i])
500
fatal("memory allocation error\n");
501
}
502
/* mapping between blocks of 'flp' to those of 'grid' */
503
ptr = (int **) calloc(flp->n_units, sizeof(int *));
504
if (!ptr)
505
fatal("memory allocation error\n");
506
/*
507
* ptr is a 2-d array with each row of possibly different
508
* length. the size of each row is stored in its first element.
509
* here, it is basically the mapping between 'flp' to 'grid'
510
* i.e., for each flp->unit, it stores the set of grid->units
511
* it maps to.
512
*/
513
for(i=0; i < flp->n_units; i++) {
514
ptr[i] = (int *) calloc(grid->n_units+1, sizeof(int));
515
if(!ptr[i])
516
fatal("memory allocation error\n");
517
}
518
519
/*
520
* now populate the 'grid' blocks and map the blocks
521
* from 'flp' to 'grid'. for each block, identify the
522
* intervening lines that chop it into grid cells and
523
* assign the names of those cells from that of the
524
* block
525
*/
526
for(i=0; i < flp->n_units; i++) {
527
double *xstart, *xend, *ystart, *yend;
528
double *ptr1, *ptr2;
529
int grid_num=0;
530
if (!bsearch_double(x, xsize, flp->units[i].leftx, &xstart))
531
fatal("invalid sorted arrays\n");
532
if (!bsearch_double(x, xsize, flp->units[i].leftx+flp->units[i].width, &xend))
533
fatal("invalid sorted arrays\n");
534
if (!bsearch_double(y, ysize, flp->units[i].bottomy, &ystart))
535
fatal("invalid sorted arrays\n");
536
if (!bsearch_double(y, ysize, flp->units[i].bottomy+flp->units[i].height, &yend))
537
fatal("invalid sorted arrays\n");
538
for(ptr1 = xstart; ptr1 < xend; ptr1++)
539
for(ptr2 = ystart; ptr2 < yend; ptr2++) {
540
/* add this grid block if it has not been added already */
541
for(n=0, found=FALSE; n < count; n++) {
542
if (grid->units[n].leftx == ptr1[0] && grid->units[n].bottomy == ptr2[0]) {
543
found = TRUE;
544
break;
545
}
546
}
547
if(!found) {
548
sprintf(grid->units[count].name, "%s_%d", flp->units[i].name, grid_num);
549
grid->units[count].leftx = ptr1[0];
550
grid->units[count].bottomy = ptr2[0];
551
grid->units[count].width = ptr1[1]-ptr1[0];
552
grid->units[count].height = ptr2[1]-ptr2[0];
553
/* map between position in 'flp' to that in 'grid' */
554
ptr[i][++ptr[i][0]] = count;
555
grid_num++;
556
count++;
557
}
558
}
559
}
560
561
562
/* sanity check */
563
if(count != (xsize-1) * (ysize-1))
564
fatal("mismatch in the no. of units\n");
565
566
/* fill-in the wire densities */
567
for(i=0; i < flp->n_units; i++)
568
for(j=0; j < flp->n_units; j++) {
569
int p, q;
570
for(p=1; p <= ptr[i][0]; p++)
571
for(q=1; q <= ptr[j][0]; q++)
572
grid->wire_density[ptr[i][p]][ptr[j][q]] = flp->wire_density[i][j];
573
}
574
575
/* output the map */
576
if (map)
577
(*map) = ptr;
578
else
579
free_blkgrid_map(flp, ptr);
580
581
return grid;
582
}
583
584
/* free the map allocated by flp_create_grid */
585
void free_blkgrid_map(flp_t *flp, int **map)
586
{
587
int i;
588
589
for(i=0; i < flp->n_units; i++)
590
free(map[i]);
591
free(map);
592
}
593
594
/* translate power numbers to the grid created by flp_create_grid */
595
void xlate_power_blkgrid(flp_t *flp, flp_t *grid, \
596
double *bpower, double *gpower, int **map)
597
{
598
int i, p;
599
600
for(i=0; i < flp->n_units; i++)
601
for(p=1; p <= map[i][0]; p++)
602
/* retain the power density */
603
gpower[map[i][p]] = bpower[i] / (flp->units[i].width * flp->units[i].height) *\
604
grid->units[map[i][p]].width * grid->units[map[i][p]].height;
605
}
606
607
/*
608
* wrap the L2 around this floorplan. L2's area information
609
* is obtained from flp_desc. memory for L2 and its arms has
610
* already been allocated in the flp. note that flp & flp_desc
611
* have L2 hidden beyond the boundary at this point
612
*/
613
void flp_wrap_l2(flp_t *flp, flp_desc_t *flp_desc)
614
{
615
/*
616
* x is the width of the L2 arms
617
* y is the height of the bottom portion
618
*/
619
double x, y, core_width, core_height, total_side, core_area, l2_area;
620
unit_t *l2, *l2_left, *l2_right;
621
622
/* find L2 dimensions so that the total chip becomes a square */
623
core_area = get_total_area(flp);
624
core_width = get_total_width(flp);
625
core_height = get_total_height(flp);
626
/* flp_desc has L2 hidden beyond the boundary */
627
l2_area = flp_desc->units[flp_desc->n_units].area;
628
total_side = sqrt(core_area + l2_area);
629
/*
630
* width of the total chip after L2 wrapping is equal to
631
* the width of the core plus the width of the two arms
632
*/
633
x = (total_side - core_width) / 2.0;
634
y = total_side - core_height;
635
/*
636
* we are trying to solve the equation
637
* (2*x+core_width) * (y+core_height)
638
* = l2_area + core_area
639
* for x and y. it is possible that the values
640
* turnout to be negative if we restrict the
641
* total chip to be a square. in that case,
642
* theoretically, any value of x in the range
643
* (0, l2_area/(2*core_height)) and the
644
* corresponding value of y or any value of y
645
* in the range (0, l2_area/core_width) and the
646
* corresponding value of x would be a solution
647
* we look for a solution with a reasonable
648
* aspect ratio. i.e., we constrain kx = y (or
649
* ky = x depending on the aspect ratio of the
650
* core) where k = WRAP_L2_RATIO. solving the equation
651
* with this constraint, we get the following
652
*/
653
if ( x <= 0 || y <= 0.0) {
654
double sum;
655
if (core_width >= core_height) {
656
sum = WRAP_L2_RATIO * core_width + 2 * core_height;
657
x = (sqrt(sum*sum + 8*WRAP_L2_RATIO*l2_area) - sum) / (4*WRAP_L2_RATIO);
658
y = WRAP_L2_RATIO * x;
659
} else {
660
sum = core_width + 2 * WRAP_L2_RATIO * core_height;
661
y = (sqrt(sum*sum + 8*WRAP_L2_RATIO*l2_area) - sum) / (4*WRAP_L2_RATIO);
662
x = WRAP_L2_RATIO * y;
663
}
664
total_side = 2 * x + core_width;
665
}
666
667
/* fix the positions of core blocks */
668
flp_translate(flp, x, y);
669
670
/* restore the L2 blocks */
671
flp->n_units += (L2_ARMS+1);
672
/* copy L2 info again from flp_desc but from beyond the boundary */
673
copy_l2_info(flp, flp->n_units-L2_ARMS-1, flp_desc,
674
flp_desc->n_units, flp_desc->n_units);
675
676
/* fix the positions of the L2 blocks. connectivity
677
* information has already been fixed (in flp_placeholder).
678
* bottom L2 block - (leftx, bottomy) is already (0,0)
679
*/
680
l2 = &flp->units[flp->n_units-1-L2_ARMS];
681
l2->width = total_side;
682
l2->height = y;
683
l2->leftx = l2->bottomy = 0;
684
685
/* left L2 arm */
686
l2_left = &flp->units[flp->n_units-L2_ARMS+L2_LEFT];
687
l2_left->width = x;
688
l2_left->height = core_height;
689
l2_left->leftx = 0;
690
l2_left->bottomy = y;
691
692
/* right L2 arm */
693
l2_right = &flp->units[flp->n_units-L2_ARMS+L2_RIGHT];
694
l2_right->width = x;
695
l2_right->height = core_height;
696
l2_right->leftx = x + core_width;
697
l2_right->bottomy = y;
698
}
699
700
/*
701
* wrap the rim strips around. each edge has rim blocks
702
* equal to the number of blocks abutting that edge. at
703
* the four corners, the rim blocks are extended by the
704
* rim thickness in a clockwise fashion
705
*/
706
int flp_wrap_rim(flp_t *flp, double rim_thickness)
707
{
708
double width, height;
709
int i, j = 0, k, n = flp->n_units;
710
unit_t *unit;
711
712
width = get_total_width(flp) + 2 * rim_thickness;
713
height = get_total_height(flp) + 2 * rim_thickness;
714
flp_translate(flp, rim_thickness, rim_thickness);
715
716
for (i = 0; i < n; i++) {
717
/* shortcut */
718
unit = &flp->units[i];
719
720
/* block is on the western border */
721
if (eq(unit->leftx, rim_thickness)) {
722
sprintf(flp->units[n+j].name, "%s_%s",
723
RIM_LEFT_STR, unit->name);
724
flp->units[n+j].width = rim_thickness;
725
flp->units[n+j].height = unit->height;
726
flp->units[n+j].leftx = 0;
727
flp->units[n+j].bottomy = unit->bottomy;
728
/* northwest corner */
729
if (eq(unit->bottomy + unit->height, height-rim_thickness))
730
flp->units[n+j].height += rim_thickness;
731
j++;
732
}
733
734
/* block is on the eastern border */
735
if (eq(unit->leftx + unit->width, width-rim_thickness)) {
736
sprintf(flp->units[n+j].name, "%s_%s",
737
RIM_RIGHT_STR, unit->name);
738
flp->units[n+j].width = rim_thickness;
739
flp->units[n+j].height = unit->height;
740
flp->units[n+j].leftx = unit->leftx + unit->width;
741
flp->units[n+j].bottomy = unit->bottomy;
742
/* southeast corner */
743
if (eq(unit->bottomy, rim_thickness)) {
744
flp->units[n+j].height += rim_thickness;
745
flp->units[n+j].bottomy = 0;
746
}
747
j++;
748
}
749
750
/* block is on the northern border */
751
if (eq(unit->bottomy + unit->height, height-rim_thickness)) {
752
sprintf(flp->units[n+j].name, "%s_%s",
753
RIM_TOP_STR, unit->name);
754
flp->units[n+j].width = unit->width;
755
flp->units[n+j].height = rim_thickness;
756
flp->units[n+j].leftx = unit->leftx;
757
flp->units[n+j].bottomy = unit->bottomy + unit->height;
758
/* northeast corner */
759
if (eq(unit->leftx + unit->width, width-rim_thickness))
760
flp->units[n+j].width += rim_thickness;
761
j++;
762
}
763
764
/* block is on the southern border */
765
if (eq(unit->bottomy, rim_thickness)) {
766
sprintf(flp->units[n+j].name, "%s_%s",
767
RIM_BOTTOM_STR, unit->name);
768
flp->units[n+j].width = unit->width;
769
flp->units[n+j].height = rim_thickness;
770
flp->units[n+j].leftx = unit->leftx;
771
flp->units[n+j].bottomy = 0;
772
/* southwest corner */
773
if (eq(unit->leftx, rim_thickness)) {
774
flp->units[n+j].width += rim_thickness;
775
flp->units[n+j].leftx = 0;
776
}
777
j++;
778
}
779
}
780
781
flp->n_units += j;
782
783
/* update all the rim wire densities */
784
for(i=n; i < n+j; i++)
785
for(k=0; k <= i; k++)
786
flp->wire_density[i][k] = flp->wire_density[k][i] = 0;
787
788
return j;
789
}
790
791
/*
792
* floorplanning using simulated annealing.
793
* precondition: flp is a pre-allocated placeholder.
794
* returns the number of compacted blocks in the selected
795
* floorplan
796
*/
797
int floorplan(flp_t *flp, flp_desc_t *flp_desc,
798
RC_model_t *model, double *power)
799
{
800
NPE_t *expr, *next, *best; /* Normalized Polish Expressions */
801
tree_node_stack_t *stack; /* for NPE evaluation */
802
tree_node_t *root; /* shape curve tree */
803
double cost, new_cost, best_cost, sum_cost, T, Tcold;
804
int i, steps, downs, n, rejects, compacted, rim_blocks = 0;
805
int original_n = flp->n_units;
806
int wrap_l2;
807
808
/* to maintain the order of power values during
809
* the compaction/shifting around of blocks
810
*/
811
double *tpower = hotspot_vector(model);
812
813
/* shortcut */
814
flp_config_t cfg = flp_desc->config;
815
816
/*
817
* make the rim strips disappear for slicing tree
818
* purposes. can be restored at the end
819
*/
820
if (cfg.model_rim)
821
flp->n_units = (flp->n_units - 2) / 3;
822
823
/* wrap L2 around? */
824
wrap_l2 = FALSE;
825
if (cfg.wrap_l2 &&
826
!strcasecmp(flp_desc->units[flp_desc->n_units-1].name, cfg.l2_label)) {
827
wrap_l2 = TRUE;
828
/* make L2 disappear too */
829
flp_desc->n_units--;
830
flp->n_units -= (L2_ARMS+1);
831
}
832
833
/* initialization */
834
expr = NPE_get_initial(flp_desc);
835
stack = new_tree_node_stack();
836
init_rand();
837
838
/* convert NPE to flp */
839
root = tree_from_NPE(flp_desc, stack, expr);
840
/* compacts too small dead blocks */
841
compacted = tree_to_flp(root, flp, TRUE, cfg.compact_ratio);
842
/* update the tpower vector according to the compaction */
843
trim_hotspot_vector(model, tpower, power, flp->n_units, compacted);
844
free_tree(root);
845
if(wrap_l2)
846
flp_wrap_l2(flp, flp_desc);
847
if(cfg.model_rim)
848
rim_blocks = flp_wrap_rim(flp, cfg.rim_thickness);
849
850
resize_thermal_model(model, flp->n_units);
851
#if VERBOSE > 2
852
print_flp(flp, TRUE);
853
#endif
854
cost = flp_evaluate_metric(flp, model, tpower, cfg.lambdaA, cfg.lambdaT, cfg.lambdaW);
855
/* restore the compacted blocks */
856
restore_dead_blocks(flp, flp_desc, compacted, wrap_l2, cfg.model_rim, rim_blocks);
857
858
best = NPE_duplicate(expr); /* best till now */
859
best_cost = cost;
860
861
/* simulated annealing */
862
steps = 0;
863
/* initial annealing temperature */
864
T = -cfg.Davg / log(cfg.P0);
865
/*
866
* final annealing temperature - we stop when there
867
* are fewer than (1-cfg.Rreject) accepts.
868
* of those accepts, assuming half are uphill moves,
869
* we want the temperature so that the probability
870
* of accepting uphill moves is as low as
871
* (1-cfg.Rreject)/2.
872
*/
873
Tcold = -cfg.Davg / log ((1.0 - cfg.Rreject) / 2.0);
874
#if VERBOSE > 0
875
fprintf(stdout, "initial cost: %g\tinitial T: %g\tfinal T: %g\n", cost, T, Tcold);
876
#endif
877
/*
878
* stop annealing if temperature has cooled down enough or
879
* max no. of iterations have been tried
880
*/
881
while (T >= Tcold && steps < cfg.Nmax) {
882
/* shortcut */
883
n = cfg.Kmoves * flp->n_units;
884
i = downs = rejects = 0;
885
sum_cost = 0;
886
/* try enough total or downhill moves per T */
887
while ((i < 2 * n) && (downs < n)) {
888
next = make_random_move(expr);
889
890
/* convert NPE to flp */
891
root = tree_from_NPE(flp_desc, stack, next);
892
compacted = tree_to_flp(root, flp, TRUE, cfg.compact_ratio);
893
/* update the tpower vector according to the compaction */
894
trim_hotspot_vector(model, tpower, power, flp->n_units, compacted);
895
free_tree(root);
896
if(wrap_l2)
897
flp_wrap_l2(flp, flp_desc);
898
if(cfg.model_rim)
899
rim_blocks = flp_wrap_rim(flp, cfg.rim_thickness);
900
901
resize_thermal_model(model, flp->n_units);
902
#if VERBOSE > 2
903
print_flp(flp, TRUE);
904
#endif
905
new_cost = flp_evaluate_metric(flp, model, tpower, cfg.lambdaA, cfg.lambdaT, cfg.lambdaW);
906
restore_dead_blocks(flp, flp_desc, compacted, wrap_l2, cfg.model_rim, rim_blocks);
907
908
#if VERBOSE > 1
909
fprintf(stdout, "count: %d\tdowns: %d\tcost: %g\t",
910
i, downs, new_cost);
911
#endif
912
913
/* move accepted? */
914
if (new_cost < cost || /* downhill always accepted */
915
/* boltzmann probability function */
916
rand_fraction() < exp(-(new_cost-cost)/T)) {
917
918
free_NPE(expr);
919
expr = next;
920
921
/* downhill move */
922
if (new_cost < cost) {
923
downs++;
924
/* found new best */
925
if (new_cost < best_cost) {
926
free_NPE(best);
927
best = NPE_duplicate(expr);
928
best_cost = new_cost;
929
}
930
}
931
932
#if VERBOSE > 1
933
fprintf(stdout, "accepted\n");
934
#endif
935
cost = new_cost;
936
sum_cost += cost;
937
} else { /* rejected move */
938
rejects++;
939
free_NPE(next);
940
#if VERBOSE > 1
941
fprintf(stdout, "rejected\n");
942
#endif
943
}
944
i++;
945
}
946
#if VERBOSE > 0
947
fprintf(stdout, "step: %d\tT: %g\ttries: %d\taccepts: %d\trejects: %d\t",
948
steps, T, i, (i-rejects), rejects);
949
fprintf(stdout, "avg. cost: %g\tbest cost: %g\n",
950
(i-rejects)?(sum_cost / (i-rejects)):sum_cost, best_cost);
951
#endif
952
953
/* stop annealing if there are too little accepts */
954
if(((double)rejects/i) > cfg.Rreject)
955
break;
956
957
/* annealing schedule */
958
T *= cfg.Rcool;
959
steps++;
960
}
961
962
/* best floorplan found */
963
root = tree_from_NPE(flp_desc, stack, best);
964
#if VERBOSE > 0
965
{
966
int pos = min_area_pos(root->curve);
967
print_tree_relevant(root, pos, flp_desc);
968
}
969
#endif
970
compacted = tree_to_flp(root, flp, TRUE, cfg.compact_ratio);
971
/* update the power vector according to the compaction */
972
trim_hotspot_vector(model, power, power, flp->n_units, compacted);
973
free_tree(root);
974
/* restore L2 and rim */
975
if(wrap_l2) {
976
flp_wrap_l2(flp, flp_desc);
977
flp_desc->n_units++;
978
}
979
if(cfg.model_rim)
980
rim_blocks = flp_wrap_rim(flp, cfg.rim_thickness);
981
resize_thermal_model(model, flp->n_units);
982
#if VERBOSE > 2
983
print_flp(flp, TRUE);
984
#endif
985
986
free_NPE(expr);
987
free_NPE(best);
988
free_tree_node_stack(stack);
989
free_dvector(tpower);
990
991
/*
992
* return the number of blocks compacted finally
993
* so that any deallocator can take care of memory
994
* accordingly.
995
*/
996
return (original_n - flp->n_units);
997
}
998
999
/* functions duplicated from flp_desc.c */
1000
/*
1001
* find the number of units from the
1002
* floorplan file
1003
*/
1004
int flp_count_units(FILE *fp)
1005
{
1006
char str1[LINE_SIZE], str2[LINE_SIZE];
1007
char name[STR_SIZE];
1008
double leftx, bottomy, width, height;
1009
double cp, res;
1010
char *ptr;
1011
int count = 0;
1012
1013
fseek(fp, 0, SEEK_SET);
1014
while(!feof(fp)) {
1015
fgets(str1, LINE_SIZE, fp);
1016
if (feof(fp))
1017
break;
1018
strcpy(str2, str1);
1019
1020
/* ignore comments and empty lines */
1021
ptr = strtok(str1, " \r\t\n");
1022
if (!ptr || ptr[0] == '#')
1023
continue;
1024
1025
/* functional block placement information */
1026
if (sscanf(str2, "%s%lf%lf%lf%lf%lf%lf", name, &leftx, &bottomy,
1027
&width, &height, &cp, &res) > 4)
1028
count++;
1029
}
1030
return count;
1031
}
1032
1033
flp_t *flp_alloc_init_mem(int count, int use_wire_density)
1034
{
1035
int i;
1036
flp_t *flp;
1037
flp = (flp_t *) calloc (1, sizeof(flp_t));
1038
if(!flp)
1039
fatal("memory allocation error\n");
1040
flp->units = (unit_t *) calloc(count, sizeof(unit_t));
1041
if(!flp->units)
1042
fatal("memory allocation error\n");
1043
if(use_wire_density) {
1044
flp->wire_density = (double **) calloc(count, sizeof(double *));
1045
if (!flp->wire_density)
1046
fatal("memory allocation error\n");
1047
1048
for (i=0; i < count; i++) {
1049
flp->wire_density[i] = (double *) calloc(count, sizeof(double));
1050
if (!flp->wire_density[i])
1051
fatal("memory allocation error\n");
1052
}
1053
}
1054
flp->n_units = count;
1055
return flp;
1056
}
1057
1058
/* populate block information */
1059
void flp_populate_blks(flp_t *flp, FILE *fp)
1060
{
1061
int i=0;
1062
char str[LINE_SIZE], copy[LINE_SIZE];
1063
char name1[STR_SIZE], name2[STR_SIZE];
1064
double width, height, leftx, bottomy, cp, res, temp;
1065
double wire_density;
1066
char *ptr;
1067
1068
fseek(fp, 0, SEEK_SET);
1069
while(!feof(fp)) { /* second pass */
1070
fgets(str, LINE_SIZE, fp);
1071
if (feof(fp))
1072
break;
1073
strcpy(copy, str);
1074
1075
/* ignore comments and empty lines */
1076
ptr = strtok(str, " \r\t\n");
1077
if (!ptr || ptr[0] == '#')
1078
continue;
1079
cp = res = 0.0;
1080
if (sscanf(copy, "%s%lf%lf%lf%lf%lf%lf%lf", name1, &width, &height,
1081
&leftx, &bottomy, &cp, &res, &temp) > 7)
1082
fatal("invalid floorplan file format\n");
1083
else if (sscanf(copy, "%s%lf%lf%lf%lf%lf%lf", name1, &width, &height,
1084
&leftx, &bottomy, &cp, &res) == 7)
1085
{
1086
strcpy(flp->units[i].name, name1);
1087
flp->units[i].width = width;
1088
flp->units[i].height = height;
1089
flp->units[i].leftx = leftx;
1090
flp->units[i].bottomy = bottomy;
1091
flp->units[i].specificheat = cp; //BU_3D set specific heat
1092
flp->units[i].resistivity = res; //BU_3D set resistivity
1093
flp->units[i].hasRes = TRUE;
1094
flp->units[i].hasSh = TRUE;
1095
i++;
1096
}
1097
/* Default Option */
1098
else if(sscanf(copy, "%s%lf%lf%lf%lf%lf%lf", name1, &width, &height,
1099
&leftx, &bottomy, &cp, &res) == 5)
1100
{
1101
strcpy(flp->units[i].name, name1);
1102
flp->units[i].width = width;
1103
flp->units[i].height = height;
1104
flp->units[i].leftx = leftx;
1105
flp->units[i].bottomy = bottomy;
1106
flp->units[i].specificheat = 0.0; //BU_3D else - set specific heat to default value 0.0
1107
flp->units[i].resistivity = 0.0; //BU_3D set resistivity to default value 0.0
1108
flp->units[i].hasRes = FALSE; //BU_3D set boolean for has resistivity flag to false
1109
flp->units[i].hasSh = FALSE; //BU_3D set boolean for has specific heat flag to false
1110
i++;
1111
}
1112
/* skip connectivity info */
1113
else if(sscanf(copy, "%s%s%lf", name1, name2, &wire_density) != 3)
1114
fatal("invalid floorplan file format\n");
1115
}
1116
if (i != flp->n_units)
1117
fatal("mismatch of number of units\n");
1118
}
1119
1120
/* populate connectivity info */
1121
void flp_populate_connects(flp_t *flp, FILE *fp)
1122
{
1123
char str1[LINE_SIZE], str2[LINE_SIZE];
1124
char name1[STR_SIZE], name2[STR_SIZE];
1125
/* dummy fields */
1126
double f1, f2, f3, f4, f5, f6;
1127
double wire_density;
1128
char *ptr;
1129
int x, y, temp;
1130
1131
/* initialize wire_density */
1132
for(x=0; x < flp->n_units; x++)
1133
for(y=0; y < flp->n_units; y++)
1134
flp->wire_density[x][y] = 0.0;
1135
1136
fseek(fp, 0, SEEK_SET);
1137
while(!feof(fp)) {
1138
fgets(str1, LINE_SIZE, fp);
1139
if (feof(fp))
1140
break;
1141
strcpy(str2, str1);
1142
1143
/* ignore comments and empty lines */
1144
ptr = strtok(str1, " \r\t\n");
1145
if (!ptr || ptr[0] == '#')
1146
continue;
1147
1148
/* lines with unit positions */
1149
if (sscanf(str2, "%s%lf%lf%lf%lf%lf%lf", name1, &f1, &f2, &f3, &f4, &f5, &f6) == 7 ||
1150
/* flp_desc like lines. ignore them */
1151
sscanf(str2, "%s%lf%lf%lf%d", name1, &f1, &f2, &f3, &temp) == 5)
1152
continue;
1153
1154
/* lines with connectivity info */
1155
else if (sscanf(str2, "%s%s%lf", name1, name2, &wire_density) == 3) {
1156
x = get_blk_index(flp, name1);
1157
y = get_blk_index(flp, name2);
1158
1159
if (x == y)
1160
fatal("block connected to itself?\n");
1161
1162
if (!flp->wire_density[x][y] && !flp->wire_density[y][x])
1163
flp->wire_density[x][y] = flp->wire_density[y][x] = wire_density;
1164
else if((flp->wire_density[x][y] != flp->wire_density[y][x]) ||
1165
(flp->wire_density[x][y] != wire_density)) {
1166
sprintf(str2, "wrong connectivity information for blocks %s and %s\n",
1167
name1, name2);
1168
fatal(str2);
1169
}
1170
} else
1171
fatal("invalid floorplan file format\n");
1172
} /* end while */
1173
}
1174
1175
flp_t *read_flp(char *file, int read_connects, int initialize_connects)
1176
{
1177
char str[STR_SIZE];
1178
FILE *fp;
1179
flp_t *flp;
1180
int count, i, j;
1181
1182
if (!strcasecmp(file, "stdin"))
1183
fp = stdin;
1184
else
1185
fp = fopen (file, "r");
1186
1187
if (!fp) {
1188
sprintf(str, "error opening file %s\n", file);
1189
fatal(str);
1190
}
1191
1192
/* 1st pass - find n_units */
1193
count = flp_count_units(fp);
1194
if(!count)
1195
fatal("no units specified in the floorplan file\n");
1196
1197
/* allocate initial memory */
1198
flp = flp_alloc_init_mem(count, read_connects || initialize_connects);
1199
1200
/* 2nd pass - populate block info */
1201
flp_populate_blks(flp, fp);
1202
1203
/* 3rd pass - populate connectivity info */
1204
if (read_connects)
1205
flp_populate_connects(flp, fp);
1206
/* older version - no connectivity */
1207
else if(initialize_connects)
1208
for (i=0; i < flp->n_units; i++)
1209
for (j=0; j < flp->n_units; j++)
1210
flp->wire_density[i][j] = 1.0;
1211
1212
if(fp != stdin)
1213
fclose(fp);
1214
1215
/* make sure the origin is (0,0) */
1216
flp_translate(flp, 0, 0);
1217
return flp;
1218
}
1219
1220
void dump_flp(flp_t *flp, char *file, int dump_connects)
1221
{
1222
char str[STR_SIZE];
1223
int i, j;
1224
FILE *fp;
1225
1226
if (!strcasecmp(file, "stdout"))
1227
fp = stdout;
1228
else if (!strcasecmp(file, "stderr"))
1229
fp = stderr;
1230
else
1231
fp = fopen (file, "w");
1232
1233
if (!fp) {
1234
sprintf(str, "error opening file %s\n", file);
1235
fatal(str);
1236
}
1237
/* functional unit placement info */
1238
for(i=0; i < flp->n_units; i++) {
1239
fprintf(fp, "%s\t%.11f\t%.11f\t%.11f\t%.11f\n",
1240
flp->units[i].name, flp->units[i].width, flp->units[i].height,
1241
flp->units[i].leftx, flp->units[i].bottomy);
1242
}
1243
1244
if (dump_connects) {
1245
fprintf(fp, "\n");
1246
/* connectivity information */
1247
for(i=1; i < flp->n_units; i++)
1248
for(j=0; j < i; j++)
1249
if (flp->wire_density[i][j])
1250
fprintf(fp, "%s\t%s\t%.3f\n", flp->units[i].name,
1251
flp->units[j].name, flp->wire_density[i][j]);
1252
}
1253
1254
if(fp != stdout && fp != stderr)
1255
fclose(fp);
1256
}
1257
1258
void free_flp(flp_t *flp, int compacted, int free_connects)
1259
{
1260
int i;
1261
if(free_connects) {
1262
for (i=0; i < flp->n_units + compacted; i++) {
1263
free(flp->wire_density[i]);
1264
}
1265
free(flp->wire_density);
1266
}
1267
free(flp->units);
1268
free(flp);
1269
}
1270
1271
void print_flp_fig (flp_t *flp)
1272
{
1273
int i;
1274
double leftx, bottomy, rightx, topy;
1275
1276
fprintf(stdout, "FIG starts\n");
1277
for (i=0; i< flp->n_units; i++) {
1278
leftx = flp->units[i].leftx;
1279
bottomy = flp->units[i].bottomy;
1280
rightx = flp->units[i].leftx + flp->units[i].width;
1281
topy = flp->units[i].bottomy + flp->units[i].height;
1282
fprintf(stdout, "%.5f %.5f %.5f %.5f %.5f %.5f %.5f %.5f %.5f %.5f\n",
1283
leftx, bottomy, leftx, topy, rightx, topy, rightx, bottomy,
1284
leftx, bottomy);
1285
fprintf(stdout, "%s\n", flp->units[i].name);
1286
}
1287
fprintf(stdout, "FIG ends\n");
1288
}
1289
1290
/* debug print */
1291
void print_flp (flp_t *flp, int print_connects)
1292
{
1293
int i, j;
1294
1295
fprintf(stdout, "printing floorplan information for %d blocks\n", flp->n_units);
1296
fprintf(stdout, "name\tarea\twidth\theight\tleftx\tbottomy\trightx\ttopy\n");
1297
for (i=0; i< flp->n_units; i++) {
1298
double area, width, height, leftx, bottomy, rightx, topy;
1299
char *name;
1300
name = flp->units[i].name;
1301
width = flp->units[i].width;
1302
height = flp->units[i].height;
1303
area = width * height;
1304
leftx = flp->units[i].leftx;
1305
bottomy = flp->units[i].bottomy;
1306
rightx = flp->units[i].leftx + flp->units[i].width;
1307
topy = flp->units[i].bottomy + flp->units[i].height;
1308
fprintf(stdout, "%s\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n",
1309
name, area, width, height, leftx, bottomy, rightx, topy);
1310
}
1311
if(print_connects) {
1312
fprintf(stdout, "printing connections:\n");
1313
for (i=0; i< flp->n_units; i++)
1314
for (j=i+1; j < flp->n_units; j++)
1315
if (flp->wire_density[i][j])
1316
fprintf(stdout, "%s\t%s\t%lg\n", flp->units[i].name,
1317
flp->units[j].name, flp->wire_density[i][j]);
1318
}
1319
}
1320
1321
/* print the statistics about this floorplan.
1322
* note that connects_file is NULL if wire
1323
* information is already populated
1324
*/
1325
void print_flp_stats(flp_t *flp, RC_model_t *model,
1326
char *l2_label, char *power_file,
1327
char *connects_file)
1328
{
1329
double core, total, occupied; /* area */
1330
double width, height, aspect, total_w, total_h;
1331
double wire_metric;
1332
double peak, avg; /* temperature */
1333
double *power, *temp;
1334
FILE *fp = NULL;
1335
char str[STR_SIZE];
1336
1337
if (connects_file) {
1338
fp = fopen(connects_file, "r");
1339
if (!fp) {
1340
sprintf(str, "error opening file %s\n", connects_file);
1341
fatal(str);
1342
}
1343
flp_populate_connects(flp, fp);
1344
}
1345
1346
power = hotspot_vector(model);
1347
temp = hotspot_vector(model);
1348
read_power(model, power, power_file);
1349
1350
core = get_core_area(flp, l2_label);
1351
total = get_total_area(flp);
1352
total_w = get_total_width(flp);
1353
total_h = get_total_height(flp);
1354
occupied = get_core_occupied_area(flp, l2_label);
1355
width = get_core_width(flp, l2_label);
1356
height = get_core_height(flp, l2_label);
1357
aspect = (height > width) ? (height/width) : (width/height);
1358
wire_metric = get_wire_metric(flp);
1359
1360
populate_R_model(model, flp);
1361
steady_state_temp(model, power, temp);
1362
peak = find_max_temp(model, temp);
1363
avg = find_avg_temp(model, temp);
1364
1365
fprintf(stdout, "printing summary statistics about the floorplan\n");
1366
fprintf(stdout, "total area:\t%g\n", total);
1367
fprintf(stdout, "total width:\t%g\n", total_w);
1368
fprintf(stdout, "total height:\t%g\n", total_h);
1369
fprintf(stdout, "core area:\t%g\n", core);
1370
fprintf(stdout, "occupied area:\t%g\n", occupied);
1371
fprintf(stdout, "area utilization:\t%.3f\n", occupied / core * 100.0);
1372
fprintf(stdout, "core width:\t%g\n", width);
1373
fprintf(stdout, "core height:\t%g\n", height);
1374
fprintf(stdout, "core aspect ratio:\t%.3f\n", aspect);
1375
fprintf(stdout, "wire length metric:\t%.3f\n", wire_metric);
1376
fprintf(stdout, "peak temperature:\t%.3f\n", peak);
1377
fprintf(stdout, "avg temperature:\t%.3f\n", avg);
1378
1379
free_dvector(power);
1380
free_dvector(temp);
1381
if (fp)
1382
fclose(fp);
1383
}
1384
1385
int get_blk_index(flp_t *flp, char *name)
1386
{
1387
int i;
1388
char msg[STR_SIZE];
1389
1390
if (!flp)
1391
fatal("null pointer in get_blk_index\n");
1392
1393
for (i = 0; i < flp->n_units; i++) {
1394
if (!strcasecmp(name, flp->units[i].name)) {
1395
return i;
1396
}
1397
}
1398
1399
sprintf(msg, "block %s not found\n", name);
1400
fatal(msg);
1401
return -1;
1402
}
1403
1404
int is_horiz_adj(flp_t *flp, int i, int j)
1405
{
1406
double x1, x2, x3, x4;
1407
double y1, y2, y3, y4;
1408
1409
if (i == j)
1410
return FALSE;
1411
1412
x1 = flp->units[i].leftx;
1413
x2 = x1 + flp->units[i].width;
1414
x3 = flp->units[j].leftx;
1415
x4 = x3 + flp->units[j].width;
1416
1417
y1 = flp->units[i].bottomy;
1418
y2 = y1 + flp->units[i].height;
1419
y3 = flp->units[j].bottomy;
1420
y4 = y3 + flp->units[j].height;
1421
1422
/* diagonally adjacent => not adjacent */
1423
if (eq(x2,x3) && eq(y2,y3))
1424
return FALSE;
1425
if (eq(x1,x4) && eq(y1,y4))
1426
return FALSE;
1427
if (eq(x2,x3) && eq(y1,y4))
1428
return FALSE;
1429
if (eq(x1,x4) && eq(y2,y3))
1430
return FALSE;
1431
1432
if (eq(x1,x4) || eq(x2,x3))
1433
if ((y3 >= y1 && y3 <= y2) || (y4 >= y1 && y4 <= y2) ||
1434
(y1 >= y3 && y1 <= y4) || (y2 >= y3 && y2 <= y4))
1435
return TRUE;
1436
1437
return FALSE;
1438
}
1439
1440
int is_vert_adj (flp_t *flp, int i, int j)
1441
{
1442
double x1, x2, x3, x4;
1443
double y1, y2, y3, y4;
1444
1445
if (i == j)
1446
return FALSE;
1447
1448
x1 = flp->units[i].leftx;
1449
x2 = x1 + flp->units[i].width;
1450
x3 = flp->units[j].leftx;
1451
x4 = x3 + flp->units[j].width;
1452
1453
y1 = flp->units[i].bottomy;
1454
y2 = y1 + flp->units[i].height;
1455
y3 = flp->units[j].bottomy;
1456
y4 = y3 + flp->units[j].height;
1457
1458
/* diagonally adjacent => not adjacent */
1459
if (eq(x2,x3) && eq(y2,y3))
1460
return FALSE;
1461
if (eq(x1,x4) && eq(y1,y4))
1462
return FALSE;
1463
if (eq(x2,x3) && eq(y1,y4))
1464
return FALSE;
1465
if (eq(x1,x4) && eq(y2,y3))
1466
return FALSE;
1467
1468
if (eq(y1,y4) || eq(y2,y3))
1469
if ((x3 >= x1 && x3 <= x2) || (x4 >= x1 && x4 <= x2) ||
1470
(x1 >= x3 && x1 <= x4) || (x2 >= x3 && x2 <= x4))
1471
return TRUE;
1472
1473
return FALSE;
1474
}
1475
1476
double get_shared_len(flp_t *flp, int i, int j)
1477
{
1478
double p11, p12, p21, p22;
1479
p11 = p12 = p21 = p22 = 0.0;
1480
1481
if (i==j)
1482
return FALSE;
1483
1484
if (is_horiz_adj(flp, i, j)) {
1485
p11 = flp->units[i].bottomy;
1486
p12 = p11 + flp->units[i].height;
1487
p21 = flp->units[j].bottomy;
1488
p22 = p21 + flp->units[j].height;
1489
}
1490
1491
if (is_vert_adj(flp, i, j)) {
1492
p11 = flp->units[i].leftx;
1493
p12 = p11 + flp->units[i].width;
1494
p21 = flp->units[j].leftx;
1495
p22 = p21 + flp->units[j].width;
1496
}
1497
1498
return (MIN(p12, p22) - MAX(p11, p21));
1499
}
1500
1501
double get_total_width(flp_t *flp)
1502
{
1503
int i;
1504
double min_x = flp->units[0].leftx;
1505
double max_x = flp->units[0].leftx + flp->units[0].width;
1506
1507
for (i=1; i < flp->n_units; i++) {
1508
if (flp->units[i].leftx < min_x)
1509
min_x = flp->units[i].leftx;
1510
if (flp->units[i].leftx + flp->units[i].width > max_x)
1511
max_x = flp->units[i].leftx + flp->units[i].width;
1512
}
1513
1514
return (max_x - min_x);
1515
}
1516
1517
double get_total_height(flp_t *flp)
1518
{
1519
int i;
1520
double min_y = flp->units[0].bottomy;
1521
double max_y = flp->units[0].bottomy + flp->units[0].height;
1522
1523
for (i=1; i < flp->n_units; i++) {
1524
if (flp->units[i].bottomy < min_y)
1525
min_y = flp->units[i].bottomy;
1526
if (flp->units[i].bottomy + flp->units[i].height > max_y)
1527
max_y = flp->units[i].bottomy + flp->units[i].height;
1528
}
1529
1530
return (max_y - min_y);
1531
}
1532
1533
double get_minx(flp_t *flp)
1534
{
1535
int i;
1536
double min_x = flp->units[0].leftx;
1537
1538
for (i=1; i < flp->n_units; i++)
1539
if (flp->units[i].leftx < min_x)
1540
min_x = flp->units[i].leftx;
1541
1542
return min_x;
1543
}
1544
1545
double get_miny(flp_t *flp)
1546
{
1547
int i;
1548
double min_y = flp->units[0].bottomy;
1549
1550
for (i=1; i < flp->n_units; i++)
1551
if (flp->units[i].bottomy < min_y)
1552
min_y = flp->units[i].bottomy;
1553
1554
return min_y;
1555
}
1556
1557
/* precondition: L2 should have been wrapped around */
1558
double get_core_width(flp_t *flp, char *l2_label)
1559
{
1560
int i;
1561
double min_x = LARGENUM;
1562
double max_x = -LARGENUM;
1563
1564
for (i=0; i < flp->n_units; i++) {
1565
/* core is that part of the chip excluding the l2 and rim */
1566
if (strstr(flp->units[i].name, l2_label) != flp->units[i].name &&
1567
strstr(flp->units[i].name, RIM_PREFIX) != flp->units[i].name) {
1568
if (flp->units[i].leftx < min_x)
1569
min_x = flp->units[i].leftx;
1570
if (flp->units[i].leftx + flp->units[i].width > max_x)
1571
max_x = flp->units[i].leftx + flp->units[i].width;
1572
}
1573
}
1574
1575
return (max_x - min_x);
1576
}
1577
1578
/* precondition: L2 should have been wrapped around */
1579
double get_core_height(flp_t *flp, char *l2_label)
1580
{
1581
int i;
1582
double min_y = LARGENUM;
1583
double max_y = -LARGENUM;
1584
1585
for (i=0; i < flp->n_units; i++) {
1586
/* core is that part of the chip excluding the l2 and rim */
1587
if (strstr(flp->units[i].name, l2_label) != flp->units[i].name &&
1588
strstr(flp->units[i].name, RIM_PREFIX) != flp->units[i].name) {
1589
if (flp->units[i].bottomy < min_y)
1590
min_y = flp->units[i].bottomy;
1591
if (flp->units[i].bottomy + flp->units[i].height > max_y)
1592
max_y = flp->units[i].bottomy + flp->units[i].height;
1593
}
1594
}
1595
1596
return (max_y - min_y);
1597
}
1598
1599
double get_total_area(flp_t *flp)
1600
{
1601
int i;
1602
double area = 0.0;
1603
for(i=0; i < flp->n_units; i++)
1604
area += flp->units[i].width * flp->units[i].height;
1605
return area;
1606
}
1607
1608
double get_core_area(flp_t *flp, char *l2_label)
1609
{
1610
int i;
1611
double area = 0.0;
1612
for(i=0; i < flp->n_units; i++)
1613
if (strstr(flp->units[i].name, l2_label) != flp->units[i].name &&
1614
strstr(flp->units[i].name, RIM_PREFIX) != flp->units[i].name)
1615
area += flp->units[i].width * flp->units[i].height;
1616
return area;
1617
}
1618
1619
/* excluding the dead blocks */
1620
double get_core_occupied_area(flp_t *flp, char *l2_label)
1621
{
1622
int i, num;
1623
double dead_area = 0.0;
1624
for(i=0; i < flp->n_units; i++) {
1625
/*
1626
* there can be a max of n-1 dead blocks where n is the
1627
* number of non-dead blocks (since each cut, vertical
1628
* or horizontal, can correspond to a maximum of one
1629
* dead block
1630
*/
1631
if ((sscanf(flp->units[i].name, DEAD_PREFIX"%d", &num) == 1) &&
1632
(num < (flp->n_units-1) / 2))
1633
dead_area += flp->units[i].width * flp->units[i].height;
1634
}
1635
return get_core_area(flp, l2_label) - dead_area;
1636
}
1637
1638
double get_wire_metric(flp_t *flp)
1639
{
1640
int i, j;
1641
double w = 0.0, dist;
1642
1643
for (i=0; i < flp->n_units; i++)
1644
for (j=0; j < flp->n_units; j++)
1645
if (flp->wire_density[i][j]) {
1646
dist = get_manhattan_dist(flp, i, j);
1647
w += flp->wire_density[i][j] * dist;
1648
}
1649
return w;
1650
}
1651
1652
double get_manhattan_dist(flp_t *flp, int i, int j)
1653
{
1654
double x1 = flp->units[i].leftx + flp->units[i].width / 2.0;
1655
double y1 = flp->units[i].bottomy + flp->units[i].height / 2.0;
1656
double x2 = flp->units[j].leftx + flp->units[j].width / 2.0;
1657
double y2 = flp->units[j].bottomy + flp->units[j].height / 2.0;
1658
return (fabs(x2-x1) + fabs(y2-y1));
1659
}
1660
1661