SRC/route_directed_search.c File Reference

#include <stdio.h>
#include <assert.h>
#include <sys/types.h>
#include "util.h"
#include "vpr_types.h"
#include "globals.h"
#include "mst.h"
#include "route_export.h"
#include "route_common.h"
#include "route_directed_search.h"
#include "draw.h"
Include dependency graph for route_directed_search.c:

Go to the source code of this file.

Defines

#define ROUND_UP(x)   (ceil (x - 0.001))

Functions

static boolean directed_search_route_net (int inet, float pres_fac, float astar_fac, float bend_cost, t_mst_edge **mst)
static void directed_search_expand_trace_segment (struct s_trace *start_ptr, int target_node, float astar_fac, int remaining_connections_to_sink)
static void directed_search_expand_neighbours (struct s_heap *current, int inet, float bend_cost, int target_node, float astar_fac)
static void directed_search_add_source_to_heap (int inet, int target_node, float astar_fac)
static float get_directed_search_expected_cost (int inode, int target_node)
static int get_expected_segs_to_target (int inode, int target_node, int *num_segs_ortho_dir_ptr)
boolean try_directed_search_route (struct s_router_opts router_opts, t_ivec **fb_opins_used_locally, int width_fac, t_mst_edge **mst)

Define Documentation

#define ROUND_UP (  )     (ceil (x - 0.001))

Definition at line 537 of file route_directed_search.c.


Function Documentation

static void directed_search_add_source_to_heap ( int  inet,
int  target_node,
float  astar_fac 
) [static]

Definition at line 456 of file route_directed_search.c.

