int looking_for_dead_ends(void) { int num_of_dead_ends = 0; for (int i = 0; i < size_of_column - 1; ++i) for (int j = 0; j < size_of_line - 1; ++j) if (grid[i][j] != 4) grid_transformed[i][j] = 0; rebuild_grid(); for (int i = 0; i < size_of_column - 1; ++i) for (int j = 0; j < size_of_line - 1; ++j) if (grid_transformed[i][j] == 1) mark_ends(i, j); for (int i = 0; i < size_of_column - 1; ++i) for (int j = 0; j < size_of_line - 1; ++j) if (grid_transformed[i][j] == 6) { count_ends(i, j); num_of_dead_ends++; } return num_of_dead_ends; }
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); }
void mark_ends(int i, int j) { int i1, j1; grid_transformed[i][j] = 6; if (grid[i][j] == 0) { if (grid[i][j-1] < 4 && grid_transformed[i][j-1] != 1 && grid_transformed[i][j-1] != 6 && j-1 >= 0) { grid_transformed[i][j-1]--; i1 = i; j1 = j-1; if (grid_transformed[i1][j1] == 1) mark_ends(i1, j1); } if (grid[i-1][j] < 4 && grid_transformed[i-1][j] != 1 && grid_transformed[i-1][j] != 6 && i-1 >= 0) { grid_transformed[i-1][j]--; i1 = i-1; j1 = j; if (grid_transformed[i1][j1] == 1) mark_ends(i1, j1); } if (grid[i][j+1] < 2 && grid_transformed[i][j+1] != 1 && grid_transformed[i][j+1] != 6 && j+1 < size_of_line - 1) { grid_transformed[i][j+1]--; i1 = i; j1 = j+1; if (grid_transformed[i1][j1] == 1) mark_ends(i1, j1); } if ((!grid[i+1][j] || grid[i+1][j] == 2) && grid_transformed[i+1][j] != 1 && grid_transformed[i+1][j] != 6 && i+1 < size_of_column - 1) { grid_transformed[i+1][j]--; i1 = i+1; j1 = j; if (grid_transformed[i1][j1] == 1) mark_ends(i1, j1); } } if (grid[i][j] == 1) { if (grid[i][j-1] < 4 && grid_transformed[i][j-1] != 1 && grid_transformed[i][j-1] != 6 && j-1 >= 0) { grid_transformed[i][j-1]--; i1 = i; j1 = j-1; if (grid_transformed[i1][j1] == 1) mark_ends(i1, j1); } if (grid[i][j+1] < 2 && grid_transformed[i][j+1] != 1 && grid_transformed[i][j+1] != 6 && j+1 < size_of_line - 1) { grid_transformed[i][j+1]--; i1 = i; j1 = j+1; if (grid_transformed[i1][j1] == 1) mark_ends(i1, j1); } if ((!grid[i+1][j] || grid[i+1][j] == 2) && grid_transformed[i+1][j] != 1 && grid_transformed[i+1][j] != 6 && i+1 < size_of_column - 1) { grid_transformed[i+1][j]--; i1 = i+1; j1 = j; if (grid_transformed[i1][j1] == 1) mark_ends(i1, j1); } } if (grid[i][j] == 2) { if (grid[i-1][j] < 4 && grid_transformed[i-1][j] != 1 && grid_transformed[i-1][j] != 6 && i-1 >= 0) { grid_transformed[i-1][j]--; i1 = i-1; j1 = j; if (grid_transformed[i1][j1] == 1) mark_ends(i1, j1); } if (grid[i][j+1] < 2 && grid_transformed[i][j+1] != 1 && grid_transformed[i][j+1] != 6 && j+1 < size_of_line - 1) { grid_transformed[i][j+1]--; i1 = i; j1 = j+1; if (grid_transformed[i1][j1] == 1) mark_ends(i1, j1); } if ((!grid[i+1][j] || grid[i+1][j] == 2) && grid_transformed[i+1][j] != 1 && grid_transformed[i+1][j] != 6 && i+1 < size_of_column - 1) { grid_transformed[i+1][j]--; i1 = i+1; j1 = j; if (grid_transformed[i1][j1] == 1) mark_ends(i1, j1); } } if (grid[i][j] == 3) { if (grid[i][j+1] < 2 && grid_transformed[i][j+1] != 1 && grid_transformed[i][j+1] != 6 && j+1 < size_of_line - 1) { grid_transformed[i][j+1]--; i1 = i; j1 = j+1; if (grid_transformed[i1][j1] == 1) mark_ends(i1, j1); } if ((grid[i+1][j] == 0 || grid[i+1][j] == 2) && grid_transformed[i+1][j] != 1 && grid_transformed[i+1][j] != 6 && i+1 < size_of_column - 1) { grid_transformed[i+1][j]--; i1 = i+1; j1 = j; if (grid_transformed[i1][j1] == 1) mark_ends(i1, j1); } } }
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); }