Пример #1
0
/* populate connectivity info	*/
void flp_populate_connects(flp_t *flp, FILE *fp)
{
	char str1[LINE_SIZE], str2[LINE_SIZE]; 
	char name1[STR_SIZE], name2[STR_SIZE];
	/* dummy fields	*/
	double f1, f2, f3, f4, f5, f6;
	double wire_density;
	char *ptr;
	int x, y, temp;

	/* initialize wire_density	*/
	for(x=0; x < flp->n_units; x++)
		for(y=0; y < flp->n_units; y++)
			flp->wire_density[x][y] = 0.0;

	fseek(fp, 0, SEEK_SET);
	while(!feof(fp)) {
		fgets(str1, LINE_SIZE, fp);
		if (feof(fp))
			break;
		strcpy(str2, str1);

		/* ignore comments and empty lines	*/
		ptr = strtok(str1, " \r\t\n");
		if (!ptr || ptr[0] == '#')
			continue;

		/* lines with unit positions	*/
		if (sscanf(str2, "%s%lf%lf%lf%lf%lf%lf", name1, &f1, &f2, &f3, &f4, &f5, &f6) == 7 ||
		  	/* flp_desc like lines. ignore them	*/
		  	sscanf(str2, "%s%lf%lf%lf%d", name1, &f1, &f2, &f3, &temp) == 5)
			continue;

		 /* lines with connectivity info	*/
		else if (sscanf(str2, "%s%s%lf", name1, name2, &wire_density) == 3) {
			x = get_blk_index(flp, name1);
			y = get_blk_index(flp, name2);

			if (x == y)
				fatal("block connected to itself?\n");

			if (!flp->wire_density[x][y] && !flp->wire_density[y][x])
				flp->wire_density[x][y] = flp->wire_density[y][x] = wire_density;
			else if((flp->wire_density[x][y] != flp->wire_density[y][x]) ||
			        (flp->wire_density[x][y] != wire_density)) {
				sprintf(str2, "wrong connectivity information for blocks %s and %s\n", 
				        name1, name2);
				fatal(str2);
			}
		} else 
		  	fatal("invalid floorplan file format\n");
	} /* end while	*/
}
Пример #2
0
/* 
 * read temperature vector alloced using 'hotspot_vector' from 'file'
 * which was dumped using 'dump_vector'. values are clipped to thermal
 * threshold based on 'clip'
 */ 
void read_temp(flp_t *flp, double *temp, char *file, int clip)
{
	int i, idx;
	double max=0, val;
	char str[STR_SIZE], name[STR_SIZE];
	FILE *fp = fopen (file, "r");
	if (!fp) {
		sprintf (str,"error: %s could not be opened for reading\n", file);
		fatal(str);
	}	

	/* find max temp on the chip	*/
	for (i=0; i < flp->n_units; i++) {
		fgets(str, STR_SIZE, fp);
		if (feof(fp))
			fatal("not enough lines in temperature file\n");
		if (sscanf(str, "%s%lf", name, &val) != 2)
			fatal("invalid temperature file format\n");
		idx = get_blk_index(flp, name);
		if (idx >= 0)
			temp[idx] = val;
		else	/* since get_blk_index calls fatal, the line below cannot be reached	*/
			fatal ("unit in temperature file not found in floorplan\n");
		if (temp[idx] > max)
			max = temp[idx];
	}

	/* internal node temperatures	*/	
	for (i=0; i < EXTRA; i++) {
		fgets(str, STR_SIZE, fp);
		if (feof(fp))
			fatal("not enough lines in temperature file\n");
		if (sscanf(str, "%s%lf", name, &val) != 2)
			fatal("invalid temperature file format\n");
		sprintf(str, "inode_%d", i);
		if (strcasecmp(str, name))
			fatal("invalid temperature file format\n");
		temp[i+flp->n_units] = val;	
	}

	fclose(fp);	

	/* clipping	*/
	if (clip && (max > thermal_threshold)) {
		/* if max has to be brought down to thermal_threshold, 
		 * (w.r.t the ambient) what is the scale down factor?
		 */
		double factor = (thermal_threshold - ambient) / (max - ambient);
	
		/* scale down all temperature differences (from ambient) by the same factor	*/
		for (i=0; i < flp->n_units + EXTRA; i++)
			temp[i] = (temp[i]-ambient)*factor + ambient;
	}
}
/*
 * read power vector alloced using 'hotspot_vector' from 'file'
 * which was dumped using 'dump_power'.
 */
