コード例 #1
0
void reserve_locally_used_opins (float pres_fac, boolean rip_up_local_opins,
          t_ivec **clb_opins_used_locally) {

/* If some subblock outputs are hooked directly to CLB outputs, then      *
 * some CLB outputs are occupied if their associated subblock is used     *
 * locally, even though the inter-CLB netlist does not say those outputs  *
 * have to connect to anything.  This is important when you have          *
 * logically equivalent outputs.  Code below makes sure any CLB outputs   *
 * that are used by being directly hooked to subblocks get properly       *
 * reserved.                                                              */

 int iblk, num_local_opin, inode, from_node, iconn, num_edges, to_node;
 int iclass, ipin;
 float cost;
 struct s_heap *heap_head_ptr;

 if (rip_up_local_opins) {
    for (iblk=0;iblk<num_blocks;iblk++) {
       for (iclass=0;iclass<num_class;iclass++) {
          num_local_opin = clb_opins_used_locally[iblk][iclass].nelem; 
                  /* Always 0 for pads and for RECEIVER (IPIN) classes */
          for (ipin=0;ipin<num_local_opin;ipin++) {
             inode = clb_opins_used_locally[iblk][iclass].list[ipin];
             adjust_one_rr_occ_and_pcost (inode, -1, pres_fac);
          }
       }
    }
 }     
 
 for (iblk=0;iblk<num_blocks;iblk++) {
    for (iclass=0;iclass<num_class;iclass++) {
       num_local_opin = clb_opins_used_locally[iblk][iclass].nelem; 
               /* Always 0 for pads and for RECEIVER (IPIN) classes */

       if (num_local_opin != 0) {  /* Have to reserve (use) some OPINs */
          from_node = rr_clb_source[iblk][iclass];
          num_edges = rr_node[from_node].num_edges;
          for (iconn=0;iconn<num_edges;iconn++) {
             to_node = rr_node[from_node].edges[iconn];
             cost = get_rr_cong_cost (to_node);
             node_to_heap (to_node, cost, OPEN, OPEN, 0., 0.);
          }

          for (ipin=0;ipin<num_local_opin;ipin++) {
             heap_head_ptr = get_heap_head ();
             inode = heap_head_ptr->index;
             adjust_one_rr_occ_and_pcost (inode, 1, pres_fac);
             clb_opins_used_locally[iblk][iclass].list[ipin] = inode;
             free_heap_data (heap_head_ptr);
          }

          empty_heap ();
       }
    }
 }
}
コード例 #2
0
ファイル: inc_route_bfs.c プロジェクト: RoshanGu/QT_Vtb2_v0.6
/**
 * Adapted from breadth_first_route_net() 
 */
