SRC/route_common.h File Reference

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  s_heap
struct  t_rr_node_route_inf

Functions

void pathfinder_update_one_cost (struct s_trace *route_segment_start, int add_or_sub, float pres_fac)
void pathfinder_update_cost (float pres_fac, float acc_fac)
struct s_traceupdate_traceback (struct s_heap *hptr, int inet)
void reset_path_costs (void)
float get_rr_cong_cost (int inode)
void mark_ends (int inet)
void node_to_heap (int inode, float cost, int prev_node, int prev_edge, float backward_path_cost, float R_upstream)
boolean is_empty_heap (void)
void free_traceback (int inet)
void add_to_mod_list (float *fptr)
struct s_heapget_heap_head (void)
void empty_heap (void)
void free_heap_data (struct s_heap *hptr)
void invalidate_heap_entries (int sink_node, int ipin_node)
void init_route_structs (int bb_factor)
void free_rr_node_route_structs (void)
void alloc_and_load_rr_node_route_structs (void)
void free_trace_structs (void)
void reserve_locally_used_opins (float pres_fac, boolean rip_up_local_opins, t_ivec **fb_opins_used_locally)

Variables

t_rr_node_route_infrr_node_route_inf
struct s_bbroute_bb

Function Documentation

void add_to_mod_list ( float *  fptr  ) 

Definition at line 1018 of file route_common.c.

01019 {
01020 
01021 /* This routine adds the floating point pointer (fptr) into a  *
01022  * linked list that indicates all the pathcosts that have been *
01023  * modified thus far.                                          */
01024 
01025     struct s_linked_f_pointer *mod_ptr;
01026 
01027     mod_ptr = alloc_linked_f_pointer();
01028 
01029 /* Add this element to the start of the modified list. */
01030 
01031     mod_ptr->next = rr_modified_head;
01032     mod_ptr->fptr = fptr;
01033     rr_modified_head = mod_ptr;
01034 }

Here is the call graph for this function:

Here is the caller graph for this function:

void alloc_and_load_rr_node_route_structs ( void   ) 

Definition at line 909 of file route_common.c.

00910 {
00911 
00912 /* Allocates some extra information about each rr_node that is used only   *
00913  * during routing.                                                         */
00914 
00915     int inode;
00916 
00917     if(rr_node_route_inf != NULL)
00918         {
00919             printf("Error in alloc_and_load_rr_node_route_structs:  \n"
00920                    "old rr_node_route_inf array exists.\n");
00921             exit(1);
00922         }
00923 
00924     rr_node_route_inf = my_malloc(num_rr_nodes * sizeof(t_rr_node_route_inf));
00925 
00926     for(inode = 0; inode < num_rr_nodes; inode++)
00927         {
00928             rr_node_route_inf[inode].prev_node = NO_PREVIOUS;
00929             rr_node_route_inf[inode].prev_edge = NO_PREVIOUS;
00930             rr_node_route_inf[inode].pres_cost = 1.;
00931             rr_node_route_inf[inode].acc_cost = 1.;
00932             rr_node_route_inf[inode].path_cost = HUGE_FLOAT;
00933             rr_node_route_inf[inode].target_flag = 0;
00934         }
00935 }

Here is the call graph for this function:

Here is the caller graph for this function:

void empty_heap ( void   ) 

Definition at line 1127 of file route_common.c.

01128 {
01129 
01130     int i;
01131 
01132     for(i = 1; i < heap_tail; i++)
01133         free_heap_data(heap[i]);
01134 
01135     heap_tail = 1;
01136 }

Here is the call graph for this function:

Here is the caller graph for this function:

void free_heap_data ( struct s_heap hptr  ) 

Definition at line 1173 of file route_common.c.

01174 {
01175 
01176     hptr->u.next = heap_free_head;
01177     heap_free_head = hptr;
01178 #ifdef DEBUG
01179     num_heap_allocated--;
01180 #endif
01181 }

