Ejemplo n.º 1
0
void
free_route_structs(t_ivec ** fb_opins_used_locally)
{

/* Frees the temporary storage needed only during the routing.  The  *
 * final routing result is not freed.                                */
    int i;

    free(heap + 1);
    free(route_bb);

    heap = NULL;		/* Defensive coding:  crash hard if I use these. */
    route_bb = NULL;

    for(i = 0; i < num_blocks; i++)
	{
	    free_ivec_vector(fb_opins_used_locally[i], 0,
			     block[i].type->num_class - 1);
	}
    free(fb_opins_used_locally);

/* NB:  Should use my chunk_malloc for tptr, hptr, and mod_ptr structures. *
 * I could free everything except the tptrs at the end then.               */

}
Ejemplo n.º 2
0
void
free_saved_routing(struct s_trace **best_routing,
		   t_ivec ** saved_clb_opins_used_locally)
{

/* Frees the data structures needed to save a routing.                     */
    int i;

    free(best_routing);
    for(i = 0; i < num_blocks; i++)
	{
	    free_ivec_vector(saved_clb_opins_used_locally[i], 0,
			     block[i].type->num_class - 1);
	}
    free(saved_clb_opins_used_locally);
}
Ejemplo n.º 3
0
static void free_routing_structs(struct s_router_opts router_opts,
		struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
		t_timing_inf timing_inf) {
	int i;
	free_rr_graph();

	free_rr_node_route_structs();
	free_route_structs();
	free_trace_structs();

	free_timing_driven_route_structs(pin_criticality, sink_order,
			rt_node_of_sink);
	
	if (clb_opins_used_locally != NULL) {
		for (i = 0; i < num_blocks; i++) {
			free_ivec_vector(clb_opins_used_locally[i], 0,
					block[i].type->num_class - 1);
		}
		free(clb_opins_used_locally);
		clb_opins_used_locally = NULL;
	}
}
void build_rr_graph (enum e_route_type route_type, struct s_det_routing_arch
         det_routing_arch, struct s_segment_inf *segment_inf, t_timing_inf 
         timing_inf) {

/* Builds the routing resource graph needed for routing.  Does all the   *
 * necessary allocation and initialization.  If route_type is DETAILED   *
 * then the routing graph built is for detailed routing, otherwise it is *
 * for GLOBAL routing.                                                   */

 int nodes_per_clb, nodes_per_pad, nodes_per_chan;
 int **rr_node_indices;
 int Fc_output, Fc_input, Fc_pad;
 int **pads_to_tracks;
 struct s_ivec **tracks_to_clb_ipin, *tracks_to_pads;

/* [0..pins_per_clb-1][0..3][0..Fc_output-1].  List of tracks this pin *
 * connects to.  Second index is the side number (see pr.h).  If a pin *
 * is not an output or input, respectively, or doesn't connect to      *
 * anything on this side, the [ipin][iside][0] element is OPEN.        */

 int ***clb_opin_to_tracks, ***clb_ipin_to_tracks;
 t_seg_details *seg_details_x, *seg_details_y;  /* [0 .. nodes_per_chan-1] */


 nodes_per_clb = num_class + pins_per_clb;
 nodes_per_pad = 4 * io_rat;    /* SOURCE, SINK, OPIN, and IPIN */

 if (route_type == GLOBAL) {
    nodes_per_chan = 1;
 }
 else {
    nodes_per_chan = chan_width_x[0];
 }

 seg_details_x = alloc_and_load_seg_details (nodes_per_chan, segment_inf, 
                 det_routing_arch.num_segment, nx);

 seg_details_y = alloc_and_load_seg_details (nodes_per_chan, segment_inf, 
                 det_routing_arch.num_segment, ny);

#ifdef DEBUG
 dump_seg_details (seg_details_x, nodes_per_chan, "x.echo");
 dump_seg_details (seg_details_y, nodes_per_chan, "y.echo");
#endif

/* To set up the routing graph I need to choose an order for the rr_indices. *
 * For each (i,j) slot in the FPGA, the index order is [source+sink]/pins/   *
 * chanx/chany. The dummy source and sink are ordered by class number or pad *
 * number; the pins are ordered by pin number or pad number, and the channel *
 * segments are ordered by track number.  Track 1 is closest to the "owning" *
 * block; i.e. it is towards the left of y-chans and the bottom of x-chans.  *
 *                                                                           *
 * The maximize cache effectiveness, I put all the rr_nodes associated with  *
 * a block together (this includes the "owned" channel segments).  I start   *
 * at (0,0) (empty), go to (1,0), (2,0) ... (0,1) and so on.                 */

/* NB:  Allocates data structures for fast index computations -- more than *
 * just rr_node_indices are allocated by this routine.                     */

 rr_node_indices = alloc_and_load_rr_node_indices (nodes_per_clb, 
         nodes_per_pad, nodes_per_chan, seg_details_x, seg_details_y);

 num_rr_nodes = rr_node_indices[nx+1][ny+1];

 if (det_routing_arch.Fc_type == ABSOLUTE) {
    Fc_output = min (det_routing_arch.Fc_output, nodes_per_chan);
    Fc_input = min (det_routing_arch.Fc_input, nodes_per_chan);
    Fc_pad = min (det_routing_arch.Fc_pad, nodes_per_chan);
 }
 else {    /* FRACTIONAL */
    Fc_output = nint (nodes_per_chan * det_routing_arch.Fc_output);
    Fc_output = max (1, Fc_output);
    Fc_input = nint (nodes_per_chan * det_routing_arch.Fc_input);
    Fc_input = max (1, Fc_input);
    Fc_pad = nint (nodes_per_chan * det_routing_arch.Fc_pad);
    Fc_pad = max (1, Fc_pad);
 }

 alloc_and_load_switch_block_conn (nodes_per_chan, 
        det_routing_arch.switch_block_type);

 clb_opin_to_tracks = alloc_and_load_clb_pin_to_tracks (DRIVER, nodes_per_chan,
        Fc_output);

 clb_ipin_to_tracks = alloc_and_load_clb_pin_to_tracks (RECEIVER,
        nodes_per_chan, Fc_input);
 
 tracks_to_clb_ipin = alloc_and_load_tracks_to_clb_ipin (nodes_per_chan,
        Fc_input, clb_ipin_to_tracks);

 pads_to_tracks = alloc_and_load_pads_to_tracks (nodes_per_chan, Fc_pad);
 
 tracks_to_pads = alloc_and_load_tracks_to_pads (pads_to_tracks, 
          nodes_per_chan, Fc_pad);

 rr_edge_done = (boolean *) my_calloc (num_rr_nodes, sizeof (boolean));

 alloc_and_load_rr_graph (rr_node_indices, clb_opin_to_tracks,
       tracks_to_clb_ipin, pads_to_tracks, tracks_to_pads, Fc_output,
       Fc_input, Fc_pad, nodes_per_chan, route_type, det_routing_arch, 
       seg_details_x, seg_details_y);

 free (rr_edge_done);
 free_rr_node_indices (rr_node_indices);
 free_matrix3 (clb_opin_to_tracks, 0, pins_per_clb-1, 0, 3, 0, sizeof(int));
 free_matrix3 (clb_ipin_to_tracks, 0, pins_per_clb-1, 0, 3, 0, sizeof(int));
 free_ivec_matrix (tracks_to_clb_ipin, 0, nodes_per_chan-1, 0, 3);
 free_ivec_vector (tracks_to_pads, 0, nodes_per_chan-1);
 free_matrix (pads_to_tracks, 0, io_rat-1, 0, sizeof(int));
 free_switch_block_conn (nodes_per_chan);
 free_edge_list_hard (&free_edge_list_head);

 save_segment_type_and_length_info (seg_details_x, nodes_per_chan,
                                    seg_details_y, nodes_per_chan);

 free_seg_details (seg_details_x, nodes_per_chan);
 free_seg_details (seg_details_y, nodes_per_chan);

 add_rr_graph_C_from_switches (timing_inf.ipin_cblock_C); 

/* dump_rr_graph ("rr_graph.echo"); */
 check_rr_graph (route_type, det_routing_arch.num_switch);
}
Ejemplo n.º 5
0
void place_and_route(enum e_operation operation,
		struct s_placer_opts placer_opts, char *place_file, char *net_file,
		char *arch_file, char *route_file,
		struct s_annealing_sched annealing_sched,
		struct s_router_opts router_opts,
		struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
		t_timing_inf timing_inf, t_chan_width_dist chan_width_dist,
		struct s_model *models,
		t_direct_inf *directs, int num_directs) {

	/* This routine controls the overall placement and routing of a circuit. */
	char msg[BUFSIZE];
	int width_fac, i;
	boolean success, Fc_clipped;
	float **net_delay = NULL;
	t_slack * slacks = NULL;
	t_chunk net_delay_ch = {NULL, 0, NULL};

	/*struct s_linked_vptr *net_delay_chunk_list_head;*/
	t_ivec **clb_opins_used_locally = NULL; /* [0..num_blocks-1][0..num_class-1] */
	int max_pins_per_clb;
	clock_t begin, end;

	Fc_clipped = FALSE;

	max_pins_per_clb = 0;
	for (i = 0; i < num_types; i++) {
		if (type_descriptors[i].num_pins > max_pins_per_clb) {
			max_pins_per_clb = type_descriptors[i].num_pins;
		}
	}

	if (placer_opts.place_freq == PLACE_NEVER) {
		/* Read the placement from a file */
		read_place(place_file, net_file, arch_file, nx, ny, num_blocks, block);
		sync_grid_to_blocks(num_blocks, block, nx, ny, grid);
	} else {
		assert(
				(PLACE_ONCE == placer_opts.place_freq) || (PLACE_ALWAYS == placer_opts.place_freq));
		begin = clock();
		try_place(placer_opts, annealing_sched, chan_width_dist, router_opts,
				det_routing_arch, segment_inf, timing_inf, directs, num_directs);
		print_place(place_file, net_file, arch_file);
		end = clock();
#ifdef CLOCKS_PER_SEC
		vpr_printf(TIO_MESSAGE_INFO, "Placement took %g seconds.\n", (float)(end - begin) / CLOCKS_PER_SEC);
#else
		vpr_printf(TIO_MESSAGE_INFO, "Placement took %g seconds.\n", (float)(end - begin) / CLK_PER_SEC);
#endif
	}
	begin = clock();
	post_place_sync(num_blocks, block);

	fflush(stdout);

	if (!router_opts.doRouting)
		return;

	width_fac = router_opts.fixed_channel_width;

	/* If channel width not fixed, use binary search to find min W */
	if (NO_FIXED_CHANNEL_WIDTH == width_fac) {
		g_solution_inf.channel_width = binary_search_place_and_route(placer_opts, place_file, net_file,
				arch_file, route_file, router_opts.full_stats,
				router_opts.verify_binary_search, annealing_sched, router_opts,
				det_routing_arch, segment_inf, timing_inf, chan_width_dist,
				models, directs, num_directs);
	} else {
		g_solution_inf.channel_width = width_fac;
		if (det_routing_arch.directionality == UNI_DIRECTIONAL) {
			if (width_fac % 2 != 0) {
				vpr_printf(TIO_MESSAGE_ERROR, "in pack_place_and_route.c: Given odd chan width (%d) for udsd architecture.\n",
						width_fac);
				exit(1);
			}
		}
		/* Other constraints can be left to rr_graph to check since this is one pass routing */

		/* Allocate the major routing structures. */

		clb_opins_used_locally = alloc_route_structs();

		slacks = alloc_and_load_timing_graph(timing_inf);
		net_delay = alloc_net_delay(&net_delay_ch, clb_net,
					num_nets);

		success = try_route(width_fac, router_opts, det_routing_arch,
				segment_inf, timing_inf, net_delay, slacks, chan_width_dist,
				clb_opins_used_locally, &Fc_clipped, directs, num_directs);

		if (Fc_clipped) {
			vpr_printf(TIO_MESSAGE_WARNING, "Fc_output was too high and was clipped to full (maximum) connectivity.\n");
		}

		if (success == FALSE) {
			vpr_printf(TIO_MESSAGE_INFO, "Circuit is unrouteable with a channel width factor of %d.\n", width_fac);
			vpr_printf(TIO_MESSAGE_INFO, "\n");
			sprintf(msg, "Routing failed with a channel width factor of %d. ILLEGAL routing shown.", width_fac);
		}

		else {
			check_route(router_opts.route_type, det_routing_arch.num_switch, clb_opins_used_locally);
			get_serial_num();

			vpr_printf(TIO_MESSAGE_INFO, "Circuit successfully routed with a channel width factor of %d.\n", width_fac);
			vpr_printf(TIO_MESSAGE_INFO, "\n");

			routing_stats(router_opts.full_stats, router_opts.route_type,
					det_routing_arch.num_switch, segment_inf,
					det_routing_arch.num_segment, det_routing_arch.R_minW_nmos,
					det_routing_arch.R_minW_pmos,
					det_routing_arch.directionality,
					timing_inf.timing_analysis_enabled, net_delay, slacks);

			print_route(route_file);

			if (getEchoEnabled() && isEchoFileEnabled(E_ECHO_ROUTING_SINK_DELAYS)) {
				print_sink_delays(getEchoFileName(E_ECHO_ROUTING_SINK_DELAYS));
			}

			sprintf(msg, "Routing succeeded with a channel width factor of %d.\n\n",
					width_fac);
		}

		init_draw_coords(max_pins_per_clb);
		update_screen(MAJOR, msg, ROUTING, timing_inf.timing_analysis_enabled);
		

		if (timing_inf.timing_analysis_enabled) {
			assert(slacks->slack);

			if (getEchoEnabled() && isEchoFileEnabled(E_ECHO_POST_FLOW_TIMING_GRAPH)) {
				print_timing_graph_as_blif (getEchoFileName(E_ECHO_POST_FLOW_TIMING_GRAPH),
						models);
			}

			free_timing_graph(slacks);

			assert(net_delay);
			free_net_delay(net_delay, &net_delay_ch);
		}

		fflush(stdout);
	}
	if (clb_opins_used_locally != NULL) {
		for (i = 0; i < num_blocks; i++) {
			free_ivec_vector(clb_opins_used_locally[i], 0,
					block[i].type->num_class - 1);
		}
		free(clb_opins_used_locally);
		clb_opins_used_locally = NULL;
	}
	if(GetPostSynthesisOption())
		{
			verilog_writer();
		}
	end = clock();
#ifdef CLOCKS_PER_SEC
	vpr_printf(TIO_MESSAGE_INFO, "Routing took %g seconds.\n", (float) (end - begin) / CLOCKS_PER_SEC);
#else
	vpr_printf(TIO_MESSAGE_INFO, "Routing took %g seconds.\n", (float)(end - begin) / CLK_PER_SEC);
#endif

	/*WMF: cleaning up memory usage */

	/*	if (g_heap_free_head)
		free(g_heap_free_head);
	if (g_trace_free_head)
		free(g_trace_free_head);
	if (g_linked_f_pointer_free_head)
		free(g_linked_f_pointer_free_head);*/
}