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); }
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); }
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); }