Esempio n. 1
0
void alloc_ivector_and_copy_int_list(t_linked_int ** list_head_ptr,
		int num_items, struct s_ivec *ivec, t_linked_int ** free_list_head_ptr) {

	/* Allocates an integer vector with num_items elements and copies the       *
	 * integers from the list pointed to by list_head (of which there must be   *
	 * num_items) over to it.  The int_list is then put on the free list, and   *
	 * the list_head_ptr is set to NULL.                                        */

	t_linked_int *linked_int, *list_head;
	int i, *list;

	list_head = *list_head_ptr;

	if (num_items == 0) { /* Empty list. */
		ivec->nelem = 0;
		ivec->list = NULL;

		if (list_head != NULL ) {
			vpr_throw(VPR_ERROR_UNKNOWN, __FILE__, __LINE__, 
				"alloc_ivector_and_copy_int_list: Copied %d elements, "
						"but list at %p contains more.\n", num_items,
				(void *) list_head);			
		}
		return;
	}

	ivec->nelem = num_items;
	list = (int *) my_malloc(num_items * sizeof(int));
	ivec->list = list;
	linked_int = list_head;

	for (i = 0; i < num_items - 1; i++) {
		list[i] = linked_int->data;
		linked_int = linked_int->next;
	}

	list[num_items - 1] = linked_int->data;

	if (linked_int->next != NULL ) {
		vpr_throw(VPR_ERROR_UNKNOWN, __FILE__, __LINE__, 
			"Error in alloc_ivector_and_copy_int_list:\n Copied %d elements, "
			"but list at %p contains more.\n", num_items,
				(void *) list_head);		
	}

	linked_int->next = *free_list_head_ptr;
	*free_list_head_ptr = list_head;
	*list_head_ptr = NULL;
}
Esempio n. 2
0
int my_irand(int imax) {

	/* Creates a random integer between 0 and imax, inclusive.  i.e. [0..imax] */

	int ival;

	/* current_random = (current_random * IA + IC) % IM; */
	current_random = current_random * IA + IC; /* Use overflow to wrap */
	ival = current_random & (IM - 1); /* Modulus */
	ival = (int) ((float) ival * (float) (imax + 0.999) / (float) IM);

#ifdef CHECK_RAND
	if ((ival < 0) || (ival > imax)) {
		if (ival == imax + 1) {
			/* Due to random floating point rounding, sometimes above calculation gives number greater than ival by 1 */
			ival = imax;
		} else {
			vpr_throw(VPR_ERROR_UNKNOWN, __FILE__, __LINE__, 
				"Bad value in my_irand, imax = %d  ival = %d\n", imax, ival);			
		}
	}
#endif

	return (ival);
}
Esempio n. 3
0
char *my_fgets(char *buf, int max_size, FILE * fp) {
	/* Get an input line, update the line number and cut off *
	 * any comment part.  A \ at the end of a line with no   *
	 * comment part (#) means continue. my_fgets should give * 
	 * identical results for Windows (\r\n) and Linux (\n)   *
	 * newlines, since it replaces each carriage return \r   *
	 * by a newline character \n.  Returns NULL after EOF.	 */

	char ch;
	int i;

	cont = 0; /* line continued? */
	file_line_number++; /* global variable */

	for (i = 0; i < max_size - 1; i++) { /* Keep going until the line finishes or the buffer is full */

		ch = fgetc(fp);

		if (feof(fp)) { /* end of file */
			if (i == 0) {
				return NULL ; /* required so we can write while (my_fgets(...) != NULL) */
			} else { /* no newline before end of file - last line must be returned */
				buf[i] = '\0';
				return buf;
			}
		}

		if (ch == '#') { /* comment */
			buf[i] = '\0';
			while ((ch = fgetc(fp)) != '\n' && !feof(fp))
				; /* skip the rest of the line */
			return buf;
		}

		if (ch == '\r' || ch == '\n') { /* newline (cross-platform) */
			if (i != 0 && buf[i - 1] == '\\') { /* if \ at end of line, line continued */
				cont = 1;
				buf[i - 1] = '\n'; /* May need this for tokens */
				buf[i] = '\0';
			} else {
				buf[i] = '\n';
				buf[i + 1] = '\0';
			}
			return buf;
		}

		buf[i] = ch; /* copy character into the buffer */

	}

	/* Buffer is full but line has not terminated, so error */
	vpr_throw(VPR_ERROR_UNKNOWN, __FILE__, __LINE__, 
		"Error on line %d -- line is too long for input buffer.\n"
		"All lines must be at most %d characters long.\n",
			file_line_number, BUFSIZE - 2);	
	return NULL;
}
Esempio n. 4
0
/* Performs linear interpolation or extrapolation on the set of (x,y) values specified by the xy_map.
   A requested x value is passed in, and we return the interpolated/extrapolated y value at this requested value of x.
   Meant for maps where both key and element are numbers.
   This is specifically enforced by the explicit instantiations below this function. i.e. only templates
   using those types listed in the explicit instantiations below are allowed */