boolean inc_breadth_first_route_net(int inet, float bend_cost, struct s_trace **old_trace_tail, int old_num_nets, struct s_router_opts *router_opts)
{
	/* Uses a maze routing (Dijkstra's) algorithm to route a net.  The net       *
	 * begins at the net output, and expands outward until it hits a target      *
	 * pin.  The algorithm is then restarted with the entire first wire segment  *
	 * included as part of the source this time.  For an n-pin net, the maze     *
	 * router is invoked n-1 times to complete all the connections.  Inet is     *
	 * the index of the net to be routed.  Bends are penalized by bend_cost      *
	 * (which is typically zero for detailed routing and nonzero only for global *
	 * routing), since global routes with lots of bends are tougher to detailed  *
	 * route (using a detailed router like SEGA).                                *
	 * If this routine finds that a net *cannot* be connected (due to a complete *
	 * lack of potential paths, rather than congestion), it returns FALSE, as    *
	 * routing is impossible on this architecture.  Otherwise it returns TRUE.   */

	int inode, prev_node, remaining_connections_to_sink;
	int itarget, target_inode, target_iblk;
	int max_mdist;
	float pcost, new_pcost;
	struct s_heap *current;
	struct s_trace *tptr;

	/* Rip up incremental trace only */
	inc_free_traceback(inet, old_trace_tail);

	inode = net_rr_terminals[inet][0];

	/* EH: Extract the assigned TB target */
	itarget = clb_net[inet].num_sinks;
	target_inode = net_rr_terminals[inet][itarget+1];
	assert(target_inode != OPEN);
	target_iblk = clb_net[inet].node_block[itarget+1];

	/* If LE symmetry enabled, and inet was local, add all CLB_OPINs 
	 * from other local nets onto heap too */
	if (router_opts->inc_le_symmetry && inet >= old_num_nets)
	{
		int num_sources, *sources;
		int i;
		boolean found = FALSE;
		num_sources = inc_local_OPINs(inet, old_num_nets, &sources);
		for (i = 0; i < num_sources; i++)
		{
			inc_breadth_first_add_inode_to_heap(sources[i]);
			if (sources[i] == inode)
				found = TRUE;
		}
		assert(found == TRUE);
		free(sources);
	}
	else
	{
		breadth_first_add_source_to_heap(inet);
	}
	/*mark_ends(inet); */

	tptr = trace_head[inet];
	remaining_connections_to_sink = 0;
	max_mdist = 0;

	/*    for(i = 1; i <= clb_net[inet].num_sinks; i++) */
	{			/* Need n-1 wires to connect n pins */
		breadth_first_expand_trace_segment(tptr,
				remaining_connections_to_sink);
		current = get_heap_head();

		if(current == NULL)
		{		/* Infeasible routing.  No possible path for net. */
			reset_path_costs();	/* Clean up before leaving. */
			return (FALSE);
		}

		inode = current->index;

		/*while(rr_node_route_inf[inode].target_flag == 0)*/
		while(rr_node_route_inf[inode].target_flag != target_iblk)
		{
			/*max_mdist = max(max_mdist, inc_traceback_len(current));*/
			pcost = rr_node_route_inf[inode].path_cost;
			new_pcost = current->cost;
			if(pcost > new_pcost)
			{	/* New path is lowest cost. */
				rr_node_route_inf[inode].path_cost = new_pcost;
				prev_node = current->u.prev_node;
				rr_node_route_inf[inode].prev_node = prev_node;
				rr_node_route_inf[inode].prev_edge =
					current->prev_edge;

				if(pcost > 0.99 * HUGE_POSITIVE_FLOAT)	/* First time touched. */
					add_to_mod_list(&rr_node_route_inf[inode].
							path_cost);

				inc_breadth_first_expand_neighbours(inode, new_pcost,
						inet, bend_cost);
			}

			free_heap_data(current);
			current = get_heap_head();

			if(current == NULL)
			{	/* Impossible routing. No path for net. */
				fprintf(stdout, "\ninet %d (vnet %d) failed", inet, clb_to_vpack_net_mapping[inet]);
				empty_heap();
				reset_path_costs();
				return (FALSE);
			}

			inode = current->index;
		}

		/*rr_node_route_inf[inode].target_flag--;*/	/* Connected to this SINK. */
		remaining_connections_to_sink =
			rr_node_route_inf[inode].target_flag;

		tptr = update_traceback(current, inet);
		free_heap_data(current);
	}

	/*printf("max_mdist = %d\n", max_mdist);*/
	empty_heap();
	reset_path_costs();

	return (TRUE);
}
コード例 #3
0
ファイル: route_breadth_first.c プロジェクト: SpectreV/VPR4.3
static boolean breadth_first_route_net (int inet, float bend_cost) {

/* Uses a maze routing (Dijkstra's) algorithm to route a net.  The net       *
 * begins at the net output, and expands outward until it hits a target      *
 * pin.  The algorithm is then restarted with the entire first wire segment  *
 * included as part of the source this time.  For an n-pin net, the maze     *
 * router is invoked n-1 times to complete all the connections.  Inet is     *
 * the index of the net to be routed.  Bends are penalized by bend_cost      *
 * (which is typically zero for detailed routing and nonzero only for global *
 * routing), since global routes with lots of bends are tougher to detailed  *
 * route (using a detailed router like SEGA).                                *
 * If this routine finds that a net *cannot* be connected (due to a complete *
 * lack of potential paths, rather than congestion), it returns FALSE, as    *
 * routing is impossible on this architecture.  Otherwise it returns TRUE.   */

 int i, inode, prev_node, remaining_connections_to_sink;
 float pcost, new_pcost;
 struct s_heap *current;
 struct s_trace *tptr;

 free_traceback (inet);
 breadth_first_add_source_to_heap (inet);
 mark_ends (inet);

 tptr = NULL;
 remaining_connections_to_sink = 0;

 for (i=1;i<net[inet].num_pins;i++) { /* Need n-1 wires to connect n pins */
    breadth_first_expand_trace_segment (tptr, remaining_connections_to_sink);
    current = get_heap_head();

    if (current == NULL) { /* Infeasible routing.  No possible path for net. */
       reset_path_costs ();  /* Clean up before leaving. */
       return (FALSE);
    }

    inode = current->index;

    while (rr_node_route_inf[inode].target_flag == 0) {
       pcost = rr_node_route_inf[inode].path_cost;
       new_pcost = current->cost;
       if (pcost > new_pcost) {      /* New path is lowest cost. */
          rr_node_route_inf[inode].path_cost = new_pcost;
          prev_node = current->u.prev_node;
          rr_node_route_inf[inode].prev_node = prev_node;
          rr_node_route_inf[inode].prev_edge = current->prev_edge;

          if (pcost > 0.99 * HUGE_FLOAT)          /* First time touched. */
             add_to_mod_list (&rr_node_route_inf[inode].path_cost);

          breadth_first_expand_neighbours (inode, new_pcost, inet, bend_cost);
       } 

       free_heap_data (current);
       current = get_heap_head ();

       if (current == NULL) { /* Impossible routing. No path for net. */
          reset_path_costs ();
          return (FALSE);
       } 
 
       inode = current->index;
    }
 
    rr_node_route_inf[inode].target_flag--;    /* Connected to this SINK. */
    remaining_connections_to_sink = rr_node_route_inf[inode].target_flag;
    tptr = update_traceback (current, inet);
    free_heap_data (current);
 }
 
 empty_heap ();
 reset_path_costs ();
 return (TRUE);
}
コード例 #4
0
static boolean
directed_search_route_net(int inet,
			  float pres_fac,
			  float astar_fac,
			  float bend_cost,
			  t_mst_edge ** mst)
{

/* Uses a maze routing (Dijkstra's) algorithm to route a net.  The net       *
 * begins at the net output, and expands outward until it hits a target      *
 * pin.  The algorithm is then restarted with the entire first wire segment  *
 * included as part of the source this time.  For an n-pin net, the maze     *
 * router is invoked n-1 times to complete all the connections.  Inet is     *
 * the index of the net to be routed.  Bends are penalized by bend_cost      *
 * (which is typically zero for detailed routing and nonzero only for global *
 * routing), since global routes with lots of bends are tougher to detailed  *
 * route (using a detailed router like SEGA).                                *
 * If this routine finds that a net *cannot* be connected (due to a complete *
 * lack of potential paths, rather than congestion), it returns FALSE, as    *
 * routing is impossible on this architecture.  Otherwise it returns TRUE.   */
/* WMF: This is the directed search (A-star) version of maze router. */

    int inode, remaining_connections_to_sink;
    int itarget, target_pin, target_node;
    struct s_heap *current;
    struct s_trace *new_route_start_tptr;
    float old_tcost, new_tcost, old_back_cost, new_back_cost;
	int highfanout_rlim;

	assert(mst);

/* Rip-up any old routing. */
    /* WMF: For the 1st router iteration trace_head[inet] is NULL, as it is 
     * my_calloc'ed in alloc_route_structs() so the following does nothing.
     * However, for subsequent iterations, trace_head[inet] contains the previous
     * ieration's routing for this net. */
    pathfinder_update_one_cost(trace_head[inet], -1, pres_fac);
    free_traceback(inet);	/* kills trace, and set the trace head and tail to NULL */

    /* adding the SOURCE node to the heap with correct total cost */
	target_pin = mst[inet][0].to_node;
    target_node = net_rr_terminals[inet][target_pin];
    directed_search_add_source_to_heap(inet, target_node, astar_fac);

    mark_ends(inet);

    remaining_connections_to_sink = 0;

    for(itarget = 0; itarget < clb_net[inet].num_sinks; itarget++)
	{
	    target_pin = mst[inet][itarget].to_node;
	    target_node = net_rr_terminals[inet][target_pin];

	    /*    printf ("Target #%d, pin number %d, target_node: %d.\n",
	     * itarget, target_pin, target_node);  */

	    /* WMF: since the heap has been emptied, need to restart the wavefront
	     * from the current partial routing, starting at the trace_head (SOURCE) 
	     * Note: in the 1st iteration, there is no trace (no routing at all for this net)
	     * i.e. trace_head[inet] == NULL (found in free_traceback() in route_common.c, 
	     * which is called before the routing of any net), 
	     * so this routine does nothing, but the heap does have the SOURCE node due 
	     * to directed_search_add_source_to_heap (inet) before the loop */
	    highfanout_rlim = directed_search_expand_trace_segment(trace_head[inet],
						 target_node, astar_fac, inet,
						 remaining_connections_to_sink);

	    current = get_heap_head();

	    if(current == NULL)
		{		/* Infeasible routing.  No possible path for net. */
		    reset_path_costs();	/* Clean up before leaving. */
		    return (FALSE);
		}

	    inode = current->index;

	    while(inode != target_node)
		{
		    old_tcost = rr_node_route_inf[inode].path_cost;
		    new_tcost = current->cost;

		    /* WMF: not needed if Vaughn initialized rr_node_route_inf[inode].backward_path_cost
		     * to HUGE_FLOAT along with rr_node_route_inf[inode].path_cost */
		    if(old_tcost > 0.99 * HUGE_FLOAT)	/* First time touched. */
			old_back_cost = HUGE_FLOAT;
		    else
			old_back_cost =
			    rr_node_route_inf[inode].backward_path_cost;

		    new_back_cost = current->backward_path_cost;

		    /* I only re-expand a node if both the "known" backward cost is lower  *
		     * in the new expansion (this is necessary to prevent loops from       *
		     * forming in the routing and causing havoc) *and* the expected total  *
		     * cost to the sink is lower than the old value.  Different R_upstream *
		     * values could make a path with lower back_path_cost less desirable   *
		     * than one with higher cost.  Test whether or not I should disallow   *
		     * re-expansion based on a higher total cost.                          */

		    /* updating the maze (Dijktra's min dist algorithm) if found "shorter" path */
		    if(old_tcost > new_tcost && old_back_cost > new_back_cost)
			{
/*       if (old_tcost > new_tcost) {     */
			    rr_node_route_inf[inode].prev_node =
				current->u.prev_node;
			    rr_node_route_inf[inode].prev_edge =
				current->prev_edge;
			    rr_node_route_inf[inode].path_cost = new_tcost;
			    rr_node_route_inf[inode].backward_path_cost =
				new_back_cost;

			    if(old_tcost > 0.99 * HUGE_FLOAT)	/* First time touched. */
				add_to_mod_list(&rr_node_route_inf[inode].
						path_cost);

			    directed_search_expand_neighbours(current, inet,
							      bend_cost,
							      target_node,
								  highfanout_rlim,
							      astar_fac);
			}

		    free_heap_data(current);
		    current = get_heap_head();

		    if(current == NULL)
			{	/* Impossible routing.  No path for net. */
				printf("Failed to route net %s #%d pin %d num_sinks %d highfanout_rlim %d\n", clb_net[inet].name, inet, itarget, clb_net[inet].num_sinks, highfanout_rlim);
			    reset_path_costs();
			    return (FALSE);
			}

		    inode = current->index;
		}

	    rr_node_route_inf[inode].target_flag--;	/* Connected to this SINK. */
	    remaining_connections_to_sink =
		rr_node_route_inf[inode].target_flag;

	    /* keep info on the current routing of this net */
	    new_route_start_tptr = update_traceback(current, inet);

	    free_heap_data(current);
	    /* update the congestion costs of rr_nodes due to the routing to this sink 
	     * so only those nodes used in the partial routing of this sink and not 
	     * of the entire net (remember we're in a loop for this net over its sinks) */
	    pathfinder_update_one_cost(new_route_start_tptr, 1, pres_fac);

	    /* WMF: MUST empty heap and recalculate all total costs, because
	     * for the next sink, the target destination is changed, so the expected
	     * cost calculation is changed also, meaning all the nodes on the heap have
	     * "stale" total costs (costs based on last sink). */
	    empty_heap();
	    reset_path_costs();
	}

    return (TRUE);
}