00459 {
00460 
00461 /* Adds the SOURCE of this net to the heap.  Used to start a net's routing. */
00462 
00463     int inode;
00464     float back_cost, tot_cost;
00465 
00466     inode = net_rr_terminals[inet][0];  /* SOURCE */
00467     back_cost = 0.0 + get_rr_cong_cost(inode);
00468 
00469     /* setting the total cost to 0 because it's the only element on the heap */
00470     if(!is_empty_heap())
00471         {
00472             printf
00473                 ("Error: Wrong Assumption: in directed_search_add_source_to_heap "
00474                  "the heap is not empty. Need to properly calculate source node's cost.\n");
00475             exit(1);
00476         }
00477 
00478     /* WMF: path cost is 0. could use tot_cost = 0 to save some computation time, but
00479      * for consistency, I chose to do the expected cost calculation. */
00480     tot_cost =
00481         back_cost + astar_fac * get_directed_search_expected_cost(inode,
00482                                                                   target_node);
00483     node_to_heap(inode, tot_cost, NO_PREVIOUS, NO_PREVIOUS, back_cost, OPEN);
00484 
00485 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void directed_search_expand_neighbours ( struct s_heap current,
int  inet,
float  bend_cost,
int  target_node,
float  astar_fac 
) [static]

Definition at line 386 of file route_directed_search.c.

00391 {
00392 
00393 /* Puts all the rr_nodes adjacent to current on the heap.  rr_nodes outside   *
00394  * the expanded bounding box specified in route_bb are not added to the     *
00395  * heap.  back_cost is the path_cost to get to inode. total cost i.e.
00396  * tot_cost is path_cost + (expected_cost to target sink) */
00397 
00398     int iconn, to_node, num_edges, inode, target_x, target_y;
00399     t_rr_type from_type, to_type;
00400     float new_tot_cost, old_back_pcost, new_back_pcost;
00401 
00402     inode = current->index;
00403     old_back_pcost = current->backward_path_cost;
00404     num_edges = rr_node[inode].num_edges;
00405 
00406     target_x = rr_node[target_node].xhigh;
00407     target_y = rr_node[target_node].yhigh;
00408 
00409     for(iconn = 0; iconn < num_edges; iconn++)
00410         {
00411             to_node = rr_node[inode].edges[iconn];
00412 
00413             if(rr_node[to_node].xhigh < route_bb[inet].xmin ||
00414                rr_node[to_node].xlow > route_bb[inet].xmax ||
00415                rr_node[to_node].yhigh < route_bb[inet].ymin ||
00416                rr_node[to_node].ylow > route_bb[inet].ymax)
00417                 continue;       /* Node is outside (expanded) bounding box. */
00418 
00419 /* Prune away IPINs that lead to blocks other than the target one.  Avoids  *
00420  * the issue of how to cost them properly so they don't get expanded before *
00421  * more promising routes, but makes route-throughs (via CLBs) impossible.   *
00422  * Change this if you want to investigate route-throughs.                   */
00423 
00424             to_type = rr_node[to_node].type;
00425             if(to_type == IPIN && (rr_node[to_node].xhigh != target_x ||
00426                                    rr_node[to_node].yhigh != target_y))
00427                 continue;
00428 
00429 /* new_back_pcost stores the "known" part of the cost to this node -- the   *
00430  * congestion cost of all the routing resources back to the existing route  *
00431  * new_tot_cost 
00432  * is this "known" backward cost + an expected cost to get to the target.   */
00433 
00434             new_back_pcost = old_back_pcost + get_rr_cong_cost(to_node);
00435 
00436             if(bend_cost != 0.)
00437                 {
00438                     from_type = rr_node[inode].type;
00439                     to_type = rr_node[to_node].type;
00440                     if((from_type == CHANX && to_type == CHANY) ||
00441                        (from_type == CHANY && to_type == CHANX))
00442                         new_back_pcost += bend_cost;
00443                 }
00444 
00445             /* Calculate the new total cost = path cost + astar_fac * remaining distance to target */
00446             new_tot_cost = new_back_pcost + astar_fac *
00447                 get_directed_search_expected_cost(to_node, target_node);
00448 
00449             node_to_heap(to_node, new_tot_cost, inode, iconn, new_back_pcost,
00450                          OPEN);
00451         }
00452 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void directed_search_expand_trace_segment ( struct s_trace start_ptr,
int  target_node,
float  astar_fac,
int  remaining_connections_to_sink 
) [static]

Definition at line 313 of file route_directed_search.c.

00317 {
00318 
00319 /* Adds all the rr_nodes in the entire traceback from SOURCE to all SINKS   *
00320  * routed so far (partial routing). 
00321  * This allows expansion to begin from the existing wiring.  The            *
00322  * remaining_connections_to_sink value is 0 if the route segment ending     *
00323  * at this location is the last one to connect to the SINK ending the route *
00324  * segment.  This is the usual case.  If it is not the last connection this *
00325  * net must make to this SINK, I have a hack to ensure the next connection  *
00326  * to this SINK goes through a different IPIN.  Without this hack, the      *
00327  * router would always put all the connections from this net to this SINK   *
00328  * through the same IPIN.  With LUTs or cluster-based logic blocks, you     *
00329  * should never have a net connecting to two logically-equivalent pins on   *
00330  * the same logic block, so the hack will never execute.  If your logic     *
00331  * block is an and-gate, however, nets might connect to two and-inputs on   *
00332  * the same logic block, and since the and-inputs are logically-equivalent, *
00333  * this means two connections to the same SINK.                             */
00334 
00335     struct s_trace *tptr;
00336     int inode, backward_path_cost, tot_cost;
00337 
00338     tptr = start_ptr;
00339 
00340     if(remaining_connections_to_sink == 0)
00341         {                       /* Usual case. */
00342             while(tptr != NULL)
00343                 {
00344                     /* WMF: partial routing is added to the heap with path cost of 0, because
00345                      * new extension to the next sink can start at any point on current partial 
00346                      * routing. However, for directed search the total cost must be made to favor
00347                      * the points of current partial routing that are NEAR the next sink (target sink) */
00348 
00349                     /* WMF: IPINs and SINKs should be excluded from the heap in this
00350                      * since they NEVER connect TO any rr_node (no to_edges), but since they have
00351                      * no to_edges, it's ok (ROUTE_THROUGHS are disabled). To clarify, see 
00352                      * rr_graph.c to find out rr_node[inode].num_edges = 0 for SINKs and
00353                      * rr_node[inode].num_edges = 1 for INPINs */
00354 
00355                     inode = tptr->index;
00356 
00357                     if(!
00358                        (rr_node[inode].type == IPIN
00359                         || rr_node[inode].type == SINK))
00360                         {
00361 
00362                             backward_path_cost = 0;
00363                             tot_cost =
00364                                 backward_path_cost +
00365                                 astar_fac *
00366                                 get_directed_search_expected_cost(inode,
00367                                                                   target_node);
00368                             node_to_heap(inode, tot_cost, NO_PREVIOUS,
00369                                          NO_PREVIOUS, backward_path_cost,
00370                                          OPEN);
00371                         }
00372 
00373                     tptr = tptr->next;
00374                 }
00375         }
00376 
00377     else
00378         {                       /* This case never executes for most logic blocks. */
00379             printf("Warning: Multiple connections from net to the same sink. "
00380                    "This should not happen for LUT/Cluster based logic blocks. Aborting.\n");
00381             exit(1);
00382         }
00383 }

Here is the call graph for this function:

Here is the caller graph for this function:

static boolean directed_search_route_net ( int  inet,
float  pres_fac,
float  astar_fac,
float  bend_cost,
t_mst_edge **  mst 
) [static]

Definition at line 158 of file route_directed_search.c.

00163 {
00164 
00165 /* Uses a maze routing (Dijkstra's) algorithm to route a net.  The net       *
00166  * begins at the net output, and expands outward until it hits a target      *
00167  * pin.  The algorithm is then restarted with the entire first wire segment  *
00168  * included as part of the source this time.  For an n-pin net, the maze     *
00169  * router is invoked n-1 times to complete all the connections.  Inet is     *
00170  * the index of the net to be routed.  Bends are penalized by bend_cost      *
00171  * (which is typically zero for detailed routing and nonzero only for global *
00172  * routing), since global routes with lots of bends are tougher to detailed  *
00173  * route (using a detailed router like SEGA).                                *
00174  * If this routine finds that a net *cannot* be connected (due to a complete *
00175  * lack of potential paths, rather than congestion), it returns FALSE, as    *
00176  * routing is impossible on this architecture.  Otherwise it returns TRUE.   */
00177 /* WMF: This is the directed search (A-star) version of maze router. */
00178 
00179     int inode, remaining_connections_to_sink;
00180     int itarget, target_pin, target_node;
00181     struct s_heap *current;
00182     struct s_trace *new_route_start_tptr;
00183     float old_tcost, new_tcost, old_back_cost, new_back_cost;
00184 
00185 /* Rip-up any old routing. */
00186     /* WMF: For the 1st router iteration trace_head[inet] is NULL, as it is 
00187      * my_calloc'ed in alloc_route_structs() so the following does nothing.
00188      * However, for subsequent iterations, trace_head[inet] contains the previous
00189      * ieration's routing for this net. */
00190     pathfinder_update_one_cost(trace_head[inet], -1, pres_fac);
00191     free_traceback(inet);       /* kills trace, and set the trace head and tail to NULL */
00192 
00193     /* adding the SOURCE node to the heap with correct total cost */
00194     target_pin = mst[inet][0].to_node;
00195     target_node = net_rr_terminals[inet][target_pin];
00196     directed_search_add_source_to_heap(inet, target_node, astar_fac);
00197 
00198     mark_ends(inet);
00199 
00200     remaining_connections_to_sink = 0;
00201 
00202     for(itarget = 0; itarget < net[inet].num_sinks; itarget++)
00203         {
00204             target_pin = mst[inet][itarget].to_node;
00205             target_node = net_rr_terminals[inet][target_pin];
00206 
00207             /*    printf ("Target #%d, pin number %d, target_node: %d.\n",
00208              * itarget, target_pin, target_node);  */
00209 
00210             /* WMF: since the heap has been emptied, need to restart the wavefront
00211              * from the current partial routing, starting at the trace_head (SOURCE) 
00212              * Note: in the 1st iteration, there is no trace (no routing at all for this net)
00213              * i.e. trace_head[inet] == NULL (found in free_traceback() in route_common.c, 
00214              * which is called before the routing of any net), 
00215              * so this routine does nothing, but the heap does have the SOURCE node due 
00216              * to directed_search_add_source_to_heap (inet) before the loop */
00217             directed_search_expand_trace_segment(trace_head[inet],
00218                                                  target_node, astar_fac,
00219                                                  remaining_connections_to_sink);
00220 
00221             current = get_heap_head();
00222 
00223             if(current == NULL)
00224                 {               /* Infeasible routing.  No possible path for net. */
00225                     reset_path_costs(); /* Clean up before leaving. */
00226                     return (FALSE);
00227                 }
00228 
00229             inode = current->index;
00230 
00231             while(inode != target_node)
00232                 {
00233                     old_tcost = rr_node_route_inf[inode].path_cost;
00234                     new_tcost = current->cost;
00235 
00236                     /* WMF: not needed if Vaughn initialized rr_node_route_inf[inode].backward_path_cost
00237                      * to HUGE_FLOAT along with rr_node_route_inf[inode].path_cost */
00238                     if(old_tcost > 0.99 * HUGE_FLOAT)   /* First time touched. */
00239                         old_back_cost = HUGE_FLOAT;
00240                     else
00241                         old_back_cost =
00242                             rr_node_route_inf[inode].backward_path_cost;
00243 
00244                     new_back_cost = current->backward_path_cost;
00245 
00246                     /* I only re-expand a node if both the "known" backward cost is lower  *
00247                      * in the new expansion (this is necessary to prevent loops from       *
00248                      * forming in the routing and causing havoc) *and* the expected total  *
00249                      * cost to the sink is lower than the old value.  Different R_upstream *
00250                      * values could make a path with lower back_path_cost less desirable   *
00251                      * than one with higher cost.  Test whether or not I should disallow   *
00252                      * re-expansion based on a higher total cost.                          */
00253 
00254                     /* updating the maze (Dijktra's min dist algorithm) if found "shorter" path */
00255                     if(old_tcost > new_tcost && old_back_cost > new_back_cost)
00256                         {
00257 /*       if (old_tcost > new_tcost) {     */
00258                             rr_node_route_inf[inode].prev_node =
00259                                 current->u.prev_node;
00260                             rr_node_route_inf[inode].prev_edge =
00261                                 current->prev_edge;
00262                             rr_node_route_inf[inode].path_cost = new_tcost;
00263                             rr_node_route_inf[inode].backward_path_cost =
00264                                 new_back_cost;
00265 
00266                             if(old_tcost > 0.99 * HUGE_FLOAT)   /* First time touched. */
00267                                 add_to_mod_list(&rr_node_route_inf[inode].
00268                                                 path_cost);
00269 
00270                             directed_search_expand_neighbours(current, inet,
00271                                                               bend_cost,
00272                                                               target_node,
00273                                                               astar_fac);
00274                         }
00275 
00276                     free_heap_data(current);
00277                     current = get_heap_head();
00278 
00279                     if(current == NULL)
00280                         {       /* Impossible routing.  No path for net. */
00281                             reset_path_costs();
00282                             return (FALSE);
00283                         }
00284 
00285                     inode = current->index;
00286                 }
00287 
00288             rr_node_route_inf[inode].target_flag--;     /* Connected to this SINK. */
00289             remaining_connections_to_sink =
00290                 rr_node_route_inf[inode].target_flag;
00291 
00292             /* keep info on the current routing of this net */
00293             new_route_start_tptr = update_traceback(current, inet);
00294 
00295             free_heap_data(current);
00296             /* update the congestion costs of rr_nodes due to the routing to this sink 
00297              * so only those nodes used in the partial routing of this sink and not 
00298              * of the entire net (remember we're in a loop for this net over its sinks) */
00299             pathfinder_update_one_cost(new_route_start_tptr, 1, pres_fac);
00300 
00301             /* WMF: MUST empty heap and recalculate all total costs, because
00302              * for the next sink, the target destination is changed, so the expected
00303              * cost calculation is changed also, meaning all the nodes on the heap have
00304              * "stale" total costs (costs based on last sink). */
00305             empty_heap();
00306             reset_path_costs();
00307         }
00308 
00309     return (TRUE);
00310 }

Here is the call graph for this function:

Here is the caller graph for this function:

static float get_directed_search_expected_cost ( int  inode,
int  target_node 
) [static]

Definition at line 489 of file route_directed_search.c.

00491 {
00492 
00493 /* Determines the expected cost (due to resouce cost i.e. distance) to reach  *
00494  * the target node from inode.  It doesn't include the cost of inode --       *
00495  * that's already in the "known" path_cost.                                   */
00496 
00497     t_rr_type rr_type;
00498     int cost_index, ortho_cost_index, num_segs_same_dir, num_segs_ortho_dir;
00499     float cong_cost;
00500 
00501     rr_type = rr_node[inode].type;
00502 
00503     if(rr_type == CHANX || rr_type == CHANY)
00504         {
00505             num_segs_same_dir =
00506                 get_expected_segs_to_target(inode, target_node,
00507                                             &num_segs_ortho_dir);
00508             cost_index = rr_node[inode].cost_index;
00509             ortho_cost_index = rr_indexed_data[cost_index].ortho_cost_index;
00510 
00511             cong_cost =
00512                 num_segs_same_dir * rr_indexed_data[cost_index].base_cost +
00513                 num_segs_ortho_dir *
00514                 rr_indexed_data[ortho_cost_index].base_cost;
00515             cong_cost +=
00516                 rr_indexed_data[IPIN_COST_INDEX].base_cost +
00517                 rr_indexed_data[SINK_COST_INDEX].base_cost;
00518 
00519             return (cong_cost);
00520         }
00521 
00522     else if(rr_type == IPIN)
00523         {                       /* Change if you're allowing route-throughs */
00524             return (rr_indexed_data[SINK_COST_INDEX].base_cost);
00525         }
00526 
00527     else
00528         {                       /* Change this if you want to investigate route-throughs */
00529             return (0.);
00530         }
00531 }

Here is the call graph for this function:

Here is the caller graph for this function:

static int get_expected_segs_to_target ( int  inode,
int  target_node,
int *  num_segs_ortho_dir_ptr 
) [static]

Definition at line 541 of file route_directed_search.c.

00544 {
00545 
00546 /* Returns the number of segments the same type as inode that will be needed *
00547  * to reach target_node (not including inode) in each direction (the same    *
00548  * direction (horizontal or vertical) as inode and the orthogonal direction).*/
00549 
00550     t_rr_type rr_type;
00551     int target_x, target_y, num_segs_same_dir, cost_index, ortho_cost_index;
00552     int no_need_to_pass_by_clb;
00553     float inv_length, ortho_inv_length, ylow, yhigh, xlow, xhigh;
00554 
00555     target_x = rr_node[target_node].xlow;
00556     target_y = rr_node[target_node].ylow;
00557     cost_index = rr_node[inode].cost_index;
00558     inv_length = rr_indexed_data[cost_index].inv_length;
00559     ortho_cost_index = rr_indexed_data[cost_index].ortho_cost_index;
00560     ortho_inv_length = rr_indexed_data[ortho_cost_index].inv_length;
00561     rr_type = rr_node[inode].type;
00562 
00563     if(rr_type == CHANX)
00564         {
00565             ylow = rr_node[inode].ylow;
00566             xhigh = rr_node[inode].xhigh;
00567             xlow = rr_node[inode].xlow;
00568 
00569             /* Count vertical (orthogonal to inode) segs first. */
00570 
00571             if(ylow > target_y)
00572                 {               /* Coming from a row above target? */
00573                     *num_segs_ortho_dir_ptr =
00574                         ROUND_UP((ylow - target_y + 1.) * ortho_inv_length);
00575                     no_need_to_pass_by_clb = 1;
00576                 }
00577             else if(ylow < target_y - 1)
00578                 {               /* Below the FB bottom? */
00579                     *num_segs_ortho_dir_ptr = ROUND_UP((target_y - ylow) *
00580                                                        ortho_inv_length);
00581                     no_need_to_pass_by_clb = 1;
00582                 }
00583             else
00584                 {               /* In a row that passes by target FB */
00585                     *num_segs_ortho_dir_ptr = 0;
00586                     no_need_to_pass_by_clb = 0;
00587                 }
00588 
00589             /* Now count horizontal (same dir. as inode) segs. */
00590 
00591             if(xlow > target_x + no_need_to_pass_by_clb)
00592                 {
00593                     num_segs_same_dir =
00594                         ROUND_UP((xlow - no_need_to_pass_by_clb -
00595                                   target_x) * inv_length);
00596                 }
00597             else if(xhigh < target_x - no_need_to_pass_by_clb)
00598                 {
00599                     num_segs_same_dir =
00600                         ROUND_UP((target_x - no_need_to_pass_by_clb -
00601                                   xhigh) * inv_length);
00602                 }
00603             else
00604                 {
00605                     num_segs_same_dir = 0;
00606                 }
00607         }
00608 
00609     else
00610         {                       /* inode is a CHANY */
00611             ylow = rr_node[inode].ylow;
00612             yhigh = rr_node[inode].yhigh;
00613             xlow = rr_node[inode].xlow;
00614 
00615             /* Count horizontal (orthogonal to inode) segs first. */
00616 
00617             if(xlow > target_x)
00618                 {               /* Coming from a column right of target? */
00619                     *num_segs_ortho_dir_ptr =
00620                         ROUND_UP((xlow - target_x + 1.) * ortho_inv_length);
00621                     no_need_to_pass_by_clb = 1;
00622                 }
00623             else if(xlow < target_x - 1)
00624                 {               /* Left of and not adjacent to the FB? */
00625                     *num_segs_ortho_dir_ptr = ROUND_UP((target_x - xlow) *
00626                                                        ortho_inv_length);
00627                     no_need_to_pass_by_clb = 1;
00628                 }
00629             else
00630                 {               /* In a column that passes by target FB */
00631                     *num_segs_ortho_dir_ptr = 0;
00632                     no_need_to_pass_by_clb = 0;
00633                 }
00634 
00635             /* Now count vertical (same dir. as inode) segs. */
00636 
00637             if(ylow > target_y + no_need_to_pass_by_clb)
00638                 {
00639                     num_segs_same_dir =
00640                         ROUND_UP((ylow - no_need_to_pass_by_clb -
00641                                   target_y) * inv_length);
00642                 }
00643             else if(yhigh < target_y - no_need_to_pass_by_clb)
00644                 {
00645                     num_segs_same_dir =
00646                         ROUND_UP((target_y - no_need_to_pass_by_clb -
00647                                   yhigh) * inv_length);
00648                 }
00649             else
00650                 {
00651                     num_segs_same_dir = 0;
00652                 }
00653         }
00654 
00655     return (num_segs_same_dir);
00656 }

Here is the caller graph for this function:

boolean try_directed_search_route ( struct s_router_opts  router_opts,
t_ivec **  fb_opins_used_locally,
int  width_fac,
t_mst_edge **  mst 
)

Definition at line 48 of file route_directed_search.c.

00052 {
00053 
00054 /* Iterated maze router ala Pathfinder Negotiated Congestion algorithm,  *
00055  * (FPGA 95 p. 111).  Returns TRUE if it can route this FPGA, FALSE if   *
00056  * it can't.                                                             */
00057 
00058     float pres_fac;
00059     boolean success, is_routable, rip_up_local_opins;
00060     int itry, inet;
00061 
00062     /* char msg[100]; */
00063 
00064     /* mst not built as good as it should, ideally, just have it after placement once only
00065          however, rr_node numbers changed when the channel width changes so forced to do it here */
00066     if(mst)
00067         {
00068             for(inet = 0; inet < num_nets; inet++)
00069                 {
00070                     free(mst[inet]);
00071                     mst[inet] = get_mst_of_net(inet);
00072                 }
00073         }
00074 
00075 /* Usually the first iteration uses a very small (or 0) pres_fac to find  *
00076  * the shortest path and get a congestion map.  For fast compiles, I set  *
00077  * pres_fac high even for the first iteration.                            */
00078 
00079     pres_fac = router_opts.first_iter_pres_fac;
00080 
00081     for(itry = 1; itry <= router_opts.max_router_iterations; itry++)
00082         {
00083 
00084             for(inet = 0; inet < num_nets; inet++)
00085                 {
00086                     if(net[inet].is_global == FALSE)
00087                         {       /* Skip global nets. */
00088 
00089                             is_routable =
00090                                 directed_search_route_net(inet, pres_fac,
00091                                                           router_opts.
00092                                                           astar_fac,
00093                                                           router_opts.
00094                                                           bend_cost, mst);
00095 
00096                             /* Impossible to route? (disconnected rr_graph) */
00097 
00098                             if(!is_routable)
00099                                 {
00100                                     printf("Routing failed.\n");
00101                                     return (FALSE);
00102                                 }
00103 
00104                         }
00105                 }
00106 
00107             /* Make sure any FB OPINs used up by subblocks being hooked directly     *
00108              * to them are reserved for that purpose.                                 */
00109 
00110             if(itry == 1)
00111                 rip_up_local_opins = FALSE;
00112             else
00113                 rip_up_local_opins = TRUE;
00114 
00115             reserve_locally_used_opins(pres_fac, rip_up_local_opins,
00116                                        fb_opins_used_locally);
00117 
00118             success = feasible_routing();
00119             if(success)
00120                 {
00121                     printf
00122                         ("Successfully routed after %d routing iterations by Directed Search.\n",
00123                          itry);
00124                     return (TRUE);
00125                 }
00126 #if 0
00127             else
00128                 {
00129                     sprintf(msg,
00130                             "After iteration %d routing failed (A*) with a channel width factor of %d and Fc_int of %d, Fs_int of %d.",
00131                             itry, width_fac, Fc_int, Fs_int);
00132                     init_draw_coords(pins_per_clb);
00133                     update_screen(MAJOR, msg, ROUTING, FALSE);
00134                 }
00135 #endif
00136 
00137 
00138             if(itry == 1)
00139                 {
00140                     pres_fac = router_opts.initial_pres_fac;
00141                     pathfinder_update_cost(pres_fac, 0.);       /* Acc_fac=0 for first iter. */
00142                 }
00143             else
00144                 {
00145                     pres_fac *= router_opts.pres_fac_mult;
00146                     pathfinder_update_cost(pres_fac, router_opts.acc_fac);
00147                 }
00148 
00149         }
00150 
00151     printf("Routing failed.\n");
00152 
00153     return (FALSE);
00154 }

Here is the call graph for this function:

Here is the caller graph for this function:


Generated on Tue Jan 5 15:26:13 2010 for VPR5.0 by  doxygen 1.6.1