template<typename X, typename Y> Y linear_interpolate_or_extrapolate(INP std::map<X,Y> *xy_map, INP X requested_x){
	Y result;

	/* the intention of this function is to interpolate/extrapolate. we can't do so with less than 2 values in the xy_map */
	if (xy_map->size() < 2){
		vpr_throw(VPR_ERROR_UNKNOWN, __FILE__, __LINE__, 
			"linear_interpolate_or_extrapolate: cannot interpolate/extrapolate based on less than 2 (x,y) pairs");		
	}

	if (xy_map->count(requested_x) == 1){
		/* requested x already exists in the x,y map */
		result = (*xy_map)[requested_x];
	} else {
		/* requested x does not exist in the x,y map. need to interpolate/extrapolate */

		typename std::map<X,Y>::const_iterator it;
		double x_low, x_high, y_low, y_high;
		double slope, reference_y, delta_x;

		/* get first x greater than the one requested */
		it = xy_map->upper_bound(requested_x);

		if(it == xy_map->end()){
			/* need to extrapolate to higher x. based on the y values at the two largest x values */
			it--;
			x_high = (double)it->first;
			y_high = (double)it->second;
			it--;
			x_low = (double)it->first;
			y_low = (double)it->second;
		} else if (it == xy_map->begin()){
			/* need to extrapolate to lower x. based on the y values at the two smallest x */
			x_low = (double)it->first;
			y_low = (double)it->second;
			it++;
			x_high = (double)it->first;
			y_high = (double)it->second;
		} else {
			/* need to interpolate. based on y values at x just above/below
			   the one we want */
			x_high = (double)it->first;
			y_high = (double)it->second;
			it--;
			x_low = (double)it->first;
			y_low = (double)it->second;
		}

		slope = (y_high - y_low) / (x_high - x_low);
		reference_y = y_low;
		delta_x = (double)requested_x - x_low;
		result = (Y)(reference_y + (slope * delta_x));
	}

	return result;
}
Esempio n. 5
0
void *my_malloc_impl(size_t size, const char* const file, const int line) {
	void *ret;
	if (size == 0) {
		return NULL ;
	}

	if ((ret = malloc(size)) == NULL ) {
		vpr_throw(VPR_ERROR_UNKNOWN, file, line,
			"Error:  Unable to malloc memory.  Aborting.\n");		
	}
	return (ret);
}
Esempio n. 6
0
int my_atoi(const char *str) {

	/* Returns the integer represented by the first part of the character       *
	 * string.                                              */

	if (str[0] < '0' || str[0] > '9') {
		if (!(str[0] == '-' && str[1] >= '0' && str[1] <= '9')) {
			vpr_throw(VPR_ERROR_UNKNOWN, __FILE__, __LINE__, 
				"expected number instead of '%s'.\n", str);			
		}
	}
	return (atoi(str));
}
Esempio n. 7
0
/* Uses global var 'out_file_prefix' */
FILE *my_fopen(const char *fname, const char *flag, int prompt) {
	FILE *fp;
	size_t Len;
	char *new_fname = NULL;
	char prompt_filename[256];

	file_line_number = 0;

	/* Appends a prefix string for output files */
	if (out_file_prefix) {
		if (strchr(flag, 'w')) {
			Len = 1; /* NULL char */
			Len += strlen(out_file_prefix);
			Len += strlen(fname);
			new_fname = (char *) my_malloc(Len * sizeof(char));
			strcpy(new_fname, out_file_prefix);
			strcat(new_fname, fname);
			fname = new_fname;
		}
	}

	if (prompt) {
		int check_num_of_entered_values = scanf("%s", prompt_filename);
		while (getchar() != '\n')
			;

		while (check_num_of_entered_values != 1) {
			vpr_printf_error(__FILE__, __LINE__,
					"Was expecting one file name to be entered, with no spaces. You have entered %d parameters. Please try again: \n",
					check_num_of_entered_values);
			check_num_of_entered_values = scanf("%s", prompt_filename);
		}
		fname = prompt_filename;
	}

	if (NULL == (fp = fopen(fname, flag))) {
		vpr_throw(VPR_ERROR_UNKNOWN, __FILE__, __LINE__, 
			"Error opening file %s for %s access: %s.\n", fname, flag, strerror(errno));		
	}

	if (new_fname)
		free(new_fname);

	return (fp);
}
Esempio n. 8
0
float my_frand(void) {

	/* Creates a random float between 0 and 1.  i.e. [0..1).        */

	float fval;
	int ival;

	current_random = current_random * IA + IC; /* Use overflow to wrap */
	ival = current_random & (IM - 1); /* Modulus */
	fval = (float) ival / (float) IM;

#ifdef CHECK_RAND
	if ((fval < 0) || (fval > 1.)) {
		vpr_throw(VPR_ERROR_UNKNOWN, __FILE__, __LINE__, 
			"Bad value in my_frand, fval = %g\n", fval);		
	}
#endif

	return (fval);
}
Esempio n. 9
0
void *my_realloc_impl(void *ptr, size_t size, const char* const file, const int line) {
	void *ret;

	if (size <= 0) {
		vpr_printf_warning(file, line,
				"reallocating of size <= 0.\n");
	}

	ret = realloc(ptr, size);
	if (NULL == ret) {
		vpr_printf_error(file, line,
				"Unable to realloc memory. Aborting. "
				"ptr=%p, Size=%d.\n", ptr, (int) size);
		if (ptr == NULL ) {
			vpr_printf_error(file, line,
					"my_realloc: ptr == NULL. Aborting.\n");
		}
			vpr_throw(VPR_ERROR_UNKNOWN, file, line,
					"Unable to realloc memory. Aborting. ptr=%p, Size=%d.\n", ptr, (int) size);				
	}
	return (ret);
}
/* Checks that options don't conflict and that 
 * options aren't specified that may conflict */