void read_power_block (block_model_t *model, double *power, char *file)
{
	flp_t *flp = model->flp;
	int idx;
	double val;
	char *ptr, str1[LINE_SIZE], str2[LINE_SIZE], name[STR_SIZE];
	FILE *fp;

	if (!strcasecmp(file, "stdin"))
		fp = stdin;
	else
		fp = fopen (file, "r");

	if (!fp) {
		sprintf (str1,"error: %s could not be opened for reading\n", file);
		fatal(str1);
	}
	while(!feof(fp)) {
		fgets(str1, LINE_SIZE, fp);
		if (feof(fp))
			break;
		strcpy(str2, str1);

		/* ignore comments and empty lines	*/
		ptr = strtok(str1, " \r\t\n");
		if (!ptr || ptr[0] == '#')
			continue;

		if (sscanf(str2, "%s%lf", name, &val) != 2)
			fatal("invalid power file format\n");
		idx = get_blk_index(flp, name);
		if (idx >= 0)
			power[idx] = val;
		else	/* since get_blk_index calls fatal, the line below cannot be reached	*/
			fatal ("unit in power file not found in floorplan\n");
	}
	if(fp != stdin)
		fclose(fp);
}
Пример #4
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;
}
/*
 * read temperature vector alloced using 'hotspot_vector' from 'file'
 * which was dumped using 'dump_temp'. values are clipped to thermal
 * threshold based on 'clip'
 */
void read_temp_block(block_model_t *model, double *temp, char *file, int clip)
{
	/*	shortcuts	*/
	flp_t *flp = model->flp;
	double thermal_threshold = model->config.thermal_threshold;
	double ambient = model->config.ambient;

	int i, n, idx;
	double max=0, val;
	char *ptr, str1[LINE_SIZE], str2[LINE_SIZE];
	char name[STR_SIZE], format[STR_SIZE];
	FILE *fp;

	if (!strcasecmp(file, "stdin"))
		fp = stdin;
	else
		fp = fopen (file, "r");

	if (!fp) {
		sprintf (str1,"error: %s could not be opened for reading\n", file);
		fatal(str1);
	}

	/* temperatures of the different layers	*/
	for (n=0; n < NL; n++) {
		switch(n)
		{
			case 0:
					strcpy(format,"%s%lf");
					break;
			case IFACE:
					strcpy(format,"iface_%s%lf");
					break;
			case HSP:
					strcpy(format,"hsp_%s%lf");
					break;
			case HSINK:
					strcpy(format,"hsink_%s%lf");
					break;
			default:
					fatal("unknown layer\n");
					break;
		}
		for (i=0; i < flp->n_units; i++) {
			fgets(str1, LINE_SIZE, fp);
			if (feof(fp))
				fatal("not enough lines in temperature file\n");
			strcpy(str2, str1);

			/* ignore comments and empty lines	*/
			ptr = strtok(str1, " \r\t\n");
			if (!ptr || ptr[0] == '#') {
				i--;
				continue;
			}

			if (sscanf(str2, format, name, &val) != 2)
				fatal("invalid temperature file format\n");
			idx = get_blk_index(flp, name);
			if (idx >= 0)
				temp[idx + n*flp->n_units] = val;
			else	/* since get_blk_index calls fatal, the line below cannot be reached	*/
				fatal ("unit in temperature file not found in floorplan\n");

			/* find max temp on the chip	*/
			if (n == 0 && temp[idx] > max)
				max = temp[idx];
		}
	}

	/* internal node temperatures	*/
	for (i=0; i < EXTRA; i++) {
		fgets(str1, LINE_SIZE, fp);
		if (feof(fp))
			fatal("not enough lines in temperature file\n");
		strcpy(str2, str1);
		/* ignore comments and empty lines	*/
		ptr = strtok(str1, " \r\t\n");
		if (!ptr || ptr[0] == '#') {
			i--;
			continue;
		}
		if (sscanf(str2, "%s%lf", name, &val) != 2)
			fatal("invalid temperature file format\n");
		sprintf(str1, "inode_%d", i);
		if (strcasecmp(str1, name))
			fatal("invalid temperature file format\n");
		temp[i+NL*flp->n_units] = val;
	}

	fgets(str1, LINE_SIZE, fp);
	if (!feof(fp))
		fatal("too many lines in temperature file\n");

	if(fp != stdin)
		fclose(fp);

	/* clipping	*/
	if (clip && (max > thermal_threshold)) {
		/* if max has to be brought down to thermal_threshold,
		 * (w.r.t the ambient) what is the scale down factor?
		 */
		double factor = (thermal_threshold - ambient) / (max - ambient);

		/* scale down all temperature differences (from ambient) by the same factor	*/
		for (i=0; i < NL*flp->n_units + EXTRA; i++)
			temp[i] = (temp[i]-ambient)*factor + ambient;
	}
}