Here is the caller graph for this function:

void free_rr_node_route_structs ( void   ) 

Definition at line 939 of file route_common.c.

00940 {
00941 
00942 /* Frees the extra information about each rr_node that is needed only      *
00943  * during routing.                                                         */
00944 
00945     free(rr_node_route_inf);
00946     rr_node_route_inf = NULL;   /* Mark as free */
00947 }

Here is the caller graph for this function:

void free_trace_structs ( void   ) 

Definition at line 847 of file route_common.c.

00848 {
00849     /*the trace lists are only freed after use by the timing-driven placer */
00850     /*Do not  free them after use by the router, since stats, and draw  */
00851     /*routines use the trace values */
00852     int i;
00853 
00854     for(i = 0; i < num_nets; i++)
00855         free_traceback(i);
00856 
00857     free(trace_head);
00858     free(trace_tail);
00859     trace_head = NULL;
00860     trace_tail = NULL;
00861 }

Here is the call graph for this function:

Here is the caller graph for this function:

void free_traceback ( int  inet  ) 

Definition at line 680 of file route_common.c.

00681 {
00682 
00683 /* Puts the entire traceback (old routing) for this net on the free list *
00684  * and sets the trace_head pointers etc. for the net to NULL.            */
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 }

Here is the call graph for this function:

Here is the caller graph for this function:

struct s_heap* get_heap_head ( void   )  [read]

Definition at line 1077 of file route_common.c.

01078 {
01079 
01080 /* Returns a pointer to the smallest element on the heap, or NULL if the     *
01081  * heap is empty.  Invalid (index == OPEN) entries on the heap are never     *
01082  * returned -- they are just skipped over.                                   */
01083 
01084     int ito, ifrom;
01085     struct s_heap *heap_head, *temp_ptr;
01086 
01087     do
01088         {
01089             if(heap_tail == 1)
01090                 {               /* Empty heap. */
01091                     printf("Empty heap occurred in get_heap_head.\n");
01092                     printf
01093                         ("Some blocks are impossible to connect in this architecture.\n");
01094                     return (NULL);
01095                 }
01096 
01097             heap_head = heap[1];        /* Smallest element. */
01098 
01099             /* Now fix up the heap */
01100 
01101             heap_tail--;
01102             heap[1] = heap[heap_tail];
01103             ifrom = 1;
01104             ito = 2 * ifrom;
01105 
01106             while(ito < heap_tail)
01107                 {
01108                     if(heap[ito + 1]->cost < heap[ito]->cost)
01109                         ito++;
01110                     if(heap[ito]->cost > heap[ifrom]->cost)
01111                         break;
01112                     temp_ptr = heap[ito];
01113                     heap[ito] = heap[ifrom];
01114                     heap[ifrom] = temp_ptr;
01115                     ifrom = ito;
01116                     ito = 2 * ifrom;
01117                 }
01118 
01119         }
01120     while(heap_head->index == OPEN);    /* Get another one if invalid entry. */
01121 
01122     return (heap_head);
01123 }

Here is the caller graph for this function:

float get_rr_cong_cost ( int  inode  ) 

Definition at line 611 of file route_common.c.

00612 {
00613 
00614 /* Returns the *congestion* cost of using this rr_node. */
00615 
00616     short cost_index;
00617     float cost;
00618 
00619     cost_index = rr_node[inode].cost_index;
00620     cost = rr_indexed_data[cost_index].base_cost *
00621         rr_node_route_inf[inode].acc_cost *
00622         rr_node_route_inf[inode].pres_cost;
00623     return (cost);
00624 }

Here is the caller graph for this function:

void init_route_structs ( int  bb_factor  ) 

Definition at line 451 of file route_common.c.

