Beispiel #1
0
/* 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);
}
Beispiel #2
0
/* 
 * 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);
}
Beispiel #3
0
/* 
 * 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;
}
Beispiel #4
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");	
}
Beispiel #6
0
/* 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;
}