示例#1
0
/* make a random move out of the above	*/
NPE_t *make_random_move(NPE_t *expr)
{
	int i, move, count = 0, done = FALSE, m3_count;
	NPE_t *copy = NPE_duplicate(expr);

	while (!done && count < MAX_MOVES) {
		/* choose one of three moves	*/
		move = rand_upto(3);
		switch(move) {
			case 0:	/* swap adjacent units	*/
				/* leave the unit last in the NPE	*/
				i = rand_upto(expr->n_units-1);
				#if VERBOSE > 2
				fprintf(stdout, "making M1 at %d\n", expr->unit_pos[i]);
				#endif
				NPE_swap_units(copy, expr->unit_pos[i]);
				done = TRUE;
				break;

			case 1:	/* invert an arbitrary chain	*/
				i = rand_upto(expr->n_chains);
				#if VERBOSE > 2
				fprintf(stdout, "making M2 at %d\n", expr->chain_pos[i]);
				#endif
				NPE_invert_chain(copy, expr->chain_pos[i]);
				done = TRUE;
				break;

			case 2:	/* swap a unit and an adjacent cut_type	*/
				m3_count = 0; 
				while (!done && m3_count < MAX_MOVES) {
					i = rand_upto(expr->n_flips);
					#if VERBOSE > 2
					fprintf(stdout, "making M3 at %d\n", expr->flip_pos[i]);
					#endif
					done = NPE_swap_cut_unit(copy, expr->flip_pos[i]);
					m3_count++;
				}
				break;

			default:
				fatal("unknown move type\n");
				break;
		}
		count++;
	}

	if (count == MAX_MOVES) {
		char msg[STR_SIZE];
		sprintf(msg, "tried %d moves, now giving up\n", MAX_MOVES); 
		fatal(msg);
	}

	return copy;
}
示例#2
0
文件: flp.c 项目: JensRasche/HotSpot
/* 
 * 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);
}