00452 {
00453 
00454 /* Call this before you route any nets.  It frees any old traceback and   *
00455  * sets the list of rr_nodes touched to empty.                            */
00456 
00457     int i;
00458 
00459     for(i = 0; i < num_nets; i++)
00460         free_traceback(i);
00461 
00462     load_route_bb(bb_factor);
00463 
00464 /* Check that things that should have been emptied after the last routing *
00465  * really were.                                                           */
00466 
00467     if(rr_modified_head != NULL)
00468         {
00469             printf
00470                 ("Error in init_route_structs.  List of modified rr nodes is \n"
00471                  "not empty.\n");
00472             exit(1);
00473         }
00474 
00475     if(heap_tail != 1)
00476         {
00477             printf("Error in init_route_structs.  Heap is not empty.\n");
00478             exit(1);
00479         }
00480 }

Here is the call graph for this function:

Here is the caller graph for this function:

void invalidate_heap_entries ( int  sink_node,
int  ipin_node 
)

Definition at line 1185 of file route_common.c.

01187 {
01188 
01189 /* Marks all the heap entries consisting of sink_node, where it was reached *
01190  * via ipin_node, as invalid (OPEN).  Used only by the breadth_first router *
01191  * and even then only in rare circumstances.                                */
01192 
01193     int i;
01194 
01195     for(i = 1; i < heap_tail; i++)
01196         {
01197             if(heap[i]->index == sink_node
01198                && heap[i]->u.prev_node == ipin_node)
01199                 heap[i]->index = OPEN;  /* Invalid. */
01200         }
01201 }

Here is the caller graph for this function:

boolean is_empty_heap ( void   ) 

Definition at line 1071 of file route_common.c.

01072 {
01073     return (heap_tail == 1);
01074 }

Here is the caller graph for this function:

void mark_ends ( int  inet  ) 

Definition at line 628 of file route_common.c.

00629 {
00630 
00631 /* Mark all the SINKs of this net as targets by setting their target flags  *
00632  * to the number of times the net must connect to each SINK.  Note that     *
00633  * this number can occassionally be greater than 1 -- think of connecting   *
00634  * the same net to two inputs of an and-gate (and-gate inputs are logically *
00635  * equivalent, so both will connect to the same SINK).                      */
00636 
00637     int ipin, inode;
00638 
00639     for(ipin = 1; ipin <= net[inet].num_sinks; ipin++)
00640         {
00641             inode = net_rr_terminals[inet][ipin];
00642             rr_node_route_inf[inode].target_flag++;
00643         }
00644 }

Here is the caller graph for this function:

void node_to_heap ( int  inode,
float  cost,
int  prev_node,
int  prev_edge,
float  backward_path_cost,
float  R_upstream 
)

Definition at line 648 of file route_common.c.

00654 {
00655 
00656 /* Puts an rr_node on the heap, if the new cost given is lower than the     *
00657  * current path_cost to this channel segment.  The index of its predecessor *
00658  * is stored to make traceback easy.  The index of the edge used to get     *
00659  * from its predecessor to it is also stored to make timing analysis, etc.  *
00660  * easy.  The backward_path_cost and R_upstream values are used only by the *
00661  * timing-driven router -- the breadth-first router ignores them.           */
00662 
00663     struct s_heap *hptr;
00664 
00665     if(cost >= rr_node_route_inf[inode].path_cost)
00666         return;
00667 
00668     hptr = alloc_heap_data();
00669     hptr->index = inode;
00670     hptr->cost = cost;
00671     hptr->u.prev_node = prev_node;
00672     hptr->prev_edge = prev_edge;
00673     hptr->backward_path_cost = backward_path_cost;
00674     hptr->R_upstream = R_upstream;
00675     add_to_heap(hptr);
00676 }

Here is the call graph for this function:

Here is the caller graph for this function:

void pathfinder_update_cost ( float  pres_fac,
float  acc_fac 
)

Definition at line 412 of file route_common.c.

