VPR-6.0

vpr/SRC/route/route_common.c

Go to the documentation of this file.
00001 #include <math.h>
00002 #include <stdio.h>
00003 #include <assert.h>
00004 #include <time.h>
00005 #include "util.h"
00006 #include "vpr_types.h"
00007 #include "vpr_utils.h"
00008 #include "globals.h"
00009 #include "mst.h"
00010 #include "route_export.h"
00011 #include "route_common.h"
00012 #include "route_tree_timing.h"
00013 #include "route_timing.h"
00014 #include "route_breadth_first.h"
00015 #include "route_directed_search.h"
00016 #include "place_and_route.h"
00017 #include "rr_graph.h"
00018 #include "read_xml_arch_file.h"
00019 
00020 /***************** Variables shared only by route modules *******************/
00021 
00022 t_rr_node_route_inf *rr_node_route_inf = NULL;  /**< [0..num_rr_nodes-1] */
00023 
00024 struct s_bb *route_bb = NULL;   /**< [0..num_nets-1]. Limits area in which each  
00025                                  *   net must be routed.                         */
00026 
00027 
00028 /**************** Static variables local to route_common.c ******************/
00029 
00030 static struct s_heap **heap;    /**< Indexed from [1..heap_size] */
00031 static int heap_size;           /**< Number of slots in the heap array */
00032 static int heap_tail;           /**< Index of first unused slot in the heap array */
00033 
00034 /** For managing my own list of currently free heap data structures.     */
00035 static struct s_heap *heap_free_head = NULL;
00036 
00037 /** For managing my own list of currently free trace data structures.    */
00038 static struct s_trace *trace_free_head = NULL;
00039 
00040 #ifdef DEBUG
00041 static int num_trace_allocated = 0;     /**< To watch for memory leaks. */
00042 static int num_heap_allocated = 0;
00043 static int num_linked_f_pointer_allocated = 0;
00044 #endif
00045 
00046 static struct s_linked_f_pointer *rr_modified_head = NULL;
00047 static struct s_linked_f_pointer *linked_f_pointer_free_head = NULL;
00048 
00049 
00050 
00051 /*  The numbering relation between the channels and clbs is:               *
00052  *                                                                         *
00053  *  |   IO    | chan_   |   CLB      | chan_   |   CLB     |               *
00054  *  |grid[0][2]| y[0][2] | grid[1][2]  | y[1][2] |  grid[2][2]|               *
00055  *  +-------- +         +------------+         +-----------+               *
00056  *                                                           } capacity in *
00057  *   No channel          chan_x[1][1]          chan_x[2][1]  } chan_width  *
00058  *                                                           } _x[1]       *
00059  *  +---------+         +------------+         +-----------+               *
00060  *  |         | chan_   |            | chan_   |           |               *
00061  *  |  IO     | y[0][1] |    CLB     | y[1][1] |   CLB     |               *
00062  *  |grid[0][1]|         |  grid[1][1] |         | grid[2][1] |               *
00063  *  |         |         |            |         |           |               *
00064  *  +---------+         +------------+         +-----------+               *
00065  *                                                           } capacity in *
00066  *                      chan_x[1][0]           chan_x[2][0]  } chan_width  * 
00067  *                                                           } _x[0]       *
00068  *                      +------------+         +-----------+               *
00069  *              No      |            | No      |           |               *
00070  *            Channel   |    IO      | Channel |   IO      |               *
00071  *                      |  grid[1][0] |         | grid[2][0] |               *
00072  *                      |            |         |           |               *
00073  *                      +------------+         +-----------+               *
00074  *                                                                         *
00075  *             {=======}              {=======}                            *
00076  *            Capacity in            Capacity in                           *
00077  *          chan_width_y[0]        chan_width_y[1]                         *
00078  *                                                                         */
00079 
00080 
00081 /******************** Subroutines local to route_common.c *******************/
00082 
00083 static void free_trace_data(struct s_trace *tptr);
00084 static void load_route_bb(int bb_factor);
00085 
00086 static struct s_trace *alloc_trace_data(void);
00087 static void add_to_heap(struct s_heap *hptr);
00088 static struct s_heap *alloc_heap_data(void);
00089 static struct s_linked_f_pointer *alloc_linked_f_pointer(void);
00090 
00091 static t_ivec **alloc_and_load_clb_opins_used_locally();
00092 static void adjust_one_rr_occ_and_pcost(int inode,
00093                                         int add_or_sub,
00094                                         float pres_fac);
00095 
00096 
00097 
00098 /************************** Subroutine definitions ***************************/
00099 
00100 /** This routing frees any routing currently held in best routing,      
00101  * then copies over the current routing (held in trace_head), and       
00102  * finally sets trace_head and trace_tail to all NULLs so that the      
00103  * connection to the saved routing is broken.  This is necessary so     
00104  * that the next iteration of the router does not free the saved        
00105  * routing elements.  Also saves any data about locally used clb_opins, 
00106  * since this is also part of the routing.                              
00107  */
00108 void
00109 save_routing(struct s_trace **best_routing,
00110              t_ivec ** clb_opins_used_locally,
00111              t_ivec ** saved_clb_opins_used_locally)
00112 {
00113 
00114     int inet, iblk, iclass, ipin, num_local_opins;
00115     struct s_trace *tptr, *tempptr;
00116     t_type_ptr type;
00117 
00118     for(inet = 0; inet < num_nets; inet++)
00119         {
00120 
00121 /* Free any previously saved routing.  It is no longer best. */
00122             tptr = best_routing[inet];
00123             while(tptr != NULL)
00124                 {
00125                     tempptr = tptr->next;
00126                     free_trace_data(tptr);
00127                     tptr = tempptr;
00128                 }
00129 
00130 /* Save a pointer to the current routing in best_routing. */
00131             best_routing[inet] = trace_head[inet];
00132 
00133 /* Set the current (working) routing to NULL so the current trace       *
00134  * elements won't be reused by the memory allocator.                    */
00135 
00136             trace_head[inet] = NULL;
00137             trace_tail[inet] = NULL;
00138         }
00139 
00140 /* Save which OPINs are locally used.                           */
00141 
00142     for(iblk = 0; iblk < num_blocks; iblk++)
00143         {
00144             type = block[iblk].type;
00145             for(iclass = 0; iclass < type->num_class; iclass++)
00146                 {
00147                     num_local_opins =
00148                         clb_opins_used_locally[iblk][iclass].nelem;
00149                     for(ipin = 0; ipin < num_local_opins; ipin++)
00150                         {
00151                             saved_clb_opins_used_locally[iblk][iclass].
00152                                 list[ipin] =
00153                                 clb_opins_used_locally[iblk][iclass].
00154                                 list[ipin];
00155                         }
00156                 }
00157         }
00158 }
00159 
00160 /** Deallocates any current routing in trace_head, and replaces it with    
00161  * the routing in best_routing.  Best_routing is set to NULL to show that 
00162  * it no longer points to a valid routing.  NOTE:  trace_tail is not      
00163  * restored -- it is set to all NULLs since it is only used in            
00164  * update_traceback.  If you need trace_tail restored, modify this        
00165  * routine.  Also restores the locally used opin data.                    
00166  */
00167 void
00168 restore_routing(struct s_trace **best_routing,
00169                 t_ivec ** clb_opins_used_locally,
00170                 t_ivec ** saved_clb_opins_used_locally)
00171 {
00172 
00173     int inet, iblk, ipin, iclass, num_local_opins;
00174     t_type_ptr type;
00175 
00176     for(inet = 0; inet < num_nets; inet++)
00177         {
00178 
00179             /* Free any current routing. */
00180             free_traceback(inet);
00181 
00182             /* Set the current routing to the saved one. */
00183             trace_head[inet] = best_routing[inet];
00184             best_routing[inet] = NULL;  /* No stored routing. */
00185         }
00186 
00187 /* Save which OPINs are locally used.                           */
00188 
00189     for(iblk = 0; iblk < num_blocks; iblk++)
00190         {
00191             type = block[iblk].type;
00192             for(iclass = 0; iclass < type->num_class; iclass++)
00193                 {
00194                     num_local_opins =
00195                         clb_opins_used_locally[iblk][iclass].nelem;
00196                     for(ipin = 0; ipin < num_local_opins; ipin++)
00197                         {
00198                             clb_opins_used_locally[iblk][iclass].list[ipin] =
00199                                 saved_clb_opins_used_locally[iblk][iclass].
00200                                 list[ipin];
00201                         }
00202                 }
00203 
00204         }
00205 }
00206 
00207 /** This routine finds a "magic cookie" for the routing and prints it.    
00208  * Use this number as a routing serial number to ensure that programming 
00209  * changes do not break the router.                                      
00210  */
00211 void
00212 get_serial_num(void)
00213 {
00214 
00215     int inet, serial_num, inode;
00216     struct s_trace *tptr;
00217 
00218     serial_num = 0;
00219 
00220     for(inet = 0; inet < num_nets; inet++)
00221         {
00222 
00223 /* Global nets will have null trace_heads (never routed) so they *
00224  * are not included in the serial number calculation.            */
00225 
00226             tptr = trace_head[inet];
00227             while(tptr != NULL)
00228                 {
00229                     inode = tptr->index;
00230                     serial_num +=
00231                         (inet + 1) * (rr_node[inode].xlow * (nx + 1) -
00232                                       rr_node[inode].yhigh);
00233 
00234                     serial_num -= rr_node[inode].ptc_num * (inet + 1) * 10;
00235 
00236                     serial_num -= rr_node[inode].type * (inet + 1) * 100;
00237                     serial_num %= 2000000000;   /* Prevent overflow */
00238                     tptr = tptr->next;
00239                 }
00240         }
00241     printf("Serial number (magic cookie) for the routing is: %d\n",
00242            serial_num);
00243 }
00244 
00245 /** Attempts a routing via an iterated maze router algorithm.  Width_fac 
00246  * specifies the relative width of the channels, while the members of   
00247  * router_opts determine the value of the costs assigned to routing     
00248  * resource node, etc.  det_routing_arch describes the detailed routing 
00249  * architecture (connection and switch boxes) of the FPGA; it is used   
00250  * only if a DETAILED routing has been selected.                        
00251  */
00252 boolean
00253 try_route(int width_fac,
00254           struct s_router_opts router_opts,
00255           struct s_det_routing_arch det_routing_arch,
00256           t_segment_inf * segment_inf,
00257           t_timing_inf timing_inf,
00258           float **net_slack,
00259           float **net_delay,
00260           t_chan_width_dist chan_width_dist,
00261           t_ivec ** clb_opins_used_locally,
00262           t_mst_edge ** mst,
00263           boolean * Fc_clipped)
00264 {
00265 
00266     int tmp;
00267         clock_t begin, end;
00268     boolean success;
00269         t_graph_type graph_type;
00270 
00271         if(router_opts.route_type == GLOBAL) {
00272                 graph_type = GRAPH_GLOBAL;
00273         } else {
00274                 graph_type = (det_routing_arch.directionality ==
00275                     BI_DIRECTIONAL ? GRAPH_BIDIR : GRAPH_UNIDIR);
00276         }
00277 
00278 /* Set the channel widths */
00279 
00280     init_chan(width_fac, chan_width_dist);
00281 
00282 /* Free any old routing graph, if one exists. */
00283 
00284     free_rr_graph();
00285 
00286         begin = clock();
00287 
00288 
00289 /* Set up the routing resource graph defined by this FPGA architecture. */
00290 
00291     build_rr_graph(graph_type,
00292                    num_types, type_descriptors, nx, ny, grid,
00293                    chan_width_x[0], NULL,
00294                    det_routing_arch.switch_block_type, det_routing_arch.Fs,
00295                    det_routing_arch.num_segment, det_routing_arch.num_switch, segment_inf,
00296                    det_routing_arch.global_route_switch,
00297                    det_routing_arch.delayless_switch, timing_inf,
00298                    det_routing_arch.wire_to_ipin_switch,
00299                    router_opts.base_cost_type, &tmp);
00300 
00301         end = clock();
00302         #ifdef CLOCKS_PER_SEC
00303                 printf("build rr_graph took %g seconds\n", (float)(end - begin) / CLOCKS_PER_SEC);
00304         #else
00305                 printf("build rr_graph took %g seconds\n", (float)(end - begin) / CLK_PER_SEC);
00306         #endif
00307 
00308 
00309 /* Allocate and load some additional rr_graph information needed only by *
00310  * the router.                                                           */
00311 
00312     alloc_and_load_rr_node_route_structs();
00313 
00314     init_route_structs(router_opts.bb_factor);
00315 
00316     if(router_opts.router_algorithm == BREADTH_FIRST)
00317         {
00318             printf("Confirming Router Algorithm: BREADTH_FIRST.\n");
00319             success =
00320                 try_breadth_first_route(router_opts, clb_opins_used_locally,
00321                                         width_fac);
00322         }
00323     else if(router_opts.router_algorithm == TIMING_DRIVEN)
00324         {                       /* TIMING_DRIVEN route */
00325             printf("Confirming Router Algorithm: TIMING_DRIVEN.\n");
00326             assert(router_opts.route_type != GLOBAL);
00327             success =
00328                 try_timing_driven_route(router_opts, net_slack, net_delay,
00329                                         clb_opins_used_locally);
00330         }
00331     else
00332         {                       /* Directed Search Routability Driven */
00333             printf("Confirming Router Algorithm: DIRECTED_SEARCH.\n");
00334             success =
00335                 try_directed_search_route(router_opts, clb_opins_used_locally,
00336                                           width_fac, mst);
00337         }
00338 
00339     free_rr_node_route_structs();
00340 
00341     return (success);
00342 }
00343 
00344 /** This routine checks to see if this is a resource-feasible routing.      
00345  * That is, are all rr_node capacity limitations respected?  It assumes    
00346  * that the occupancy arrays are up to date when it is called.             
00347  */
00348 boolean
00349 feasible_routing(void)
00350 {
00351 
00352     int inode;
00353 
00354         for(inode = 0; inode < num_rr_nodes; inode++) {
00355                 if(rr_node[inode].occ > rr_node[inode].capacity) {
00356                         return (FALSE);
00357                 }
00358         }
00359 
00360     return (TRUE);
00361 }
00362 
00363 /** This routine updates the occupancy and pres_cost of the rr_nodes that are 
00364  * affected by the portion of the routing of one net that starts at          
00365  * route_segment_start.  If route_segment_start is trace_head[inet], the     
00366  * cost of all the nodes in the routing of net inet are updated.  If         
00367  * add_or_sub is -1 the net (or net portion) is ripped up, if it is 1 the    
00368  * net is added to the routing.  The size of pres_fac determines how severly 
00369  * oversubscribed rr_nodes are penalized.                                    
00370  */
00371 void
00372 pathfinder_update_one_cost(struct s_trace *route_segment_start,
00373                            int add_or_sub,
00374                            float pres_fac)
00375 {
00376 
00377     struct s_trace *tptr;
00378     int inode, occ, capacity;
00379 
00380     tptr = route_segment_start;
00381     if(tptr == NULL)            /* No routing yet. */
00382         return;
00383 
00384     for(;;)
00385         {
00386             inode = tptr->index;
00387 
00388             occ = rr_node[inode].occ + add_or_sub;
00389             capacity = rr_node[inode].capacity;
00390 
00391             rr_node[inode].occ = occ;
00392 
00393 /* pres_cost is Pn in the Pathfinder paper. I set my pres_cost according to *
00394  * the overuse that would result from having ONE MORE net use this routing  *
00395  * node.                                                                    */
00396 
00397             if(occ < capacity)
00398                 {
00399                     rr_node_route_inf[inode].pres_cost = 1.;
00400                 }
00401             else
00402                 {
00403                     rr_node_route_inf[inode].pres_cost =
00404                         1. + (occ + 1 - capacity) * pres_fac;
00405                 }
00406 
00407             if(rr_node[inode].type == SINK)
00408                 {
00409                     tptr = tptr->next;  /* Skip next segment. */
00410                     if(tptr == NULL)
00411                         break;
00412                 }
00413 
00414             tptr = tptr->next;
00415 
00416         }                       /* End while loop -- did an entire traceback. */
00417 }
00418 
00419 /** This routine recomputes the pres_cost and acc_cost of each routing       
00420  * resource for the pathfinder algorithm after all nets have been routed.    
00421  * It updates the accumulated cost to by adding in the number of extra       
00422  * signals sharing a resource right now (i.e. after each complete iteration) 
00423  * times acc_fac.  It also updates pres_cost, since pres_fac may have        
00424  * changed.  THIS ROUTINE ASSUMES THE OCCUPANCY VALUES IN RR_NODE ARE UP TO  
00425  * DATE.                                                                     
00426  */
00427 void
00428 pathfinder_update_cost(float pres_fac,
00429                        float acc_fac)
00430 {
00431 
00432     int inode, occ, capacity;
00433 
00434     for(inode = 0; inode < num_rr_nodes; inode++)
00435         {
00436             occ = rr_node[inode].occ;
00437             capacity = rr_node[inode].capacity;
00438 
00439             if(occ > capacity)
00440                 {
00441                     rr_node_route_inf[inode].acc_cost +=
00442                         (occ - capacity) * acc_fac;
00443                     rr_node_route_inf[inode].pres_cost =
00444                         1. + (occ + 1 - capacity) * pres_fac;
00445                 }
00446 
00447 /* If occ == capacity, we don't need to increase acc_cost, but a change    *
00448  * in pres_fac could have made it necessary to recompute the cost anyway.  */
00449 
00450             else if(occ == capacity)
00451                 {
00452                     rr_node_route_inf[inode].pres_cost = 1. + pres_fac;
00453                 }
00454         }
00455 }
00456 
00457 /** Call this before you route any nets.  It frees any old traceback and   
00458  * sets the list of rr_nodes touched to empty.                            
00459  */
00460 void
00461 init_route_structs(int bb_factor)
00462 {
00463 
00464     int i;
00465 
00466     for(i = 0; i < num_nets; i++)
00467         free_traceback(i);
00468 
00469     load_route_bb(bb_factor);
00470 
00471 /* Check that things that should have been emptied after the last routing *
00472  * really were.                                                           */
00473 
00474     if(rr_modified_head != NULL)
00475         {
00476             printf
00477                 ("Error in init_route_structs.  List of modified rr nodes is \n"
00478                  "not empty.\n");
00479             exit(1);
00480         }
00481 
00482     if(heap_tail != 1)
00483         {
00484             printf("Error in init_route_structs.  Heap is not empty.\n");
00485             exit(1);
00486         }
00487 }
00488 
00489 /** This routine adds the most recently finished wire segment to the         
00490  * traceback linked list.  The first connection starts with the net SOURCE  
00491  * and begins at the structure pointed to by trace_head[inet]. Each         
00492  * connection ends with a SINK.  After each SINK, the next connection       
00493  * begins (if the net has more than 2 pins).  The first element after the   
00494  * SINK gives the routing node on a previous piece of the routing, which is 
00495  * the link from the existing net to this new piece of the net.             
00496  * In each traceback I start at the end of a path and trace back through    
00497  * its predecessors to the beginning.  I have stored information on the     
00498  * predecesser of each node to make traceback easy -- this sacrificies some 
00499  * memory for easier code maintenance.  This routine returns a pointer to   
00500  * the first "new" node in the traceback (node not previously in trace).    
00501  */
00502 struct s_trace *
00503 update_traceback(struct s_heap *hptr,
00504                  int inet)
00505 {
00506 
00507     struct s_trace *tptr, *prevptr, *temptail, *ret_ptr;
00508     int inode;
00509     short iedge;
00510 
00511 #ifdef DEBUG
00512     t_rr_type rr_type;
00513 #endif
00514 
00515     inode = hptr->index;
00516 
00517 #ifdef DEBUG
00518     rr_type = rr_node[inode].type;
00519     if(rr_type != SINK)
00520         {
00521             printf("Error in update_traceback.  Expected type = SINK (%d).\n",
00522                    SINK);
00523             printf("Got type = %d while tracing back net %d.\n", rr_type,
00524                    inet);
00525             exit(1);
00526         }
00527 #endif
00528 
00529     tptr = alloc_trace_data();  /* SINK on the end of the connection */
00530     tptr->index = inode;
00531     tptr->iswitch = OPEN;
00532     tptr->next = NULL;
00533     temptail = tptr;            /* This will become the new tail at the end */
00534     /* of the routine.                          */
00535 
00536 /* Now do it's predecessor. */
00537 
00538     inode = hptr->u.prev_node;
00539     iedge = hptr->prev_edge;
00540 
00541     while(inode != NO_PREVIOUS)
00542         {
00543             prevptr = alloc_trace_data();
00544             prevptr->index = inode;
00545             prevptr->iswitch = rr_node[inode].switches[iedge];
00546             prevptr->next = tptr;
00547             tptr = prevptr;
00548 
00549             iedge = rr_node_route_inf[inode].prev_edge;
00550             inode = rr_node_route_inf[inode].prev_node;
00551         }
00552 
00553     if(trace_tail[inet] != NULL)
00554         {
00555             trace_tail[inet]->next = tptr;      /* Traceback ends with tptr */
00556             ret_ptr = tptr->next;       /* First new segment.       */
00557         }
00558     else
00559         {                       /* This was the first "chunk" of the net's routing */
00560             trace_head[inet] = tptr;
00561             ret_ptr = tptr;     /* Whole traceback is new. */
00562         }
00563 
00564     trace_tail[inet] = temptail;
00565     return (ret_ptr);
00566 }
00567 
00568 /** The routine sets the path_cost to HUGE_FLOAT for all channel segments   
00569  * touched by previous routing phases.                                     
00570  */
00571 void
00572 reset_path_costs(void)
00573 {
00574 
00575     struct s_linked_f_pointer *mod_ptr;
00576 
00577 #ifdef DEBUG
00578     int num_mod_ptrs;
00579 #endif
00580 
00581 /* The traversal method below is slightly painful to make it faster. */
00582 
00583     if(rr_modified_head != NULL)
00584         {
00585             mod_ptr = rr_modified_head;
00586 
00587 #ifdef DEBUG
00588             num_mod_ptrs = 1;
00589 #endif
00590 
00591             while(mod_ptr->next != NULL)
00592                 {
00593                     *(mod_ptr->fptr) = HUGE_FLOAT;
00594                     mod_ptr = mod_ptr->next;
00595 #ifdef DEBUG
00596                     num_mod_ptrs++;
00597 #endif
00598                 }
00599             *(mod_ptr->fptr) = HUGE_FLOAT;      /* Do last one. */
00600 
00601 /* Reset the modified list and put all the elements back in the free   *
00602  * list.                                                               */
00603 
00604             mod_ptr->next = linked_f_pointer_free_head;
00605             linked_f_pointer_free_head = rr_modified_head;
00606             rr_modified_head = NULL;
00607 
00608 #ifdef DEBUG
00609             num_linked_f_pointer_allocated -= num_mod_ptrs;
00610 #endif
00611         }
00612 }
00613 
00614 
00615 /** Returns the *congestion* cost of using this rr_node. */
00616 float
00617 get_rr_cong_cost(int inode)
00618 {
00619     short cost_index;
00620     float cost;
00621 
00622     cost_index = rr_node[inode].cost_index;
00623     cost = rr_indexed_data[cost_index].base_cost *
00624         rr_node_route_inf[inode].acc_cost *
00625         rr_node_route_inf[inode].pres_cost;
00626     return (cost);
00627 }
00628 
00629 /** Mark all the SINKs of this net as targets by setting their target flags  
00630  * to the number of times the net must connect to each SINK.  Note that     
00631  * this number can occassionally be greater than 1 -- think of connecting   
00632  * the same net to two inputs of an and-gate (and-gate inputs are logically 
00633  * equivalent, so both will connect to the same SINK).                      
00634  */
00635 void
00636 mark_ends(int inet)
00637 {
00638 
00639     int ipin, inode;
00640 
00641     for(ipin = 1; ipin <= clb_net[inet].num_sinks; ipin++)
00642         {
00643             inode = net_rr_terminals[inet][ipin];
00644             rr_node_route_inf[inode].target_flag++;
00645         }
00646 }
00647 
00648 /** Puts an rr_node on the heap, if the new cost given is lower than the     
00649  * current path_cost to this channel segment.  The index of its predecessor 
00650  * is stored to make traceback easy.  The index of the edge used to get     
00651  * from its predecessor to it is also stored to make timing analysis, etc.  
00652  * easy.  The backward_path_cost and R_upstream values are used only by the 
00653  * timing-driven router -- the breadth-first router ignores them.           
00654  */
00655 void
00656 node_to_heap(int inode,
00657              float cost,
00658              int prev_node,
00659              int prev_edge,
00660              float backward_path_cost,
00661              float R_upstream)
00662 {
00663 
00664     struct s_heap *hptr;
00665 
00666     if(cost >= rr_node_route_inf[inode].path_cost)
00667         return;
00668 
00669     hptr = alloc_heap_data();
00670     hptr->index = inode;
00671     hptr->cost = cost;
00672     hptr->u.prev_node = prev_node;
00673     hptr->prev_edge = prev_edge;
00674     hptr->backward_path_cost = backward_path_cost;
00675     hptr->R_upstream = R_upstream;
00676     add_to_heap(hptr);
00677 }
00678 
00679 /** Puts the entire traceback (old routing) for this net on the free list 
00680  * and sets the trace_head pointers etc. for the net to NULL.            
00681  */
00682 void
00683 free_traceback(int inet)
00684 {
00685 
00686     struct s_trace *tptr, *tempptr;
00687 
00688     tptr = trace_head[inet];
00689 
00690     while(tptr != NULL)
00691         {
00692             tempptr = tptr->next;
00693             free_trace_data(tptr);
00694             tptr = tempptr;
00695         }
00696 
00697     trace_head[inet] = NULL;
00698     trace_tail[inet] = NULL;
00699 }
00700 
00701 
00702 /** Allocates the data structures needed for routing.    */
00703 t_ivec **
00704 alloc_route_structs()
00705 {
00706     t_ivec **clb_opins_used_locally;
00707 
00708         alloc_route_static_structs();
00709     clb_opins_used_locally =
00710         alloc_and_load_clb_opins_used_locally();
00711 
00712     return (clb_opins_used_locally);
00713 }
00714 
00715 void alloc_route_static_structs() {
00716     trace_head = (struct s_trace **)my_calloc(num_nets,
00717                                               sizeof(struct s_trace *));
00718     trace_tail = (struct s_trace **)my_malloc(num_nets *
00719                                               sizeof(struct s_trace *));
00720 
00721     heap_size = nx * ny;
00722     heap = (struct s_heap **)my_malloc(heap_size * sizeof(struct s_heap *));
00723     heap--;                     /* heap stores from [1..heap_size] */
00724     heap_tail = 1;
00725 
00726     route_bb = (struct s_bb *)my_malloc(num_nets * sizeof(struct s_bb));
00727 }
00728 
00729 /** Allocates data structures into which the key routing data can be saved,   
00730  * allowing the routing to be recovered later (e.g. after a another routing  
00731  * is attempted).                                                            
00732  */
00733 struct s_trace **
00734 alloc_saved_routing(t_ivec ** clb_opins_used_locally,
00735                     t_ivec *** saved_clb_opins_used_locally_ptr)
00736 {
00737 
00738     struct s_trace **best_routing;
00739     t_ivec **saved_clb_opins_used_locally;
00740     int iblk, iclass, num_local_opins;
00741     t_type_ptr type;
00742 
00743     best_routing = (struct s_trace **)my_calloc(num_nets,
00744                                                 sizeof(struct s_trace *));
00745 
00746     saved_clb_opins_used_locally =
00747         (t_ivec **) my_malloc(num_blocks * sizeof(t_ivec *));
00748 
00749     for(iblk = 0; iblk < num_blocks; iblk++)
00750         {
00751             type = block[iblk].type;
00752             saved_clb_opins_used_locally[iblk] =
00753                 (t_ivec *) my_malloc(type->num_class * sizeof(t_ivec));
00754             for(iclass = 0; iclass < type->num_class; iclass++)
00755                 {
00756                     num_local_opins =
00757                         clb_opins_used_locally[iblk][iclass].nelem;
00758                     saved_clb_opins_used_locally[iblk][iclass].nelem =
00759                         num_local_opins;
00760 
00761                     if(num_local_opins == 0)
00762                         {
00763                             saved_clb_opins_used_locally[iblk][iclass].list =
00764                                 NULL;
00765                         }
00766                     else
00767                         {
00768                             saved_clb_opins_used_locally[iblk][iclass].list =
00769                                 (int *)my_malloc(num_local_opins *
00770                                                  sizeof(int));
00771                         }
00772                 }
00773         }
00774 
00775     *saved_clb_opins_used_locally_ptr = saved_clb_opins_used_locally;
00776     return (best_routing);
00777 }
00778 
00779 /* TODO: probably now this whole function can be removed, must check correctness of routing so I will leave everything as is
00780 until I can golden check the routing before I do this massive code rewrite and performance optimizations */
00781 /** Allocates and loads the data needed to make the router reserve some CLB  
00782  * output pins for connections made locally within a CLB (if the netlist    
00783  * specifies that this is necessary).                                       
00784  */
00785 static t_ivec **
00786 alloc_and_load_clb_opins_used_locally()
00787 {
00788 
00789     t_ivec **clb_opins_used_locally;
00790     int iblk, clb_pin, iclass, num_local_opins;
00791     int class_low, class_high;
00792     t_type_ptr type;
00793 
00794     clb_opins_used_locally =
00795         (t_ivec **) my_malloc(num_blocks * sizeof(t_ivec *));
00796     
00797     for(iblk = 0; iblk < num_blocks; iblk++)
00798         {
00799             type = block[iblk].type;
00800             get_class_range_for_block(iblk, &class_low, &class_high);
00801             clb_opins_used_locally[iblk] =
00802                 (t_ivec *) my_malloc(type->num_class * sizeof(t_ivec));
00803             for(iclass = 0; iclass < type->num_class; iclass++)
00804                 clb_opins_used_locally[iblk][iclass].nelem = 0;
00805 
00806                 for(clb_pin = 0; clb_pin < type->num_pins; clb_pin++)
00807                 {
00808                     /* Subblock output used only locally, but must connect to a CLB OPIN?  */
00809                     if(block[iblk].nets[clb_pin] != OPEN
00810                                 && clb_net[block[iblk].nets[clb_pin]].num_sinks == 0)
00811                         {
00812                             iclass = type->pin_class[clb_pin];
00813                             /* Check to make sure class is in same range as that assigned to block */
00814                             assert(iclass >= class_low
00815                                    && iclass <= class_high);
00816                             clb_opins_used_locally[iblk][iclass].nelem++;
00817                         }
00818                 }
00819 
00820             for(iclass = 0; iclass < type->num_class; iclass++)
00821                 {
00822                     num_local_opins =
00823                         clb_opins_used_locally[iblk][iclass].nelem;
00824 
00825                     if(num_local_opins == 0)
00826                         clb_opins_used_locally[iblk][iclass].list = NULL;
00827                     else
00828                         clb_opins_used_locally[iblk][iclass].list =
00829                             (int *)my_malloc(num_local_opins * sizeof(int));
00830                 }
00831         }
00832 
00833     return (clb_opins_used_locally);
00834 }
00835 
00836 /** the trace lists are only freed after use by the timing-driven placer.
00837  * Do not free them after use by the router, since stats, and draw  
00838  * routines use the trace values 
00839  */
00840 void
00841 free_trace_structs(void)
00842 {
00843     int i;
00844 
00845     for(i = 0; i < num_nets; i++)
00846         free_traceback(i);
00847 
00848     free(trace_head);
00849     free(trace_tail);
00850     trace_head = NULL;
00851     trace_tail = NULL;
00852 }
00853 
00854 /** Frees the temporary storage needed only during the routing.  The  
00855  * final routing result is not freed.                                
00856  */
00857 void
00858 free_route_structs(t_ivec ** clb_opins_used_locally)
00859 {
00860 
00861     int i;
00862 
00863     free(heap + 1);
00864     free(route_bb);
00865 
00866     heap = NULL;                /* Defensive coding:  crash hard if I use these. */
00867     route_bb = NULL;
00868 
00869         if(clb_opins_used_locally != NULL) {
00870                 for(i = 0; i < num_blocks; i++)
00871                 {
00872                         free_ivec_vector(clb_opins_used_locally[i], 0,
00873                                          block[i].type->num_class - 1);
00874                 }
00875                 free(clb_opins_used_locally);
00876         }
00877 
00878 /* NB:  Should use my chunk_malloc for tptr, hptr, and mod_ptr structures. *
00879  * I could free everything except the tptrs at the end then.               */
00880 
00881 }
00882 
00883 
00884 /** Frees the data structures needed to save a routing.                     */
00885 void
00886 free_saved_routing(struct s_trace **best_routing,
00887                    t_ivec ** saved_clb_opins_used_locally)
00888 {
00889     int i;
00890 
00891     free(best_routing);
00892     for(i = 0; i < num_blocks; i++)
00893         {
00894             free_ivec_vector(saved_clb_opins_used_locally[i], 0,
00895                              block[i].type->num_class - 1);
00896         }
00897     free(saved_clb_opins_used_locally);
00898 }
00899 
00900 /** Allocates some extra information about each rr_node that is used only   
00901  * during routing.                                                         
00902  */
00903 void
00904 alloc_and_load_rr_node_route_structs(void)
00905 {
00906 
00907     int inode;
00908 
00909     if(rr_node_route_inf != NULL)
00910         {
00911             printf("Error in alloc_and_load_rr_node_route_structs:  \n"
00912                    "old rr_node_route_inf array exists.\n");
00913             exit(1);
00914         }
00915 
00916     rr_node_route_inf = my_malloc(num_rr_nodes * sizeof(t_rr_node_route_inf));
00917 
00918     for(inode = 0; inode < num_rr_nodes; inode++)
00919         {
00920             rr_node_route_inf[inode].prev_node = NO_PREVIOUS;
00921             rr_node_route_inf[inode].prev_edge = NO_PREVIOUS;
00922             rr_node_route_inf[inode].pres_cost = 1.;
00923             rr_node_route_inf[inode].acc_cost = 1.;
00924             rr_node_route_inf[inode].path_cost = HUGE_FLOAT;
00925             rr_node_route_inf[inode].target_flag = 0;
00926         }
00927 }
00928 
00929 /** Allocates some extra information about each rr_node that is used only   
00930  * during routing.                                                         
00931  */
00932 void
00933 reset_rr_node_route_structs(void)
00934 {
00935     int inode;
00936 
00937     assert(rr_node_route_inf != NULL);
00938 
00939     for(inode = 0; inode < num_rr_nodes; inode++)
00940         {
00941             rr_node_route_inf[inode].prev_node = NO_PREVIOUS;
00942             rr_node_route_inf[inode].prev_edge = NO_PREVIOUS;
00943             rr_node_route_inf[inode].pres_cost = 1.;
00944             rr_node_route_inf[inode].acc_cost = 1.;
00945             rr_node_route_inf[inode].path_cost = HUGE_FLOAT;
00946             rr_node_route_inf[inode].target_flag = 0;
00947         }
00948 }
00949 
00950 /** Frees the extra information about each rr_node that is needed only      
00951  * during routing.                                                         
00952  */
00953 void
00954 free_rr_node_route_structs(void)
00955 {
00956 
00957     free(rr_node_route_inf);
00958     rr_node_route_inf = NULL;   /* Mark as free */
00959 }
00960 
00961 /* RESEARCH TODO: Bounding box heuristic needs to be redone for heterogeneous blocks */
00962 /** This routine loads the bounding box arrays used to limit the space 
00963  * searched by the maze router when routing each net.  The search is   
00964  * limited to channels contained with the net bounding box expanded    
00965  * by bb_factor channels on each side.  For example, if bb_factor is   
00966  * 0, the maze router must route each net within its bounding box.     
00967  * If bb_factor = nx, the maze router will search every channel in     
00968  * the FPGA if necessary.  The bounding boxes returned by this routine 
00969  * are different from the ones used by the placer in that they are      
00970  * clipped to lie within (0,0) and (nx+1,ny+1) rather than (1,1) and   
00971  * (nx,ny).                                                            
00972  */
00973 static void
00974 load_route_bb(int bb_factor)
00975 {
00976 
00977     int k, xmax, ymax, xmin, ymin, x, y, inet;
00978 
00979     for(inet = 0; inet < num_nets; inet++)
00980         {
00981                 x = block[clb_net[inet].node_block[0]].x;
00982             y = block[clb_net[inet].node_block[0]].y + block[clb_net[inet].node_block[0]].type->pin_height[clb_net[inet].node_block_pin[0]];
00983 
00984             xmin = x;
00985             ymin = y;
00986             xmax = x;
00987             ymax = y;
00988 
00989             for(k = 1; k <= clb_net[inet].num_sinks; k++)
00990                 {
00991                     x = block[clb_net[inet].node_block[k]].x;
00992                     y = block[clb_net[inet].node_block[k]].y + block[clb_net[inet].node_block[k]].type->pin_height[clb_net[inet].node_block_pin[k]];
00993 
00994                     if(x < xmin)
00995                         {
00996                             xmin = x;
00997                         }
00998                     else if(x > xmax)
00999                         {
01000                             xmax = x;
01001                         }
01002 
01003                     if(y < ymin)
01004                         {
01005                             ymin = y;
01006                         }
01007                     else if(y > ymax)
01008                         {
01009                             ymax = y;
01010                         }
01011                 }
01012 
01013             /* Want the channels on all 4 sides to be usuable, even if bb_factor = 0. */
01014 
01015             xmin -= 1;
01016             ymin -= 1;
01017 
01018             /* Expand the net bounding box by bb_factor, then clip to the physical *
01019              * chip area.                                                          */
01020 
01021             route_bb[inet].xmin = max(xmin - bb_factor, 0);
01022             route_bb[inet].xmax = min(xmax + bb_factor, nx + 1);
01023             route_bb[inet].ymin = max(ymin - bb_factor, 0);
01024             route_bb[inet].ymax = min(ymax + bb_factor, ny + 1);
01025         }
01026 }
01027 
01028 /** This routine adds the floating point pointer (fptr) into a  
01029  * linked list that indicates all the pathcosts that have been 
01030  * modified thus far.                                          
01031  */
01032 void
01033 add_to_mod_list(float *fptr)
01034 {
01035 
01036     struct s_linked_f_pointer *mod_ptr;
01037 
01038     mod_ptr = alloc_linked_f_pointer();
01039 
01040 /* Add this element to the start of the modified list. */
01041 
01042     mod_ptr->next = rr_modified_head;
01043     mod_ptr->fptr = fptr;
01044     rr_modified_head = mod_ptr;
01045 }
01046 
01047 
01048 /** Adds an item to the heap, expanding the heap if necessary.             */
01049 static void
01050 add_to_heap(struct s_heap *hptr)
01051 {
01052     int ito, ifrom;
01053     struct s_heap *temp_ptr;
01054 
01055         if(heap_tail > heap_size)
01056         {                       /* Heap is full */
01057             heap_size *= 2;
01058             heap = my_realloc((void *)(heap + 1), heap_size *
01059                               sizeof(struct s_heap *));
01060             heap--;             /* heap goes from [1..heap_size] */
01061         }
01062 
01063     heap[heap_tail] = hptr;
01064     ifrom = heap_tail;
01065     ito = ifrom / 2;
01066     heap_tail++;
01067 
01068     while((ito >= 1) && (heap[ifrom]->cost < heap[ito]->cost))
01069         {
01070             temp_ptr = heap[ito];
01071             heap[ito] = heap[ifrom];
01072             heap[ifrom] = temp_ptr;
01073             ifrom = ito;
01074             ito = ifrom / 2;
01075         }
01076 }
01077 
01078 /** WMF: peeking accessor :) */
01079 boolean
01080 is_empty_heap(void)
01081 {
01082     return (heap_tail == 1);
01083 }
01084 
01085 /** Returns a pointer to the smallest element on the heap, or NULL if the    
01086  * heap is empty.  Invalid (index == OPEN) entries on the heap are never    
01087  * returned -- they are just skipped over.                                   
01088  */
01089 struct s_heap *
01090 get_heap_head(void)
01091 {
01092 
01093     int ito, ifrom;
01094     struct s_heap *heap_head, *temp_ptr;
01095 
01096     do
01097         {
01098             if(heap_tail == 1)
01099                 {               /* Empty heap. */
01100                     printf("Empty heap occurred in get_heap_head.\n");
01101                     printf
01102                         ("Some blocks are impossible to connect in this architecture.\n");
01103                     return (NULL);
01104                 }
01105 
01106             heap_head = heap[1];        /* Smallest element. */
01107 
01108             /* Now fix up the heap */
01109 
01110             heap_tail--;
01111             heap[1] = heap[heap_tail];
01112             ifrom = 1;
01113             ito = 2 * ifrom;
01114 
01115             while(ito < heap_tail)
01116                 {
01117                     if(heap[ito + 1]->cost < heap[ito]->cost)
01118                         ito++;
01119                     if(heap[ito]->cost > heap[ifrom]->cost)
01120                         break;
01121                     temp_ptr = heap[ito];
01122                     heap[ito] = heap[ifrom];
01123                     heap[ifrom] = temp_ptr;
01124                     ifrom = ito;
01125                     ito = 2 * ifrom;
01126                 }
01127 
01128         }
01129     while(heap_head->index == OPEN);    /* Get another one if invalid entry. */
01130 
01131     return (heap_head);
01132 }
01133 
01134 
01135 void
01136 empty_heap(void)
01137 {
01138 
01139     int i;
01140 
01141     for(i = 1; i < heap_tail; i++)
01142         free_heap_data(heap[i]);
01143 
01144     heap_tail = 1;
01145 }
01146 
01147 #define NCHUNK 200              /**< # of various structs malloced at a time. */
01148 
01149 
01150 static struct s_heap *
01151 alloc_heap_data(void)
01152 {
01153 
01154     int i;
01155     struct s_heap *temp_ptr;
01156 
01157     if(heap_free_head == NULL)
01158         {                       /* No elements on the free list */
01159             heap_free_head = (struct s_heap *)my_malloc(NCHUNK *
01160                                                         sizeof(struct
01161                                                                s_heap));
01162 
01163 /* If I want to free this memory, I have to store the original pointer *
01164  * somewhere.  Not worthwhile right now -- if you need more memory     *
01165  * for post-routing stages, look into it.                              */
01166 
01167             for(i = 0; i < NCHUNK - 1; i++)
01168                 (heap_free_head + i)->u.next = heap_free_head + i + 1;
01169             (heap_free_head + NCHUNK - 1)->u.next = NULL;
01170         }
01171 
01172     temp_ptr = heap_free_head;
01173     heap_free_head = heap_free_head->u.next;
01174 #ifdef DEBUG
01175     num_heap_allocated++;
01176 #endif
01177     return (temp_ptr);
01178 }
01179 
01180 
01181 void
01182 free_heap_data(struct s_heap *hptr)
01183 {
01184 
01185     hptr->u.next = heap_free_head;
01186     heap_free_head = hptr;
01187 #ifdef DEBUG
01188     num_heap_allocated--;
01189 #endif
01190 }
01191 
01192 /** Marks all the heap entries consisting of sink_node, where it was reached 
01193  * via ipin_node, as invalid (OPEN).  Used only by the breadth_first router 
01194  * and even then only in rare circumstances.                                
01195  */
01196 void
01197 invalidate_heap_entries(int sink_node,
01198                         int ipin_node)
01199 {
01200     int i;
01201 
01202     for(i = 1; i < heap_tail; i++)
01203         {
01204             if(heap[i]->index == sink_node
01205                && heap[i]->u.prev_node == ipin_node)
01206                 heap[i]->index = OPEN;  /* Invalid. */
01207         }
01208 }
01209 
01210 
01211 static struct s_trace *
01212 alloc_trace_data(void)
01213 {
01214 
01215     int i;
01216     struct s_trace *temp_ptr;
01217 
01218     if(trace_free_head == NULL)
01219         {                       /* No elements on the free list */
01220             trace_free_head = (struct s_trace *)my_malloc(NCHUNK *
01221                                                           sizeof(struct
01222                                                                  s_trace));
01223 
01224 /* If I want to free this memory, I have to store the original pointer *
01225  * somewhere.  Not worthwhile right now -- if you need more memory     *
01226  * for post-routing stages, look into it.                              */
01227 
01228             for(i = 0; i < NCHUNK - 1; i++)
01229                 (trace_free_head + i)->next = trace_free_head + i + 1;
01230             (trace_free_head + NCHUNK - 1)->next = NULL;
01231         }
01232     temp_ptr = trace_free_head;
01233     trace_free_head = trace_free_head->next;
01234 #ifdef DEBUG
01235     num_trace_allocated++;
01236 #endif
01237     return (temp_ptr);
01238 }
01239 
01240 
01241 /** Puts the traceback structure pointed to by tptr on the free list. */
01242 static void
01243 free_trace_data(struct s_trace *tptr)
01244 {
01245     tptr->next = trace_free_head;
01246     trace_free_head = tptr;
01247 #ifdef DEBUG
01248     num_trace_allocated--;
01249 #endif
01250 }
01251 
01252 /** This routine returns a linked list element with a float pointer as 
01253  * the node data.                                                     
01254  */
01255 static struct s_linked_f_pointer *
01256 alloc_linked_f_pointer(void)
01257 {
01258 
01259     int i;
01260     struct s_linked_f_pointer *temp_ptr;
01261 
01262     if(linked_f_pointer_free_head == NULL)
01263         {
01264             /* No elements on the free list */
01265             linked_f_pointer_free_head = (struct s_linked_f_pointer *)
01266                 my_malloc(NCHUNK * sizeof(struct s_linked_f_pointer));
01267 
01268 /* If I want to free this memory, I have to store the original pointer *
01269  * somewhere.  Not worthwhile right now -- if you need more memory     * 
01270  * for post-routing stages, look into it.                              */
01271 
01272             for(i = 0; i < NCHUNK - 1; i++)
01273                 {
01274                     (linked_f_pointer_free_head + i)->next =
01275                         linked_f_pointer_free_head + i + 1;
01276                 }
01277             (linked_f_pointer_free_head + NCHUNK - 1)->next = NULL;
01278         }
01279 
01280     temp_ptr = linked_f_pointer_free_head;
01281     linked_f_pointer_free_head = linked_f_pointer_free_head->next;
01282 
01283 #ifdef DEBUG
01284     num_linked_f_pointer_allocated++;
01285 #endif
01286 
01287     return (temp_ptr);
01288 }
01289 
01290 
01291 /** Prints out the routing to file route_file.  */
01292 void
01293 print_route(char *route_file)
01294 {
01295     int inet, inode, ipin, bnum, ilow, jlow, node_block_pin, iclass;
01296     t_rr_type rr_type;
01297     struct s_trace *tptr;
01298     char *name_type[] =
01299         { "SOURCE", "SINK", "IPIN", "OPIN", "CHANX", "CHANY", "INTRA_CLUSTER_EDGE" };
01300     FILE *fp;
01301 
01302     fp = fopen(route_file, "w");
01303 
01304     fprintf(fp, "Array size: %d x %d logic blocks.\n", nx, ny);
01305     fprintf(fp, "\nRouting:");
01306     for(inet = 0; inet < num_nets; inet++)
01307         {
01308             if(clb_net[inet].is_global == FALSE)
01309                 {
01310                         if(clb_net[inet].num_sinks == FALSE)
01311                         {
01312                                 fprintf(fp, "\n\nNet %d (%s)\n\n", inet, clb_net[inet].name);
01313                                 fprintf(fp, "\n\n Used in local cluster only, reserved one CLB pin\n\n");
01314                         } else {
01315                                 fprintf(fp, "\n\nNet %d (%s)\n\n", inet, clb_net[inet].name);
01316                                 tptr = trace_head[inet];
01317 
01318                                 while(tptr != NULL)
01319                                 {
01320                                         inode = tptr->index;
01321                                         rr_type = rr_node[inode].type;
01322                                         ilow = rr_node[inode].xlow;
01323                                         jlow = rr_node[inode].ylow;
01324 
01325                                         fprintf(fp, "%6s (%d,%d) ", name_type[rr_type],
01326                                                 ilow, jlow);
01327 
01328                                         if((ilow != rr_node[inode].xhigh) || (jlow !=
01329                                                                           rr_node
01330                                                                           [inode].
01331                                                                           yhigh))
01332                                         fprintf(fp, "to (%d,%d) ",
01333                                                 rr_node[inode].xhigh,
01334                                                 rr_node[inode].yhigh);
01335 
01336                                         switch (rr_type)
01337                                         {
01338 
01339                                         case IPIN:
01340                                         case OPIN:
01341                                                 if(grid[ilow][jlow].type == IO_TYPE)
01342                                                 {
01343                                                         fprintf(fp, " Pad: ");
01344                                                 }
01345                                                 else
01346                                                 {       /* IO Pad. */
01347                                                         fprintf(fp, " Pin: ");
01348                                                 }
01349                                                 break;
01350 
01351                                         case CHANX:
01352                                         case CHANY:
01353                                                 fprintf(fp, " Track: ");
01354                                                 break;
01355 
01356                                         case SOURCE:
01357                                         case SINK:
01358                                                 if(grid[ilow][jlow].type == IO_TYPE)
01359                                                 {
01360                                                         fprintf(fp, " Pad: ");
01361                                                 }
01362                                                 else
01363                                                 {       /* IO Pad. */
01364                                                         fprintf(fp, " Class: ");
01365                                                 }
01366                                                 break;
01367 
01368                                         default:
01369                                                 printf
01370                                                 ("Error in print_route:  Unexpected traceback element "
01371                                                  "type: %d (%s).\n", rr_type,
01372                                                  name_type[rr_type]);
01373                                                 exit(1);
01374                                                 break;
01375                                         }
01376 
01377                                         fprintf(fp, "%d  ", rr_node[inode].ptc_num);
01378 
01379         /* Uncomment line below if you're debugging and want to see the switch types *
01380          * used in the routing.                                                      */
01381         /*          fprintf (fp, "Switch: %d", tptr->iswitch);    */
01382 
01383                                         fprintf(fp, "\n");
01384 
01385                                         tptr = tptr->next;
01386                                 }
01387                         }
01388                 }
01389 
01390             else
01391                 {               /* Global net.  Never routed. */
01392                     fprintf(fp, "\n\nNet %d (%s): global net connecting:\n\n",
01393                             inet, clb_net[inet].name);
01394 
01395                     for(ipin = 0; ipin <= clb_net[inet].num_sinks; ipin++)
01396                         {
01397                             bnum = clb_net[inet].node_block[ipin];
01398 
01399                             node_block_pin = clb_net[inet].node_block_pin[ipin];
01400                             iclass =
01401                                 block[bnum].type->pin_class[node_block_pin];
01402 
01403                             fprintf(fp,
01404                                     "Block %s (#%d) at (%d, %d), Pin class %d.\n",
01405                                     block[bnum].name, bnum, block[bnum].x,
01406                                     block[bnum].y, iclass);
01407                         }
01408                 }
01409         }
01410 
01411     fclose(fp);
01412 
01413 #ifdef CREATE_ECHO_FILES
01414     fp = my_fopen("mem.echo", "w", 0);
01415     fprintf(fp, "\nNum_heap_allocated: %d   Num_trace_allocated: %d\n",
01416             num_heap_allocated, num_trace_allocated);
01417     fprintf(fp, "Num_linked_f_pointer_allocated: %d\n",
01418             num_linked_f_pointer_allocated);
01419     fclose(fp);
01420 #endif /* CREATE_ECHO_FILES */
01421 
01422 }
01423 
01424 /* TODO: check if this is still necessary for speed */
01425 void
01426 reserve_locally_used_opins(float pres_fac,
01427                            boolean rip_up_local_opins,
01428                            t_ivec ** clb_opins_used_locally)
01429 {
01430 
01431 /* In the past, this function implicitly allowed LUT duplication when there are free LUTs. 
01432 This was especially important for logical equivalence; however, now that we have a very general
01433 logic cluster, it does not make sense to allow LUT duplication implicitly. we'll need to look into how we want to handle this case
01434 
01435 */
01436 
01437     int iblk, num_local_opin, inode, from_node, iconn, num_edges, to_node;
01438     int iclass, ipin;
01439     float cost;
01440     struct s_heap *heap_head_ptr;
01441     t_type_ptr type;
01442 
01443     if(rip_up_local_opins)
01444         {
01445             for(iblk = 0; iblk < num_blocks; iblk++)
01446                 {
01447                     type = block[iblk].type;
01448                     for(iclass = 0; iclass < type->num_class; iclass++)
01449                         {
01450                             num_local_opin =
01451                                 clb_opins_used_locally[iblk][iclass].nelem;
01452                             /* Always 0 for pads and for RECEIVER (IPIN) classes */
01453                             for(ipin = 0; ipin < num_local_opin; ipin++)
01454                                 {
01455                                     inode =
01456                                         clb_opins_used_locally[iblk][iclass].
01457                                         list[ipin];
01458                                     adjust_one_rr_occ_and_pcost(inode, -1,
01459                                                                 pres_fac);
01460                                 }
01461                         }
01462                 }
01463         }
01464 
01465     for(iblk = 0; iblk < num_blocks; iblk++)
01466         {
01467             type = block[iblk].type;
01468             for(iclass = 0; iclass < type->num_class; iclass++)
01469                 {
01470                     num_local_opin =
01471                         clb_opins_used_locally[iblk][iclass].nelem;
01472                     /* Always 0 for pads and for RECEIVER (IPIN) classes */
01473 
01474                     if(num_local_opin != 0)
01475                         {       /* Have to reserve (use) some OPINs */
01476                             from_node = rr_blk_source[iblk][iclass];
01477                             num_edges = rr_node[from_node].num_edges;
01478                             for(iconn = 0; iconn < num_edges; iconn++)
01479                                 {
01480                                     to_node = rr_node[from_node].edges[iconn];
01481                                     cost = get_rr_cong_cost(to_node);
01482                                     node_to_heap(to_node, cost, OPEN, OPEN,
01483                                                  0., 0.);
01484                                 }
01485 
01486                             for(ipin = 0; ipin < num_local_opin; ipin++)
01487                                 {
01488                                     heap_head_ptr = get_heap_head();
01489                                     inode = heap_head_ptr->index;
01490                                     adjust_one_rr_occ_and_pcost(inode, 1,
01491                                                                 pres_fac);
01492                                     clb_opins_used_locally[iblk][iclass].
01493                                         list[ipin] = inode;
01494                                     free_heap_data(heap_head_ptr);
01495                                 }
01496 
01497                             empty_heap();
01498                         }
01499                 }
01500         }
01501 }
01502 
01503 /** Increments or decrements (depending on add_or_sub) the occupancy of    
01504  * one rr_node, and adjusts the present cost of that node appropriately.  
01505  */
01506 static void
01507 adjust_one_rr_occ_and_pcost(int inode,
01508                             int add_or_sub,
01509                             float pres_fac)
01510 {
01511 
01512     int occ, capacity;
01513 
01514     occ = rr_node[inode].occ + add_or_sub;
01515     capacity = rr_node[inode].capacity;
01516     rr_node[inode].occ = occ;
01517 
01518     if(occ < capacity)
01519         {
01520             rr_node_route_inf[inode].pres_cost = 1.;
01521         }
01522     else
01523         {
01524             rr_node_route_inf[inode].pres_cost = 1. + (occ + 1 - capacity) *
01525                 pres_fac;
01526         }
01527 }