Пример #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);
}
Пример #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);
}
Пример #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;
}