00414 {
00415 
00416 /* This routine recomputes the pres_cost and acc_cost of each routing        *
00417  * resource for the pathfinder algorithm after all nets have been routed.    *
00418  * It updates the accumulated cost to by adding in the number of extra       *
00419  * signals sharing a resource right now (i.e. after each complete iteration) *
00420  * times acc_fac.  It also updates pres_cost, since pres_fac may have        *
00421  * changed.  THIS ROUTINE ASSUMES THE OCCUPANCY VALUES IN RR_NODE ARE UP TO  *
00422  * DATE.                                                                     */
00423 
00424     int inode, occ, capacity;
00425 
00426     for(inode = 0; inode < num_rr_nodes; inode++)
00427         {
00428             occ = rr_node[inode].occ;
00429             capacity = rr_node[inode].capacity;
00430 
00431             if(occ > capacity)
00432                 {
00433                     rr_node_route_inf[inode].acc_cost +=
00434                         (occ - capacity) * acc_fac;
00435                     rr_node_route_inf[inode].pres_cost =
00436                         1. + (occ + 1 - capacity) * pres_fac;
00437                 }
00438 
00439 /* If occ == capacity, we don't need to increase acc_cost, but a change    *
00440  * in pres_fac could have made it necessary to recompute the cost anyway.  */
00441 
00442             else if(occ == capacity)
00443                 {
00444                     rr_node_route_inf[inode].pres_cost = 1. + pres_fac;
00445                 }
00446         }
00447 }

Here is the caller graph for this function:

void pathfinder_update_one_cost ( struct s_trace route_segment_start,
int  add_or_sub,
float  pres_fac 
)

Definition at line 355 of file route_common.c.

00358 {
00359 
00360 /* This routine updates the occupancy and pres_cost of the rr_nodes that are *
00361  * affected by the portion of the routing of one net that starts at          *
00362  * route_segment_start.  If route_segment_start is trace_head[inet], the     *
00363  * cost of all the nodes in the routing of net inet are updated.  If         *
00364  * add_or_sub is -1 the net (or net portion) is ripped up, if it is 1 the    *
00365  * net is added to the routing.  The size of pres_fac determines how severly *
00366  * oversubscribed rr_nodes are penalized.                                    */
00367 
00368     struct s_trace *tptr;
00369     int inode, occ, capacity;
00370 
00371     tptr = route_segment_start;
00372     if(tptr == NULL)            /* No routing yet. */
00373         return;
00374 
00375     for(;;)
00376         {
00377             inode = tptr->index;
00378 
00379             occ = rr_node[inode].occ + add_or_sub;
00380             capacity = rr_node[inode].capacity;
00381 
00382             rr_node[inode].occ = occ;
00383 
00384 /* pres_cost is Pn in the Pathfinder paper. I set my pres_cost according to *
00385  * the overuse that would result from having ONE MORE net use this routing  *
00386  * node.                                                                    */
00387 
00388             if(occ < capacity)
00389                 {
00390                     rr_node_route_inf[inode].pres_cost = 1.;
00391                 }
00392             else
00393                 {
00394                     rr_node_route_inf[inode].pres_cost =
00395                         1. + (occ + 1 - capacity) * pres_fac;
00396                 }
00397 
00398             if(rr_node[inode].type == SINK)
00399                 {
00400                     tptr = tptr->next;  /* Skip next segment. */
00401                     if(tptr == NULL)
00402                         break;
00403                 }
00404 
00405             tptr = tptr->next;
00406 
00407         }                       /* End while loop -- did an entire traceback. */
00408 }

Here is the caller graph for this function:

void reserve_locally_used_opins ( float  pres_fac,
boolean  rip_up_local_opins,
t_ivec **  fb_opins_used_locally 
)

Definition at line 1418 of file route_common.c.

