Exemplo n.º 1
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);
}
Exemplo n.º 2
0
boolean try_breadth_first_route (struct s_router_opts router_opts,
        t_ivec **clb_opins_used_locally) {

/* Iterated maze router ala Pathfinder Negotiated Congestion algorithm,  *
 * (FPGA 95 p. 111).  Returns TRUE if it can route this FPGA, FALSE if   *
 * it can't.                                                             */

 float pres_fac;
 boolean success, is_routable, rip_up_local_opins;
 int itry, inet;

/* Usually the first iteration uses a very small (or 0) pres_fac to find  *
 * the shortest path and get a congestion map.  For fast compiles, I set  *
 * pres_fac high even for the first iteration.                            */

 pres_fac = router_opts.first_iter_pres_fac;

 for (itry=1;itry<=router_opts.max_router_iterations;itry++) {

    for (inet=0;inet<num_nets;inet++) {
    	 /* Added by Wei */
      if (is_folding)
	  {
	    if (current_stage != num_stage)
		{
	      if ((inet<num_net_per_stage[current_stage-1].begin)||(inet>=num_net_per_stage[current_stage].begin))
	          continue;
	    } 
	    else 
		{
	      if (inet<num_net_per_stage[current_stage-1].begin)
	        continue;
	    }
      }
      printf("The net is %d\n",inet);
	  
       if (is_global[inet] == FALSE) {       /* Skip global nets. */

          pathfinder_update_one_cost (trace_head[inet], -1, pres_fac);

          is_routable = breadth_first_route_net (inet, router_opts.bend_cost);

          /* Impossible to route? (disconnected rr_graph) */

          if (!is_routable) {
             printf ("Routing failed.\n");
             return (FALSE);
          }
 
          pathfinder_update_one_cost (trace_head[inet], 1, pres_fac);
       }
    }

   /* Make sure any CLB OPINs used up by subblocks being hooked directly     *
    * to them are reserved for that purpose.                                 */

    if (itry == 1)
       rip_up_local_opins = FALSE;
    else
       rip_up_local_opins = TRUE;

    reserve_locally_used_opins (pres_fac, rip_up_local_opins,
                    clb_opins_used_locally);
 
    success = feasible_routing ();
    if (success) {
       printf("Successfully routed after %d routing iterations.\n", itry);
       return (TRUE);
    }
 
    if (itry == 1)
       pres_fac = router_opts.initial_pres_fac;
    else
       pres_fac *= router_opts.pres_fac_mult;

    pathfinder_update_cost (pres_fac, router_opts.acc_fac);
 }
 
 printf ("Routing failed.\n");
 return (FALSE);
}
Exemplo n.º 3
0
boolean try_breadth_first_route(struct s_router_opts router_opts,
                                t_ivec ** clb_opins_used_locally, int width_fac) {

    /* Iterated maze router ala Pathfinder Negotiated Congestion algorithm,  *
     * (FPGA 95 p. 111).  Returns TRUE if it can route this FPGA, FALSE if   *
     * it can't.                                                             */

    float pres_fac;
    boolean success, is_routable, rip_up_local_opins;
    int itry, inet;

    /* Usually the first iteration uses a very small (or 0) pres_fac to find  *
     * the shortest path and get a congestion map.  For fast compiles, I set  *
     * pres_fac high even for the first iteration.                            */

    pres_fac = router_opts.first_iter_pres_fac;

    for (itry = 1; itry <= router_opts.max_router_iterations; itry++) {

        for (inet = 0; inet < num_nets; inet++) {
            if (clb_net[inet].is_global == FALSE) { /* Skip global nets. */

                pathfinder_update_one_cost(trace_head[inet], -1, pres_fac);

                is_routable = breadth_first_route_net(inet,
                                                      router_opts.bend_cost);

                /* Impossible to route? (disconnected rr_graph) */

                if (!is_routable) {
                    vpr_printf(TIO_MESSAGE_INFO, "Routing failed.\n");
                    return (FALSE);
                }

                pathfinder_update_one_cost(trace_head[inet], 1, pres_fac);

            }
        }

        /* Make sure any CLB OPINs used up by subblocks being hooked directly     *
         * to them are reserved for that purpose.                                 */

        if (itry == 1)
            rip_up_local_opins = FALSE;
        else
            rip_up_local_opins = TRUE;

        reserve_locally_used_opins(pres_fac, rip_up_local_opins,
                                   clb_opins_used_locally);

        success = feasible_routing();
        if (success) {
            vpr_printf(TIO_MESSAGE_INFO, "Successfully routed after %d routing iterations.\n", itry);
            return (TRUE);
        }

        if (itry == 1)
            pres_fac = router_opts.initial_pres_fac;
        else
            pres_fac *= router_opts.pres_fac_mult;

        pres_fac = std::min(pres_fac, static_cast<float>(HUGE_POSITIVE_FLOAT / 1e5));

        pathfinder_update_cost(pres_fac, router_opts.acc_fac);
    }

    vpr_printf(TIO_MESSAGE_INFO, "Routing failed.\n");
    return (FALSE);
}