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_trace * | update_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_heap * | get_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_inf * | rr_node_route_inf |
struct s_bb * | route_bb |
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
boolean is_empty_heap | ( | void | ) |
Definition at line 1071 of file route_common.c.
01072 { 01073 return (heap_tail == 1); 01074 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
Definition at line 22 of file route_common.c.
Definition at line 20 of file route_common.c.