01421 {
01422 
01423 /* If some subblock outputs are hooked directly to FB outputs, then      *
01424  * some FB outputs are occupied if their associated subblock is used     *
01425  * locally, even though the inter-FB netlist does not say those outputs  *
01426  * have to connect to anything.  This is important when you have          *
01427  * logically equivalent outputs.  Code below makes sure any FB outputs   *
01428  * that are used by being directly hooked to subblocks get properly       *
01429  * reserved.                                                              */
01430 
01431     int iblk, num_local_opin, inode, from_node, iconn, num_edges, to_node;
01432     int iclass, ipin;
01433     float cost;
01434     struct s_heap *heap_head_ptr;
01435     t_type_ptr type;
01436 
01437     if(rip_up_local_opins)
01438         {
01439             for(iblk = 0; iblk < num_blocks; iblk++)
01440                 {
01441                     type = block[iblk].type;
01442                     for(iclass = 0; iclass < type->num_class; iclass++)
01443                         {
01444                             num_local_opin =
01445                                 fb_opins_used_locally[iblk][iclass].nelem;
01446                             /* Always 0 for pads and for RECEIVER (IPIN) classes */
01447                             for(ipin = 0; ipin < num_local_opin; ipin++)
01448                                 {
01449                                     inode =
01450                                         fb_opins_used_locally[iblk][iclass].
01451                                         list[ipin];
01452                                     adjust_one_rr_occ_and_pcost(inode, -1,
01453                                                                 pres_fac);
01454                                 }
01455                         }
01456                 }
01457         }
01458 
01459     for(iblk = 0; iblk < num_blocks; iblk++)
01460         {
01461             type = block[iblk].type;
01462             for(iclass = 0; iclass < type->num_class; iclass++)
01463                 {
01464                     num_local_opin =
01465                         fb_opins_used_locally[iblk][iclass].nelem;
01466                     /* Always 0 for pads and for RECEIVER (IPIN) classes */
01467 
01468                     if(num_local_opin != 0)
01469                         {       /* Have to reserve (use) some OPINs */
01470                             from_node = rr_blk_source[iblk][iclass];
01471                             num_edges = rr_node[from_node].num_edges;
01472                             for(iconn = 0; iconn < num_edges; iconn++)
01473                                 {
01474                                     to_node = rr_node[from_node].edges[iconn];
01475                                     cost = get_rr_cong_cost(to_node);
01476                                     node_to_heap(to_node, cost, OPEN, OPEN,
01477                                                  0., 0.);
01478                                 }
01479 
01480                             for(ipin = 0; ipin < num_local_opin; ipin++)
01481                                 {
01482                                     heap_head_ptr = get_heap_head();
01483                                     inode = heap_head_ptr->index;
01484                                     adjust_one_rr_occ_and_pcost(inode, 1,
01485                                                                 pres_fac);
01486                                     fb_opins_used_locally[iblk][iclass].
01487                                         list[ipin] = inode;
01488                                     free_heap_data(heap_head_ptr);
01489                                 }
01490 
01491                             empty_heap();
01492                         }
01493                 }
01494         }
01495 }

Here is the call graph for this function:

Here is the caller graph for this function:

void reset_path_costs ( void   ) 

Definition at line 564 of file route_common.c.

00565 {
00566 
00567 /* The routine sets the path_cost to HUGE_FLOAT for all channel segments   *
00568  * touched by previous routing phases.                                     */
00569 
00570     struct s_linked_f_pointer *mod_ptr;
00571 
00572 #ifdef DEBUG
00573     int num_mod_ptrs;
00574 #endif
00575 
00576 /* The traversal method below is slightly painful to make it faster. */
00577 
00578     if(rr_modified_head != NULL)
00579         {
00580             mod_ptr = rr_modified_head;
00581 
00582 #ifdef DEBUG
00583             num_mod_ptrs = 1;
00584 #endif
00585 
00586             while(mod_ptr->next != NULL)
00587                 {
00588                     *(mod_ptr->fptr) = HUGE_FLOAT;
00589                     mod_ptr = mod_ptr->next;
00590 #ifdef DEBUG
00591                     num_mod_ptrs++;
00592 #endif
00593                 }
00594             *(mod_ptr->fptr) = HUGE_FLOAT;      /* Do last one. */
00595 
00596 /* Reset the modified list and put all the elements back in the free   *
00597  * list.                                                               */
00598 
00599             mod_ptr->next = linked_f_pointer_free_head;
00600             linked_f_pointer_free_head = rr_modified_head;
00601             rr_modified_head = NULL;
00602 
00603 #ifdef DEBUG
00604             num_linked_f_pointer_allocated -= num_mod_ptrs;
00605 #endif
00606         }
00607 }

