/* print the statistics about this floorplan. * note that connects_file is NULL if wire * information is already populated */ void print_flp_stats(flp_t *flp, RC_model_t *model, char *l2_label, char *power_file, char *connects_file) { double core, total, occupied; /* area */ double width, height, aspect, total_w, total_h; double wire_metric; double peak, avg; /* temperature */ double *power, *temp; FILE *fp = NULL; char str[STR_SIZE]; if (connects_file) { fp = fopen(connects_file, "r"); if (!fp) { sprintf(str, "error opening file %s\n", connects_file); fatal(str); } flp_populate_connects(flp, fp); } power = hotspot_vector(model); temp = hotspot_vector(model); read_power(model, power, power_file); core = get_core_area(flp, l2_label); total = get_total_area(flp); total_w = get_total_width(flp); total_h = get_total_height(flp); occupied = get_core_occupied_area(flp, l2_label); width = get_core_width(flp, l2_label); height = get_core_height(flp, l2_label); aspect = (height > width) ? (height/width) : (width/height); wire_metric = get_wire_metric(flp); populate_R_model(model, flp); steady_state_temp(model, power, temp); peak = find_max_temp(model, temp); avg = find_avg_temp(model, temp); fprintf(stdout, "printing summary statistics about the floorplan\n"); fprintf(stdout, "total area:\t%g\n", total); fprintf(stdout, "total width:\t%g\n", total_w); fprintf(stdout, "total height:\t%g\n", total_h); fprintf(stdout, "core area:\t%g\n", core); fprintf(stdout, "occupied area:\t%g\n", occupied); fprintf(stdout, "area utilization:\t%.3f\n", occupied / core * 100.0); fprintf(stdout, "core width:\t%g\n", width); fprintf(stdout, "core height:\t%g\n", height); fprintf(stdout, "core aspect ratio:\t%.3f\n", aspect); fprintf(stdout, "wire length metric:\t%.3f\n", wire_metric); fprintf(stdout, "peak temperature:\t%.3f\n", peak); fprintf(stdout, "avg temperature:\t%.3f\n", avg); free_dvector(power); free_dvector(temp); if (fp) fclose(fp); }
/* * this is the metric function used for the floorplanning. * in order to enable a different metric, just change the * return statement of this function to return an appropriate * metric. The current metric used is a linear function of * area (A), temperature (T) and wire length (W): * lambdaA * A + lambdaT * T + lambdaW * W * thermal model and power density are passed as parameters * since temperature is used in the metric. */ double flp_evaluate_metric(flp_t *flp, RC_model_t *model, double *power, double lambdaA, double lambdaT, double lambdaW) { double tmax, area, wire_length, width, height, aspect; double *temp; temp = hotspot_vector(model); populate_R_model(model, flp); steady_state_temp(model, power, temp); tmax = find_max_temp(model, temp); area = get_total_area(flp); wire_length = get_wire_metric(flp); width = get_total_width(flp); height = get_total_height(flp); if (width > height) aspect = width / height; else aspect = height / width; free_dvector(temp); /* can return any arbitrary function of area, tmax and wire_length */ return (lambdaA * area + lambdaT * tmax + lambdaW * wire_length); }
/* * main function - reads instantaneous power values (in W) from a trace * file (e.g. "gcc.ptrace") and outputs instantaneous temperature values (in C) to * a trace file("gcc.ttrace"). also outputs steady state temperature values * (including those of the internal nodes of the model) onto stdout. the * trace files are 2-d matrices with each column representing a functional * functional block and each row representing a time unit(sampling_intvl). * columns are tab-separated and each row is a separate line. the first * line contains the names of the functional blocks. the order in which * the columns are specified doesn't have to match that of the floorplan * file. */ int main(int argc, char **argv) { int i, j, idx, base = 0, count = 0, n = 0; int num, size, lines = 0, do_transient = TRUE; char **names; double *vals; /* trace file pointers */ FILE *pin, *tout = NULL; /* floorplan */ flp_t *flp; /* hotspot temperature model */ RC_model_t *model; /* instantaneous temperature and power values */ double *temp = NULL, *power; double total_power = 0.0; /* steady state temperature and power values */ double *overall_power, *steady_temp; /* thermal model configuration parameters */ thermal_config_t thermal_config; /* global configuration parameters */ global_config_t global_config; /* table to hold options and configuration */ str_pair table[MAX_ENTRIES]; /* variables for natural convection iterations */ int natural = 0; double avg_sink_temp = 0; int natural_convergence = 0; double r_convec_old; if (!(argc >= 5 && argc % 2)) { usage(argc, argv); return 1; } size = parse_cmdline(table, MAX_ENTRIES, argc, argv); global_config_from_strs(&global_config, table, size); /* no transient simulation, only steady state */ if(!strcmp(global_config.t_outfile, NULLFILE)) do_transient = FALSE; /* read configuration file */ if (strcmp(global_config.config, NULLFILE)) size += read_str_pairs(&table[size], MAX_ENTRIES, global_config.config); /* * earlier entries override later ones. so, command line options * have priority over config file */ size = str_pairs_remove_duplicates(table, size); /* get defaults */ thermal_config = default_thermal_config(); /* modify according to command line / config file */ thermal_config_add_from_strs(&thermal_config, table, size); /* if package model is used, run package model */ if (((idx = get_str_index(table, size, "package_model_used")) >= 0) && !(table[idx].value==0)) { if (thermal_config.package_model_used) { avg_sink_temp = thermal_config.ambient + SMALL_FOR_CONVEC; natural = package_model(&thermal_config, table, size, avg_sink_temp); if (thermal_config.r_convec<R_CONVEC_LOW || thermal_config.r_convec>R_CONVEC_HIGH) printf("Warning: Heatsink convection resistance is not realistic, double-check your package settings...\n"); } } /* dump configuration if specified */ if (strcmp(global_config.dump_config, NULLFILE)) { size = global_config_to_strs(&global_config, table, MAX_ENTRIES); size += thermal_config_to_strs(&thermal_config, &table[size], MAX_ENTRIES-size); /* prefix the name of the variable with a '-' */ dump_str_pairs(table, size, global_config.dump_config, "-"); } /* initialization: the flp_file global configuration * parameter is overridden by the layer configuration * file in the grid model when the latter is specified. */ flp = read_flp(global_config.flp_file, FALSE); /* allocate and initialize the RC model */ model = alloc_RC_model(&thermal_config, flp); populate_R_model(model, flp); if (do_transient) populate_C_model(model, flp); #if VERBOSE > 2 debug_print_model(model); #endif /* allocate the temp and power arrays */ /* using hotspot_vector to internally allocate any extra nodes needed */ if (do_transient) temp = hotspot_vector(model); power = hotspot_vector(model); steady_temp = hotspot_vector(model); overall_power = hotspot_vector(model); /* set up initial instantaneous temperatures */ if (do_transient && strcmp(model->config->init_file, NULLFILE)) { if (!model->config->dtm_used) /* initial T = steady T for no DTM */ read_temp(model, temp, model->config->init_file, FALSE); else /* initial T = clipped steady T with DTM */ read_temp(model, temp, model->config->init_file, TRUE); } else if (do_transient) /* no input file - use init_temp as the common temperature */ set_temp(model, temp, model->config->init_temp); /* n is the number of functional blocks in the block model * while it is the sum total of the number of functional blocks * of all the floorplans in the power dissipating layers of the * grid model. */ if (model->type == BLOCK_MODEL) n = model->block->flp->n_units; else if (model->type == GRID_MODEL) { for(i=0; i < model->grid->n_layers; i++) if (model->grid->layers[i].has_power) n += model->grid->layers[i].flp->n_units; } else fatal("unknown model type\n"); if(!(pin = fopen(global_config.p_infile, "r"))) fatal("unable to open power trace input file\n"); if(do_transient && !(tout = fopen(global_config.t_outfile, "w"))) fatal("unable to open temperature trace file for output\n"); /* names of functional units */ names = alloc_names(MAX_UNITS, STR_SIZE); if(read_names(pin, names) != n) fatal("no. of units in floorplan and trace file differ\n"); /* header line of temperature trace */ if (do_transient) write_names(tout, names, n); /* read the instantaneous power trace */ vals = dvector(MAX_UNITS); while ((num=read_vals(pin, vals)) != 0) { if(num != n) fatal("invalid trace file format\n"); /* permute the power numbers according to the floorplan order */ if (model->type == BLOCK_MODEL) for(i=0; i < n; i++) power[get_blk_index(flp, names[i])] = vals[i]; else for(i=0, base=0, count=0; i < model->grid->n_layers; i++) { if(model->grid->layers[i].has_power) { for(j=0; j < model->grid->layers[i].flp->n_units; j++) { idx = get_blk_index(model->grid->layers[i].flp, names[count+j]); power[base+idx] = vals[count+j]; } count += model->grid->layers[i].flp->n_units; } base += model->grid->layers[i].flp->n_units; } /* compute temperature */ if (do_transient) { /* if natural convection is considered, update transient convection resistance first */ if (natural) { avg_sink_temp = calc_sink_temp(model, temp); natural = package_model(model->config, table, size, avg_sink_temp); populate_R_model(model, flp); } /* for the grid model, only the first call to compute_temp * passes a non-null 'temp' array. if 'temp' is NULL, * compute_temp remembers it from the last non-null call. * this is used to maintain the internal grid temperatures * across multiple calls of compute_temp */ if (model->type == BLOCK_MODEL || lines == 0) compute_temp(model, power, temp, model->config->sampling_intvl); else compute_temp(model, power, NULL, model->config->sampling_intvl); /* permute back to the trace file order */ if (model->type == BLOCK_MODEL) for(i=0; i < n; i++) vals[i] = temp[get_blk_index(flp, names[i])]; else for(i=0, base=0, count=0; i < model->grid->n_layers; i++) { if(model->grid->layers[i].has_power) { for(j=0; j < model->grid->layers[i].flp->n_units; j++) { idx = get_blk_index(model->grid->layers[i].flp, names[count+j]); vals[count+j] = temp[base+idx]; } count += model->grid->layers[i].flp->n_units; } base += model->grid->layers[i].flp->n_units; } /* output instantaneous temperature trace */ write_vals(tout, vals, n); } /* for computing average */ if (model->type == BLOCK_MODEL) for(i=0; i < n; i++) overall_power[i] += power[i]; else for(i=0, base=0; i < model->grid->n_layers; i++) { if(model->grid->layers[i].has_power) for(j=0; j < model->grid->layers[i].flp->n_units; j++) overall_power[base+j] += power[base+j]; base += model->grid->layers[i].flp->n_units; } lines++; } if(!lines) fatal("no power numbers in trace file\n"); /* for computing average */ if (model->type == BLOCK_MODEL) for(i=0; i < n; i++) { overall_power[i] /= lines; //overall_power[i] /=150; //reduce input power for natural convection total_power += overall_power[i]; } else for(i=0, base=0; i < model->grid->n_layers; i++) { if(model->grid->layers[i].has_power) for(j=0; j < model->grid->layers[i].flp->n_units; j++) { overall_power[base+j] /= lines; total_power += overall_power[base+j]; } base += model->grid->layers[i].flp->n_units; } /* natural convection r_convec iteration, for steady-state only */ natural_convergence = 0; if (natural) { /* natural convection is used */ while (!natural_convergence) { r_convec_old = model->config->r_convec; /* steady state temperature */ steady_state_temp(model, overall_power, steady_temp); avg_sink_temp = calc_sink_temp(model, steady_temp) + SMALL_FOR_CONVEC; natural = package_model(model->config, table, size, avg_sink_temp); populate_R_model(model, flp); if (avg_sink_temp > MAX_SINK_TEMP) fatal("too high power for a natural convection package -- possible thermal runaway\n"); if (fabs(model->config->r_convec-r_convec_old)<NATURAL_CONVEC_TOL) natural_convergence = 1; } } else /* natural convection is not used, no need for iterations */ /* steady state temperature */ steady_state_temp(model, overall_power, steady_temp); /* print steady state results */ fprintf(stdout, "Unit\tSteady(Kelvin)\n"); dump_temp(model, steady_temp, "stdout"); /* dump steady state temperatures on to file if needed */ if (strcmp(model->config->steady_file, NULLFILE)) dump_temp(model, steady_temp, model->config->steady_file); /* for the grid model, optionally dump the most recent * steady state temperatures of the grid cells */ if (model->type == GRID_MODEL && strcmp(model->config->grid_steady_file, NULLFILE)) dump_steady_temp_grid(model->grid, model->config->grid_steady_file); #if VERBOSE > 2 if (model->type == BLOCK_MODEL) { if (do_transient) { fprintf(stdout, "printing temp...\n"); dump_dvector(temp, model->block->n_nodes); } fprintf(stdout, "printing steady_temp...\n"); dump_dvector(steady_temp, model->block->n_nodes); } else { if (do_transient) { fprintf(stdout, "printing temp...\n"); dump_dvector(temp, model->grid->total_n_blocks + EXTRA); } fprintf(stdout, "printing steady_temp...\n"); dump_dvector(steady_temp, model->grid->total_n_blocks + EXTRA); } #endif /* cleanup */ fclose(pin); if (do_transient) fclose(tout); delete_RC_model(model); free_flp(flp, FALSE); if (do_transient) free_dvector(temp); free_dvector(power); free_dvector(steady_temp); free_dvector(overall_power); free_names(names); free_dvector(vals); return 0; }
/* * floorplanning using simulated annealing. * precondition: flp is a pre-allocated placeholder. * returns the number of compacted blocks in the selected * floorplan */ int floorplan(flp_t *flp, flp_desc_t *flp_desc, RC_model_t *model, double *power) { NPE_t *expr, *next, *best; /* Normalized Polish Expressions */ tree_node_stack_t *stack; /* for NPE evaluation */ tree_node_t *root; /* shape curve tree */ double cost, new_cost, best_cost, sum_cost, T, Tcold; int i, steps, downs, n, rejects, compacted, rim_blocks = 0; int original_n = flp->n_units; int wrap_l2; /* to maintain the order of power values during * the compaction/shifting around of blocks */ double *tpower = hotspot_vector(model); /* shortcut */ flp_config_t cfg = flp_desc->config; /* * make the rim strips disappear for slicing tree * purposes. can be restored at the end */ if (cfg.model_rim) flp->n_units = (flp->n_units - 2) / 3; /* wrap L2 around? */ wrap_l2 = FALSE; if (cfg.wrap_l2 && !strcasecmp(flp_desc->units[flp_desc->n_units-1].name, cfg.l2_label)) { wrap_l2 = TRUE; /* make L2 disappear too */ flp_desc->n_units--; flp->n_units -= (L2_ARMS+1); } /* initialization */ expr = NPE_get_initial(flp_desc); stack = new_tree_node_stack(); init_rand(); /* convert NPE to flp */ root = tree_from_NPE(flp_desc, stack, expr); /* compacts too small dead blocks */ compacted = tree_to_flp(root, flp, TRUE, cfg.compact_ratio); /* update the tpower vector according to the compaction */ trim_hotspot_vector(model, tpower, power, flp->n_units, compacted); free_tree(root); if(wrap_l2) flp_wrap_l2(flp, flp_desc); if(cfg.model_rim) rim_blocks = flp_wrap_rim(flp, cfg.rim_thickness); resize_thermal_model(model, flp->n_units); #if VERBOSE > 2 print_flp(flp); #endif cost = flp_evaluate_metric(flp, model, tpower, cfg.lambdaA, cfg.lambdaT, cfg.lambdaW); /* restore the compacted blocks */ restore_dead_blocks(flp, flp_desc, compacted, wrap_l2, cfg.model_rim, rim_blocks); best = NPE_duplicate(expr); /* best till now */ best_cost = cost; /* simulated annealing */ steps = 0; /* initial annealing temperature */ T = -cfg.Davg / log(cfg.P0); /* * final annealing temperature - we stop when there * are fewer than (1-cfg.Rreject) accepts. * of those accepts, assuming half are uphill moves, * we want the temperature so that the probability * of accepting uphill moves is as low as * (1-cfg.Rreject)/2. */ Tcold = -cfg.Davg / log ((1.0 - cfg.Rreject) / 2.0); #if VERBOSE > 0 fprintf(stdout, "initial cost: %g\tinitial T: %g\tfinal T: %g\n", cost, T, Tcold); #endif /* * stop annealing if temperature has cooled down enough or * max no. of iterations have been tried */ while (T >= Tcold && steps < cfg.Nmax) { /* shortcut */ n = cfg.Kmoves * flp->n_units; i = downs = rejects = 0; sum_cost = 0; /* try enough total or downhill moves per T */ while ((i < 2 * n) && (downs < n)) { next = make_random_move(expr); /* convert NPE to flp */ root = tree_from_NPE(flp_desc, stack, next); compacted = tree_to_flp(root, flp, TRUE, cfg.compact_ratio); /* update the tpower vector according to the compaction */ trim_hotspot_vector(model, tpower, power, flp->n_units, compacted); free_tree(root); if(wrap_l2) flp_wrap_l2(flp, flp_desc); if(cfg.model_rim) rim_blocks = flp_wrap_rim(flp, cfg.rim_thickness); resize_thermal_model(model, flp->n_units); #if VERBOSE > 2 print_flp(flp); #endif new_cost = flp_evaluate_metric(flp, model, tpower, cfg.lambdaA, cfg.lambdaT, cfg.lambdaW); restore_dead_blocks(flp, flp_desc, compacted, wrap_l2, cfg.model_rim, rim_blocks); #if VERBOSE > 1 fprintf(stdout, "count: %d\tdowns: %d\tcost: %g\t", i, downs, new_cost); #endif /* move accepted? */ if (new_cost < cost || /* downhill always accepted */ /* boltzmann probability function */ rand_fraction() < exp(-(new_cost-cost)/T)) { free_NPE(expr); expr = next; /* downhill move */ if (new_cost < cost) { downs++; /* found new best */ if (new_cost < best_cost) { free_NPE(best); best = NPE_duplicate(expr); best_cost = new_cost; } } #if VERBOSE > 1 fprintf(stdout, "accepted\n"); #endif cost = new_cost; sum_cost += cost; } else { /* rejected move */ rejects++; free_NPE(next); #if VERBOSE > 1 fprintf(stdout, "rejected\n"); #endif } i++; } #if VERBOSE > 0 fprintf(stdout, "step: %d\tT: %g\ttries: %d\taccepts: %d\trejects: %d\t", steps, T, i, (i-rejects), rejects); fprintf(stdout, "avg. cost: %g\tbest cost: %g\n", (i-rejects)?(sum_cost / (i-rejects)):sum_cost, best_cost); #endif /* stop annealing if there are too little accepts */ if(((double)rejects/i) > cfg.Rreject) break; /* annealing schedule */ T *= cfg.Rcool; steps++; } /* best floorplan found */ root = tree_from_NPE(flp_desc, stack, best); #if VERBOSE > 0 { int pos = min_area_pos(root->curve); print_tree_relevant(root, pos, flp_desc); } #endif compacted = tree_to_flp(root, flp, TRUE, cfg.compact_ratio); /* update the power vector according to the compaction */ trim_hotspot_vector(model, power, power, flp->n_units, compacted); free_tree(root); /* restore L2 and rim */ if(wrap_l2) { flp_wrap_l2(flp, flp_desc); flp_desc->n_units++; } if(cfg.model_rim) rim_blocks = flp_wrap_rim(flp, cfg.rim_thickness); resize_thermal_model(model, flp->n_units); #if VERBOSE > 2 print_flp(flp); #endif free_NPE(expr); free_NPE(best); free_tree_node_stack(stack); free_dvector(tpower); /* * return the number of blocks compacted finally * so that any deallocator can take care of memory * accordingly. */ return (original_n - flp->n_units); }
/* steady state temperature */ void steady_state_temp(RC_model_t *model, double *power, double *temp) { // if (model->type == BLOCK_MODEL) // steady_state_temp_block(model->block, power, temp); // else if (model->type == GRID_MODEL) // steady_state_temp_grid(model->grid, power, temp); // else fatal("unknown model type\n"); int leak_convg_true = 0; int leak_iter = 0; int n, base=0; //int idx=0; double blk_height, blk_width; int i, j, k; double *d_temp = NULL; double *temp_old = NULL; double *power_new = NULL; double d_max=0.0; if (model->type == BLOCK_MODEL) { n = model->block->flp->n_units; printf("n is here : %d\n\n",n); if (model->config->leakage_used) { // if considering leakage-temperature loop d_temp = hotspot_vector(model); temp_old = hotspot_vector(model); power_new = hotspot_vector(model); for (leak_iter=0;(!leak_convg_true)&&(leak_iter<=LEAKAGE_MAX_ITER);leak_iter++){ for(i=0; i < n; i++) { blk_height = model->block->flp->units[i].height; blk_width = model->block->flp->units[i].width; power_new[i] = power[i] + calc_leakage(model->config->leakage_mode,blk_height,blk_width,temp[i]); temp_old[i] = temp[i]; //copy temp before update } steady_state_temp_block(model->block, power_new, temp); // update temperature d_max = 0.0; for(i=0; i < n; i++) { d_temp[i] = temp[i] - temp_old[i]; //temperature increase due to leakage if (d_temp[i]>d_max) { d_max = d_temp[i]; } } if (d_max < LEAK_TOL) {// check convergence leak_convg_true = 1; } if (d_max > TEMP_HIGH && leak_iter > 1) {// check to make sure d_max is not "nan" (esp. in natural convection) fatal("temperature is too high, possible thermal runaway. Double-check power inputs and package settings.\n"); } } free(d_temp); free(temp_old); free(power_new); /* if no convergence after max number of iterations, thermal runaway */ if (!leak_convg_true) fatal("too many iterations before temperature-leakage convergence -- possible thermal runaway\n"); } else // if leakage-temperature loop is not considered steady_state_temp_block(model->block, power, temp); } else if (model->type == GRID_MODEL) { if (model->config->leakage_used) { // if considering leakage-temperature loop d_temp = hotspot_vector(model); temp_old = hotspot_vector(model); power_new = hotspot_vector(model); for (leak_iter=0;(!leak_convg_true)&&(leak_iter<=LEAKAGE_MAX_ITER);leak_iter++){ for(k=0, base=0; k < model->grid->n_layers; k++) { if(model->grid->layers[k].has_power) for(j=0; j < model->grid->layers[k].flp->n_units; j++) { blk_height = model->grid->layers[k].flp->units[j].height; blk_width = model->grid->layers[k].flp->units[j].width; power_new[base+j] = power[base+j] + calc_leakage(model->config->leakage_mode,blk_height,blk_width,temp[base+j]); temp_old[base+j] = temp[base+j]; //copy temp before update } base += model->grid->layers[k].flp->n_units; } steady_state_temp_grid(model->grid, power_new, temp); d_max = 0.0; for(k=0, base=0; k < model->grid->n_layers; k++) { if(model->grid->layers[k].has_power) for(j=0; j < model->grid->layers[k].flp->n_units; j++) { d_temp[base+j] = temp[base+j] - temp_old[base+j]; //temperature increase due to leakage if (d_temp[base+j]>d_max) d_max = d_temp[base+j]; } base += model->grid->layers[k].flp->n_units; } if (d_max < LEAK_TOL) {// check convergence leak_convg_true = 1; } if (d_max > TEMP_HIGH && leak_iter > 0) {// check to make sure d_max is not "nan" (esp. in natural convection) fatal("temperature is too high, possible thermal runaway. Double-check power inputs and package settings.\n"); } } free(d_temp); free(temp_old); free(power_new); /* if no convergence after max number of iterations, thermal runaway */ if (!leak_convg_true) fatal("too many iterations before temperature-leakage convergence -- possible thermal runaway\n"); } else // if leakage-temperature loop is not considered steady_state_temp_grid(model->grid, power, temp); } else fatal("unknown model type\n"); }
/* main function for the floorplanner */ int main(int argc, char **argv) { flp_desc_t *flp_desc; flp_t *flp; RC_model_t *model; double *power; thermal_config_t thermal_config; flp_config_t flp_config; global_config_t global_config; str_pair table[MAX_ENTRIES]; int size, compacted; if (!(argc >= 7 && argc % 2)) { usage(argc, argv); return 1; } size = parse_cmdline(table, MAX_ENTRIES, argc, argv); global_config_from_strs(&global_config, table, size); /* read configuration file */ if (strcmp(global_config.config, NULLFILE)) size += read_str_pairs(&table[size], MAX_ENTRIES, global_config.config); /* * in the str_pair 'table', earlier entries override later ones. * so, command line options have priority over config file */ size = str_pairs_remove_duplicates(table, size); /* get defaults */ thermal_config = default_thermal_config(); flp_config = default_flp_config(); /* modify according to command line / config file */ thermal_config_add_from_strs(&thermal_config, table, size); flp_config_add_from_strs(&flp_config, table, size); /* dump configuration if specified */ if (strcmp(global_config.dump_config, NULLFILE)) { size = global_config_to_strs(&global_config, table, MAX_ENTRIES); size += thermal_config_to_strs(&thermal_config, &table[size], MAX_ENTRIES-size); size += flp_config_to_strs(&flp_config, &table[size], MAX_ENTRIES-size); /* prefix the name of the variable with a '-' */ dump_str_pairs(table, size, global_config.dump_config, "-"); } /* HotFloorplan currently uses the block model and does not * support the grid model. */ if (!strcasecmp(thermal_config.model_type, GRID_MODEL_STR)) fatal("HotFloorplan doesn't support the grid model\n"); /* description of the functional blocks to be floorplanned */ flp_desc = read_flp_desc(global_config.flp_desc, &flp_config); /* * just an empty frame with blocks' names. * block positions not known yet. */ flp = flp_placeholder(flp_desc); /* temperature model */ model = alloc_RC_model(&thermal_config, flp); /* input power vector */ power = hotspot_vector(model); read_power(model, power, global_config.power_in); /* main floorplanning routine */ compacted = floorplan(flp, flp_desc, model, power); /* * print the finally selected floorplan in a format that can * be understood by tofig.pl (which converts it to a FIG file) */ print_flp_fig(flp); /* print the floorplan statistics */ if (flp_config.wrap_l2 && !strcasecmp(flp_desc->units[flp_desc->n_units-1].name, flp_config.l2_label)) print_flp_stats(flp, model, flp_config.l2_label, global_config.power_in, global_config.flp_desc); /* print the wire delays between blocks */ print_wire_delays(flp, thermal_config.base_proc_freq); /* also output the floorplan to a file readable by hotspot */ dump_flp(flp, global_config.flp_out, FALSE); free_flp_desc(flp_desc); delete_RC_model(model); free_dvector(power); /* while deallocating, free the compacted blocks too */ free_flp(flp, compacted); return 0; }