void CheckOptions(INP t_options Options, INP bool TimingEnabled) {
	bool TimingPlacer;
	bool TimingRouter;
	bool default_flow;

	const struct s_TokenPair *Cur;
	enum e_OptionBaseToken Yes;

	default_flow = (Options.Count[OT_ROUTE] == 0
			&& Options.Count[OT_PLACE] == 0 && Options.Count[OT_PACK] == 0
			&& Options.Count[OT_TIMING_ANALYZE_ONLY_WITH_NET_DELAY] == 0);

	/* Check that all filenames were given */
	if ((NULL == Options.CircuitName) || (NULL == Options.ArchFile)) {
		vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__, 
				"Not enough args. Need at least 'vpr <archfile> <circuit_name>'.\n");
	}

	/* Check that options aren't over specified */
	Cur = OptionBaseTokenList;
	while (Cur->Str) {
		if (Options.Count[Cur->Enum] > 1) {
			vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__, 
					"Parameter '%s' was specified more than once on command line.\n", Cur->Str);
		}
		++Cur;
	}

	/* Todo: Add in checks for packer   */

	/* Check for conflicting parameters and determine if placer and 
	 * router are on. */

	if (Options.Count[OT_TIMING_ANALYZE_ONLY_WITH_NET_DELAY]
			&& (Options.Count[OT_PACK] || Options.Count[OT_PLACE]
					|| Options.Count[OT_ROUTE])) {
		vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__, 
				"'cluster'/'route'/'place', and 'timing_analysis_only_with_net_delay' are mutually exclusive flags..\n");
	}

	/* If placing and timing is enabled, default to a timing placer */
	TimingPlacer =((Options.Count[OT_PLACE] || default_flow) && TimingEnabled);
	if (Options.Count[OT_PLACE_ALGORITHM] > 0) {
		if ((PATH_TIMING_DRIVEN_PLACE != Options.PlaceAlgorithm)
				&& (NET_TIMING_DRIVEN_PLACE != Options.PlaceAlgorithm)) {
			/* Turn off the timing placer if they request a different placer */
			TimingPlacer = false;
		}
	}

	/* If routing and timing is enabled, default to a timing router */
	TimingRouter =((Options.Count[OT_ROUTE] || default_flow) && TimingEnabled);
	if (Options.Count[OT_ROUTER_ALGORITHM] > 0) {
		if (TIMING_DRIVEN != Options.RouterAlgorithm) {
			/* Turn off the timing router if they request a different router */
			TimingRouter = false;
		}
	}

	/* If a dump of routing resource structs was requested then routing should have been specified at a
	   fixed channel width */
	if (Options.Count[OT_DUMP_RR_STRUCTS_FILE] && !Options.Count[OT_ROUTE_CHAN_WIDTH]){
		vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
				"-route_chan_width option must be specified if dumping rr structs is requested (-dump_rr_structs_file option)\n");
	}

	Yes = OT_BASE_UNKNOWN;
	if (Options.Count[OT_SEED] > 0) {
		Yes = OT_SEED;
	}
	if (Options.Count[OT_INNER_NUM] > 0) {
		Yes = OT_INNER_NUM;
	}
	if (Options.Count[OT_INIT_T] > 0) {
		Yes = OT_INIT_T;
	}
	if (Options.Count[OT_ALPHA_T] > 0) {
		Yes = OT_ALPHA_T;
	}
	if (Options.Count[OT_EXIT_T] > 0) {
		Yes = OT_EXIT_T;
	}
	if (Options.Count[OT_FIX_PINS] > 0) {
		Yes = OT_FIX_PINS;
	}
	if (Options.Count[OT_PLACE_ALGORITHM] > 0) {
		Yes = OT_PLACE_ALGORITHM;
	}
	if (Options.Count[OT_PLACE_COST_EXP] > 0) {
		Yes = OT_PLACE_COST_EXP;
	}
	if (Options.Count[OT_PLACE_CHAN_WIDTH] > 0) {
		Yes = OT_PLACE_CHAN_WIDTH;
	}
	if (Options.Count[OT_ENABLE_TIMING_COMPUTATIONS] > 0) {
		Yes = OT_ENABLE_TIMING_COMPUTATIONS;
	}
	if (Options.Count[OT_BLOCK_DIST] > 0) {
		Yes = OT_BLOCK_DIST;
	}
	/* Make sure if place is off none of those options were given */
	if ((Options.Count[OT_PLACE] == 0) && !default_flow
			&& (Yes < OT_BASE_UNKNOWN)) {
		Cur = OptionBaseTokenList;
		while (Cur->Str) {
			if (Yes == Cur->Enum) {
				vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__, 
						"Option '%s' is not allowed when placement is not run.\n", Cur->Str);
			}
			++Cur;
		}
	}

	Yes = OT_BASE_UNKNOWN;
	if (Options.Count[OT_TIMING_TRADEOFF] > 0) {
		Yes = OT_TIMING_TRADEOFF;
	}
	if (Options.Count[OT_RECOMPUTE_CRIT_ITER] > 0) {
		Yes = OT_RECOMPUTE_CRIT_ITER;
	}
	if (Options.Count[OT_INNER_LOOP_RECOMPUTE_DIVIDER] > 0) {
		Yes = OT_INNER_LOOP_RECOMPUTE_DIVIDER;
	}
	if (Options.Count[OT_TD_PLACE_EXP_FIRST] > 0) {
		Yes = OT_TD_PLACE_EXP_FIRST;
	}
	if (Options.Count[OT_TD_PLACE_EXP_LAST] > 0) {
		Yes = OT_TD_PLACE_EXP_LAST;
	}
	/* Make sure if place is off none of those options were given */
	if ((false == TimingPlacer) && (Yes < OT_BASE_UNKNOWN)) {
		Cur = OptionBaseTokenList;
		while (Cur->Str) {
			if (Yes == Cur->Enum) {
				vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__, 
						"Option '%s' is not allowed when timing placement is not used.\n", Cur->Str);
			}
			++Cur;
		}
	}

	Yes = OT_BASE_UNKNOWN;
	if (Options.Count[OT_ROUTE_TYPE] > 0) {
		Yes = OT_ROUTE_TYPE;
	}
	if (Options.Count[OT_ROUTE_CHAN_WIDTH] > 0) {
		Yes = OT_ROUTE_CHAN_WIDTH;
	}
	if (Options.Count[OT_ROUTER_ALGORITHM] > 0) {
		Yes = OT_ROUTER_ALGORITHM;
	}
	if (Options.Count[OT_MAX_ROUTER_ITERATIONS] > 0) {
		Yes = OT_MAX_ROUTER_ITERATIONS;
	}
	if (Options.Count[OT_INITIAL_PRES_FAC] > 0) {
		Yes = OT_INITIAL_PRES_FAC;
	}
	if (Options.Count[OT_FIRST_ITER_PRES_FAC] > 0) {
		Yes = OT_FIRST_ITER_PRES_FAC;
	}
	if (Options.Count[OT_PRES_FAC_MULT] > 0) {
		Yes = OT_PRES_FAC_MULT;
	}
	if (Options.Count[OT_ACC_FAC] > 0) {
		Yes = OT_ACC_FAC;
	}
	if (Options.Count[OT_BB_FACTOR] > 0) {
		Yes = OT_BB_FACTOR;
	}
	if (Options.Count[OT_BASE_COST_TYPE] > 0) {
		Yes = OT_BASE_COST_TYPE;
	}
	if (Options.Count[OT_BEND_COST] > 0) {
		Yes = OT_BEND_COST;
	}
	if (Options.Count[OT_BASE_COST_TYPE] > 0) {
		Yes = OT_BASE_COST_TYPE;
	}
	if (Options.Count[OT_ASTAR_FAC] > 0) {
		Yes = OT_ASTAR_FAC;
	}
	Yes = OT_BASE_UNKNOWN;
	if (Options.Count[OT_MAX_CRITICALITY] > 0) {
		Yes = OT_MAX_CRITICALITY;
	}
	if (Options.Count[OT_CRITICALITY_EXP] > 0) {
		Yes = OT_CRITICALITY_EXP;
	}
	/* Make sure if timing router is off none of those options were given */
	if ((false == TimingRouter) && (Yes < OT_BASE_UNKNOWN)) {
		Cur = OptionBaseTokenList;
		while (Cur->Str) {
			if (Yes == Cur->Enum) {
				vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__, 
						"Option '%s' is not allowed when timing router is not used.\n", Cur->Str);
			}
			++Cur;
		}
	}
}
Esempio n. 11
0
void CheckSetup(INP enum e_operation Operation,
		INP struct s_placer_opts PlacerOpts,
		INP struct s_annealing_sched AnnealSched,
		INP struct s_router_opts RouterOpts,
		INP struct s_det_routing_arch RoutingArch, INP t_segment_inf * Segments,
		INP t_timing_inf Timing, INP t_chan_width_dist Chans) {
	int i;
	int Tmp;

	if ((GLOBAL == RouterOpts.route_type)
			&& ((TIMING_DRIVEN == RouterOpts.router_algorithm)||(TIMING_DRIVEN_CONR == RouterOpts.router_algorithm))) {

		vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__, 
				"The global router does not support timing-drvien routing.\n");
	}

	if ((GLOBAL == RouterOpts.route_type)
			&& (BOUNDING_BOX_PLACE != PlacerOpts.place_algorithm)) {

		/* Works, but very weird.  Can't optimize timing well, since you're
		 * not doing proper architecture delay modelling. */
		vpr_printf_warning(__FILE__, __LINE__, 
				"Using global routing with timing-driven placement. "
				"This is allowed, but strange, and circuit speed will suffer.\n");
	}

	if ((false == Timing.timing_analysis_enabled)
			&& ((PlacerOpts.place_algorithm == NET_TIMING_DRIVEN_PLACE)
					|| (PlacerOpts.place_algorithm == PATH_TIMING_DRIVEN_PLACE))) {

		/* May work, not tested */
		vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__, 
				"Timing analysis must be enabled for timing-driven placement.\n");
	}

	if (!PlacerOpts.doPlacement && (USER == PlacerOpts.pad_loc_type)) {
		vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__, 
				"A pad location file requires that placement is enabled.\n");
	}

	if (RouterOpts.doRouting) {
		if ((TIMING_DRIVEN == RouterOpts.router_algorithm||(TIMING_DRIVEN_CONR == RouterOpts.router_algorithm))
				&& (false == Timing.timing_analysis_enabled)) {
			vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__, 
					"Cannot perform timing-driven routing when timing analysis is disabled.\n");
		}

		if ((false == Timing.timing_analysis_enabled)
				&& (DEMAND_ONLY != RouterOpts.base_cost_type)) {
			vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__, 
					"base_cost_type must be demand_only when timing analysis is disabled.\n");
		}
	}

	if ((TIMING_ANALYSIS_ONLY == Operation)
			&& (false == Timing.timing_analysis_enabled)) {
		vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
				"-timing_analyze_only_with_net_delay option requires that timing analysis not be disabled.\n");
	}

	if (DETAILED == RouterOpts.route_type) {
		if ((Chans.chan_x_dist.type != UNIFORM)
				|| (Chans.chan_y_dist.type != UNIFORM)
				|| (Chans.chan_x_dist.peak != Chans.chan_y_dist.peak)
				|| (Chans.chan_x_dist.peak != Chans.chan_width_io)) {
			vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__, 
					"Detailed routing currently only supported on FPGAs with all channels of equal width.\n");
		}
	}

	for (i = 0; i < RoutingArch.num_segment; ++i) {
		Tmp = Segments[i].arch_opin_switch;
		if (false == g_arch_switch_inf[Tmp].buffered) {
			vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__, 
					"arch_opin_switch (#%d) of segment type #%d is not buffered.\n", Tmp, i);
		}
	}

	if (UNI_DIRECTIONAL == RoutingArch.directionality) {
		if ((RouterOpts.fixed_channel_width != NO_FIXED_CHANNEL_WIDTH)
				&& (RouterOpts.fixed_channel_width % 2 > 0)) {
			vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__, 
					"Routing channel width must be even for unidirectional.\n");
		}
		if ((PlacerOpts.place_chan_width != NO_FIXED_CHANNEL_WIDTH)
				&& (PlacerOpts.place_chan_width % 2 > 0)) {
			vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__, 
					"Place channel width must be even for unidirectional.\n");
		}
	}
}