Here is the caller graph for this function:

struct s_trace* update_traceback ( struct s_heap hptr,
int  inet 
) [read]

Definition at line 484 of file route_common.c.

00486 {
00487 
00488 /* This routine adds the most recently finished wire segment to the         *
00489  * traceback linked list.  The first connection starts with the net SOURCE  *
00490  * and begins at the structure pointed to by trace_head[inet]. Each         *
00491  * connection ends with a SINK.  After each SINK, the next connection       *
00492  * begins (if the net has more than 2 pins).  The first element after the   *
00493  * SINK gives the routing node on a previous piece of the routing, which is *
00494  * the link from the existing net to this new piece of the net.             *
00495  * In each traceback I start at the end of a path and trace back through    *
00496  * its predecessors to the beginning.  I have stored information on the     *
00497  * predecesser of each node to make traceback easy -- this sacrificies some *
00498  * memory for easier code maintenance.  This routine returns a pointer to   *
00499  * the first "new" node in the traceback (node not previously in trace).    */
00500 
00501     struct s_trace *tptr, *prevptr, *temptail, *ret_ptr;
00502     int inode;
00503     short iedge;
00504 
00505 #ifdef DEBUG
00506     t_rr_type rr_type;
00507 #endif
00508 
00509     inode = hptr->index;
00510 
00511 #ifdef DEBUG
00512     rr_type = rr_node[inode].type;
00513     if(rr_type != SINK)
00514         {
00515             printf("Error in update_traceback.  Expected type = SINK (%d).\n",
00516                    SINK);
00517             printf("Got type = %d while tracing back net %d.\n", rr_type,
00518                    inet);
00519             exit(1);
00520         }
00521 #endif
00522 
00523     tptr = alloc_trace_data();  /* SINK on the end of the connection */
00524     tptr->index = inode;
00525     tptr->iswitch = OPEN;
00526     tptr->next = NULL;
00527     temptail = tptr;            /* This will become the new tail at the end */
00528     /* of the routine.                          */
00529 
00530 /* Now do it's predecessor. */
00531 
00532     inode = hptr->u.prev_node;
00533     iedge = hptr->prev_edge;
00534 
00535     while(inode != NO_PREVIOUS)
00536         {
00537             prevptr = alloc_trace_data();
00538             prevptr->index = inode;
00539             prevptr->iswitch = rr_node[inode].switches[iedge];
00540             prevptr->next = tptr;
00541             tptr = prevptr;
00542 
00543             iedge = rr_node_route_inf[inode].prev_edge;
00544             inode = rr_node_route_inf[inode].prev_node;
00545         }
00546 
00547     if(trace_tail[inet] != NULL)
00548         {
00549             trace_tail[inet]->next = tptr;      /* Traceback ends with tptr */
00550             ret_ptr = tptr->next;       /* First new segment.       */
00551         }
00552     else
00553         {                       /* This was the first "chunk" of the net's routing */
00554             trace_head[inet] = tptr;
00555             ret_ptr = tptr;     /* Whole traceback is new. */
00556         }
00557 
00558     trace_tail[inet] = temptail;
00559     return (ret_ptr);
00560 }

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

struct s_bb* route_bb

Definition at line 22 of file route_common.c.

Definition at line 20 of file route_common.c.


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