00001 #include <math.h>
00002 #include <stdio.h>
00003 #include <assert.h>
00004 #include "util.h"
00005 #include "vpr_types.h"
00006 #include "vpr_utils.h"
00007 #include "globals.h"
00008 #include "mst.h"
00009 #include "route_export.h"
00010 #include "route_common.h"
00011 #include "route_tree_timing.h"
00012 #include "route_timing.h"
00013 #include "route_breadth_first.h"
00014 #include "route_directed_search.h"
00015 #include "place_and_route.h"
00016 #include "rr_graph.h"
00017
00018
00019
00020 t_rr_node_route_inf *rr_node_route_inf = NULL;
00021
00022 struct s_bb *route_bb = NULL;
00023
00024
00025
00026
00027
00028
00029 static struct s_heap **heap;
00030 static int heap_size;
00031 static int heap_tail;
00032
00033
00034 static struct s_heap *heap_free_head = NULL;
00035
00036
00037 static struct s_trace *trace_free_head = NULL;
00038
00039 #ifdef DEBUG
00040 static int num_trace_allocated = 0;
00041 static int num_heap_allocated = 0;
00042 static int num_linked_f_pointer_allocated = 0;
00043 #endif
00044
00045 static struct s_linked_f_pointer *rr_modified_head = NULL;
00046 static struct s_linked_f_pointer *linked_f_pointer_free_head = NULL;
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 static void free_trace_data(struct s_trace *tptr);
00083 static void load_route_bb(int bb_factor);
00084
00085 static struct s_trace *alloc_trace_data(void);
00086 static void add_to_heap(struct s_heap *hptr);
00087 static struct s_heap *alloc_heap_data(void);
00088 static struct s_linked_f_pointer *alloc_linked_f_pointer(void);
00089
00090 static t_ivec **alloc_and_load_clb_opins_used_locally(t_subblock_data
00091 subblock_data);
00092 static void adjust_one_rr_occ_and_pcost(int inode,
00093 int add_or_sub,
00094 float pres_fac);
00095
00096
00097
00098
00099
00100 void
00101 save_routing(struct s_trace **best_routing,
00102 t_ivec ** fb_opins_used_locally,
00103 t_ivec ** saved_clb_opins_used_locally)
00104 {
00105
00106
00107
00108
00109
00110
00111
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
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
00131 best_routing[inet] = trace_head[inet];
00132
00133
00134
00135
00136 trace_head[inet] = NULL;
00137 trace_tail[inet] = NULL;
00138 }
00139
00140
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 fb_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 fb_opins_used_locally[iblk][iclass].
00154 list[ipin];
00155 }
00156 }
00157 }
00158 }
00159
00160
00161 void
00162 restore_routing(struct s_trace **best_routing,
00163 t_ivec ** fb_opins_used_locally,
00164 t_ivec ** saved_clb_opins_used_locally)
00165 {
00166
00167
00168
00169
00170
00171
00172
00173
00174 int inet, iblk, ipin, iclass, num_local_opins;
00175 t_type_ptr type;
00176
00177 for(inet = 0; inet < num_nets; inet++)
00178 {
00179
00180
00181 free_traceback(inet);
00182
00183
00184 trace_head[inet] = best_routing[inet];
00185 best_routing[inet] = NULL;
00186 }
00187
00188
00189
00190 for(iblk = 0; iblk < num_blocks; iblk++)
00191 {
00192 type = block[iblk].type;
00193 for(iclass = 0; iclass < type->num_class; iclass++)
00194 {
00195 num_local_opins =
00196 fb_opins_used_locally[iblk][iclass].nelem;
00197 for(ipin = 0; ipin < num_local_opins; ipin++)
00198 {
00199 fb_opins_used_locally[iblk][iclass].list[ipin] =
00200 saved_clb_opins_used_locally[iblk][iclass].
00201 list[ipin];
00202 }
00203 }
00204
00205 }
00206 }
00207
00208
00209 void
00210 get_serial_num(void)
00211 {
00212
00213
00214
00215
00216
00217 int inet, serial_num, inode;
00218 struct s_trace *tptr;
00219
00220 serial_num = 0;
00221
00222 for(inet = 0; inet < num_nets; inet++)
00223 {
00224
00225
00226
00227
00228 tptr = trace_head[inet];
00229 while(tptr != NULL)
00230 {
00231 inode = tptr->index;
00232 serial_num +=
00233 (inet + 1) * (rr_node[inode].xlow * (nx + 1) -
00234 rr_node[inode].yhigh);
00235
00236 serial_num -= rr_node[inode].ptc_num * (inet + 1) * 10;
00237
00238 serial_num -= rr_node[inode].type * (inet + 1) * 100;
00239 serial_num %= 2000000000;
00240 tptr = tptr->next;
00241 }
00242 }
00243 printf("Serial number (magic cookie) for the routing is: %d\n",
00244 serial_num);
00245 }
00246
00247
00248 boolean
00249 try_route(int width_fac,
00250 struct s_router_opts router_opts,
00251 struct s_det_routing_arch det_routing_arch,
00252 t_segment_inf * segment_inf,
00253 t_timing_inf timing_inf,
00254 float **net_slack,
00255 float **net_delay,
00256 t_chan_width_dist chan_width_dist,
00257 t_ivec ** fb_opins_used_locally,
00258 t_mst_edge ** mst,
00259 boolean * Fc_clipped)
00260 {
00261
00262
00263
00264
00265
00266
00267
00268
00269 int tmp;
00270 boolean success;
00271 t_graph_type graph_type;
00272
00273 if(router_opts.route_type == GLOBAL) {
00274 graph_type = GRAPH_GLOBAL;
00275 } else {
00276 graph_type = (det_routing_arch.directionality ==
00277 BI_DIRECTIONAL ? GRAPH_BIDIR : GRAPH_UNIDIR);
00278 }
00279
00280
00281
00282 init_chan(width_fac, chan_width_dist);
00283
00284
00285
00286 free_rr_graph();
00287
00288
00289
00290 build_rr_graph(graph_type,
00291 num_types, type_descriptors, nx, ny, grid,
00292 chan_width_x[0], NULL,
00293 det_routing_arch.switch_block_type, det_routing_arch.Fs,
00294 det_routing_arch.num_segment, det_routing_arch.num_switch, segment_inf,
00295 det_routing_arch.global_route_switch,
00296 det_routing_arch.delayless_switch, timing_inf,
00297 det_routing_arch.wire_to_ipin_switch,
00298 router_opts.base_cost_type, &tmp);
00299
00300
00301
00302
00303 alloc_and_load_rr_node_route_structs();
00304
00305 init_route_structs(router_opts.bb_factor);
00306
00307 if(router_opts.router_algorithm == BREADTH_FIRST)
00308 {
00309 printf("Confirming Router Algorithm: BREADTH_FIRST.\n");
00310 success =
00311 try_breadth_first_route(router_opts, fb_opins_used_locally,
00312 width_fac);
00313 }
00314 else if(router_opts.router_algorithm == TIMING_DRIVEN)
00315 {
00316 printf("Confirming Router Algorithm: TIMING_DRIVEN.\n");
00317 assert(router_opts.route_type != GLOBAL);
00318 success =
00319 try_timing_driven_route(router_opts, net_slack, net_delay,
00320 fb_opins_used_locally);
00321 }
00322 else
00323 {
00324 printf("Confirming Router Algorithm: DIRECTED_SEARCH.\n");
00325 success =
00326 try_directed_search_route(router_opts, fb_opins_used_locally,
00327 width_fac, mst);
00328 }
00329
00330 free_rr_node_route_structs();
00331
00332 return (success);
00333 }
00334
00335
00336 boolean
00337 feasible_routing(void)
00338 {
00339
00340
00341
00342
00343
00344 int inode;
00345
00346 for(inode = 0; inode < num_rr_nodes; inode++)
00347 if(rr_node[inode].occ > rr_node[inode].capacity)
00348 return (FALSE);
00349
00350 return (TRUE);
00351 }
00352
00353
00354 void
00355 pathfinder_update_one_cost(struct s_trace *route_segment_start,
00356 int add_or_sub,
00357 float pres_fac)
00358 {
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368 struct s_trace *tptr;
00369 int inode, occ, capacity;
00370
00371 tptr = route_segment_start;
00372 if(tptr == NULL)
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
00385
00386
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;
00401 if(tptr == NULL)
00402 break;
00403 }
00404
00405 tptr = tptr->next;
00406
00407 }
00408 }
00409
00410
00411 void
00412 pathfinder_update_cost(float pres_fac,
00413 float acc_fac)
00414 {
00415
00416
00417
00418
00419
00420
00421
00422
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
00440
00441
00442 else if(occ == capacity)
00443 {
00444 rr_node_route_inf[inode].pres_cost = 1. + pres_fac;
00445 }
00446 }
00447 }
00448
00449
00450 void
00451 init_route_structs(int bb_factor)
00452 {
00453
00454
00455
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
00465
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 }
00481
00482
00483 struct s_trace *
00484 update_traceback(struct s_heap *hptr,
00485 int inet)
00486 {
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
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();
00524 tptr->index = inode;
00525 tptr->iswitch = OPEN;
00526 tptr->next = NULL;
00527 temptail = tptr;
00528
00529
00530
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;
00550 ret_ptr = tptr->next;
00551 }
00552 else
00553 {
00554 trace_head[inet] = tptr;
00555 ret_ptr = tptr;
00556 }
00557
00558 trace_tail[inet] = temptail;
00559 return (ret_ptr);
00560 }
00561
00562
00563 void
00564 reset_path_costs(void)
00565 {
00566
00567
00568
00569
00570 struct s_linked_f_pointer *mod_ptr;
00571
00572 #ifdef DEBUG
00573 int num_mod_ptrs;
00574 #endif
00575
00576
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;
00595
00596
00597
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 }
00608
00609
00610 float
00611 get_rr_cong_cost(int inode)
00612 {
00613
00614
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 }
00625
00626
00627 void
00628 mark_ends(int inet)
00629 {
00630
00631
00632
00633
00634
00635
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 }
00645
00646
00647 void
00648 node_to_heap(int inode,
00649 float cost,
00650 int prev_node,
00651 int prev_edge,
00652 float backward_path_cost,
00653 float R_upstream)
00654 {
00655
00656
00657
00658
00659
00660
00661
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 }
00677
00678
00679 void
00680 free_traceback(int inet)
00681 {
00682
00683
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 t_ivec **
00703 alloc_route_structs(t_subblock_data subblock_data)
00704 {
00705
00706
00707
00708 t_ivec **fb_opins_used_locally;
00709
00710 trace_head = (struct s_trace **)my_calloc(num_nets,
00711 sizeof(struct s_trace *));
00712 trace_tail = (struct s_trace **)my_malloc(num_nets *
00713 sizeof(struct s_trace *));
00714
00715 heap_size = nx * ny;
00716 heap = (struct s_heap **)my_malloc(heap_size * sizeof(struct s_heap *));
00717 heap--;
00718 heap_tail = 1;
00719
00720 route_bb = (struct s_bb *)my_malloc(num_nets * sizeof(struct s_bb));
00721
00722 fb_opins_used_locally =
00723 alloc_and_load_clb_opins_used_locally(subblock_data);
00724
00725 return (fb_opins_used_locally);
00726 }
00727
00728
00729 struct s_trace **
00730 alloc_saved_routing(t_ivec ** fb_opins_used_locally,
00731 t_ivec *** saved_clb_opins_used_locally_ptr)
00732 {
00733
00734
00735
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 fb_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
00780 static t_ivec **
00781 alloc_and_load_clb_opins_used_locally(t_subblock_data subblock_data)
00782 {
00783
00784
00785
00786
00787
00788 t_ivec **fb_opins_used_locally;
00789 int *num_subblocks_per_block;
00790 t_subblock **subblock_inf;
00791 int iblk, isub, clb_pin, opin, iclass, num_local_opins;
00792 int class_low, class_high;
00793 t_type_ptr type;
00794
00795 fb_opins_used_locally =
00796 (t_ivec **) my_malloc(num_blocks * sizeof(t_ivec *));
00797 num_subblocks_per_block = subblock_data.num_subblocks_per_block;
00798 subblock_inf = subblock_data.subblock_inf;
00799
00800 for(iblk = 0; iblk < num_blocks; iblk++)
00801 {
00802 type = block[iblk].type;
00803 get_class_range_for_block(iblk, &class_low, &class_high);
00804 fb_opins_used_locally[iblk] =
00805 (t_ivec *) my_malloc(type->num_class * sizeof(t_ivec));
00806 for(iclass = 0; iclass < type->num_class; iclass++)
00807 fb_opins_used_locally[iblk][iclass].nelem = 0;
00808
00809 for(isub = 0; isub < num_subblocks_per_block[iblk]; isub++)
00810 {
00811 for(opin = 0;
00812 opin < block[iblk].type->max_subblock_outputs; opin++)
00813 {
00814 clb_pin = subblock_inf[iblk][isub].outputs[opin];
00815
00816
00817 if(clb_pin != OPEN
00818 && block[iblk].nets[clb_pin] == OPEN)
00819 {
00820 iclass = type->pin_class[clb_pin];
00821
00822 assert(iclass >= class_low
00823 && iclass <= class_high);
00824 fb_opins_used_locally[iblk][iclass].
00825 nelem++;
00826 }
00827 }
00828 }
00829
00830 for(iclass = 0; iclass < type->num_class; iclass++)
00831 {
00832 num_local_opins =
00833 fb_opins_used_locally[iblk][iclass].nelem;
00834
00835 if(num_local_opins == 0)
00836 fb_opins_used_locally[iblk][iclass].list = NULL;
00837 else
00838 fb_opins_used_locally[iblk][iclass].list =
00839 (int *)my_malloc(num_local_opins * sizeof(int));
00840 }
00841 }
00842
00843 return (fb_opins_used_locally);
00844 }
00845
00846 void
00847 free_trace_structs(void)
00848 {
00849
00850
00851
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 }
00862
00863 void
00864 free_route_structs(t_ivec ** fb_opins_used_locally)
00865 {
00866
00867
00868
00869 int i;
00870
00871 free(heap + 1);
00872 free(route_bb);
00873
00874 heap = NULL;
00875 route_bb = NULL;
00876
00877 for(i = 0; i < num_blocks; i++)
00878 {
00879 free_ivec_vector(fb_opins_used_locally[i], 0,
00880 block[i].type->num_class - 1);
00881 }
00882 free(fb_opins_used_locally);
00883
00884
00885
00886
00887 }
00888
00889
00890 void
00891 free_saved_routing(struct s_trace **best_routing,
00892 t_ivec ** saved_clb_opins_used_locally)
00893 {
00894
00895
00896 int i;
00897
00898 free(best_routing);
00899 for(i = 0; i < num_blocks; i++)
00900 {
00901 free_ivec_vector(saved_clb_opins_used_locally[i], 0,
00902 block[i].type->num_class - 1);
00903 }
00904 free(saved_clb_opins_used_locally);
00905 }
00906
00907
00908 void
00909 alloc_and_load_rr_node_route_structs(void)
00910 {
00911
00912
00913
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 }
00936
00937
00938 void
00939 free_rr_node_route_structs(void)
00940 {
00941
00942
00943
00944
00945 free(rr_node_route_inf);
00946 rr_node_route_inf = NULL;
00947 }
00948
00949
00950 static void
00951 load_route_bb(int bb_factor)
00952 {
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965 int k, xmax, ymax, xmin, ymin, x, y, inet;
00966
00967 for(inet = 0; inet < num_nets; inet++)
00968 {
00969 x = block[net[inet].node_block[0]].x;
00970 y = block[net[inet].node_block[0]].y;
00971
00972 xmin = x;
00973 ymin = y;
00974 xmax = x;
00975 ymax = y;
00976
00977 for(k = 1; k <= net[inet].num_sinks; k++)
00978 {
00979 x = block[net[inet].node_block[k]].x;
00980 y = block[net[inet].node_block[k]].y;
00981
00982 if(x < xmin)
00983 {
00984 xmin = x;
00985 }
00986 else if(x > xmax)
00987 {
00988 xmax = x;
00989 }
00990
00991 if(y < ymin)
00992 {
00993 ymin = y;
00994 }
00995 else if(y > ymax)
00996 {
00997 ymax = y;
00998 }
00999 }
01000
01001
01002
01003 xmin -= 1;
01004 ymin -= 1;
01005
01006
01007
01008
01009 route_bb[inet].xmin = max(xmin - bb_factor, 0);
01010 route_bb[inet].xmax = min(xmax + bb_factor, nx + 1);
01011 route_bb[inet].ymin = max(ymin - bb_factor, 0);
01012 route_bb[inet].ymax = min(ymax + bb_factor, ny + 1);
01013 }
01014 }
01015
01016
01017 void
01018 add_to_mod_list(float *fptr)
01019 {
01020
01021
01022
01023
01024
01025 struct s_linked_f_pointer *mod_ptr;
01026
01027 mod_ptr = alloc_linked_f_pointer();
01028
01029
01030
01031 mod_ptr->next = rr_modified_head;
01032 mod_ptr->fptr = fptr;
01033 rr_modified_head = mod_ptr;
01034 }
01035
01036
01037 static void
01038 add_to_heap(struct s_heap *hptr)
01039 {
01040
01041
01042
01043 int ito, ifrom;
01044 struct s_heap *temp_ptr;
01045
01046 if(heap_tail > heap_size)
01047 {
01048 heap_size *= 2;
01049 heap = my_realloc((void *)(heap + 1), heap_size *
01050 sizeof(struct s_heap *));
01051 heap--;
01052 }
01053
01054 heap[heap_tail] = hptr;
01055 ifrom = heap_tail;
01056 ito = ifrom / 2;
01057 heap_tail++;
01058
01059 while((ito >= 1) && (heap[ifrom]->cost < heap[ito]->cost))
01060 {
01061 temp_ptr = heap[ito];
01062 heap[ito] = heap[ifrom];
01063 heap[ifrom] = temp_ptr;
01064 ifrom = ito;
01065 ito = ifrom / 2;
01066 }
01067 }
01068
01069
01070 boolean
01071 is_empty_heap(void)
01072 {
01073 return (heap_tail == 1);
01074 }
01075
01076 struct s_heap *
01077 get_heap_head(void)
01078 {
01079
01080
01081
01082
01083
01084 int ito, ifrom;
01085 struct s_heap *heap_head, *temp_ptr;
01086
01087 do
01088 {
01089 if(heap_tail == 1)
01090 {
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];
01098
01099
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);
01121
01122 return (heap_head);
01123 }
01124
01125
01126 void
01127 empty_heap(void)
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 }
01137
01138 #define NCHUNK 200
01139
01140
01141 static struct s_heap *
01142 alloc_heap_data(void)
01143 {
01144
01145 int i;
01146 struct s_heap *temp_ptr;
01147
01148 if(heap_free_head == NULL)
01149 {
01150 heap_free_head = (struct s_heap *)my_malloc(NCHUNK *
01151 sizeof(struct
01152 s_heap));
01153
01154
01155
01156
01157
01158 for(i = 0; i < NCHUNK - 1; i++)
01159 (heap_free_head + i)->u.next = heap_free_head + i + 1;
01160 (heap_free_head + NCHUNK - 1)->u.next = NULL;
01161 }
01162
01163 temp_ptr = heap_free_head;
01164 heap_free_head = heap_free_head->u.next;
01165 #ifdef DEBUG
01166 num_heap_allocated++;
01167 #endif
01168 return (temp_ptr);
01169 }
01170
01171
01172 void
01173 free_heap_data(struct s_heap *hptr)
01174 {
01175
01176 hptr->u.next = heap_free_head;
01177 heap_free_head = hptr;
01178 #ifdef DEBUG
01179 num_heap_allocated--;
01180 #endif
01181 }
01182
01183
01184 void
01185 invalidate_heap_entries(int sink_node,
01186 int ipin_node)
01187 {
01188
01189
01190
01191
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;
01200 }
01201 }
01202
01203
01204 static struct s_trace *
01205 alloc_trace_data(void)
01206 {
01207
01208 int i;
01209 struct s_trace *temp_ptr;
01210
01211 if(trace_free_head == NULL)
01212 {
01213 trace_free_head = (struct s_trace *)my_malloc(NCHUNK *
01214 sizeof(struct
01215 s_trace));
01216
01217
01218
01219
01220
01221 for(i = 0; i < NCHUNK - 1; i++)
01222 (trace_free_head + i)->next = trace_free_head + i + 1;
01223 (trace_free_head + NCHUNK - 1)->next = NULL;
01224 }
01225 temp_ptr = trace_free_head;
01226 trace_free_head = trace_free_head->next;
01227 #ifdef DEBUG
01228 num_trace_allocated++;
01229 #endif
01230 return (temp_ptr);
01231 }
01232
01233
01234 static void
01235 free_trace_data(struct s_trace *tptr)
01236 {
01237
01238
01239
01240 tptr->next = trace_free_head;
01241 trace_free_head = tptr;
01242 #ifdef DEBUG
01243 num_trace_allocated--;
01244 #endif
01245 }
01246
01247
01248 static struct s_linked_f_pointer *
01249 alloc_linked_f_pointer(void)
01250 {
01251
01252
01253
01254
01255 int i;
01256 struct s_linked_f_pointer *temp_ptr;
01257
01258 if(linked_f_pointer_free_head == NULL)
01259 {
01260
01261 linked_f_pointer_free_head = (struct s_linked_f_pointer *)
01262 my_malloc(NCHUNK * sizeof(struct s_linked_f_pointer));
01263
01264
01265
01266
01267
01268 for(i = 0; i < NCHUNK - 1; i++)
01269 {
01270 (linked_f_pointer_free_head + i)->next =
01271 linked_f_pointer_free_head + i + 1;
01272 }
01273 (linked_f_pointer_free_head + NCHUNK - 1)->next = NULL;
01274 }
01275
01276 temp_ptr = linked_f_pointer_free_head;
01277 linked_f_pointer_free_head = linked_f_pointer_free_head->next;
01278
01279 #ifdef DEBUG
01280 num_linked_f_pointer_allocated++;
01281 #endif
01282
01283 return (temp_ptr);
01284 }
01285
01286
01287 void
01288 print_route(char *route_file)
01289 {
01290
01291
01292
01293 int inet, inode, ipin, bnum, ilow, jlow, node_block_pin, iclass;
01294 t_rr_type rr_type;
01295 struct s_trace *tptr;
01296 char *name_type[] =
01297 { "SOURCE", "SINK", "IPIN", "OPIN", "CHANX", "CHANY" };
01298 FILE *fp;
01299
01300 fp = my_fopen(route_file, "w");
01301
01302 fprintf(fp, "Array size: %d x %d logic blocks.\n", nx, ny);
01303 fprintf(fp, "\nRouting:");
01304 for(inet = 0; inet < num_nets; inet++)
01305 {
01306 if(net[inet].is_global == FALSE)
01307 {
01308 fprintf(fp, "\n\nNet %d (%s)\n\n", inet, net[inet].name);
01309 tptr = trace_head[inet];
01310
01311 while(tptr != NULL)
01312 {
01313 inode = tptr->index;
01314 rr_type = rr_node[inode].type;
01315 ilow = rr_node[inode].xlow;
01316 jlow = rr_node[inode].ylow;
01317
01318 fprintf(fp, "%6s (%d,%d) ", name_type[rr_type],
01319 ilow, jlow);
01320
01321 if((ilow != rr_node[inode].xhigh) || (jlow !=
01322 rr_node
01323 [inode].
01324 yhigh))
01325 fprintf(fp, "to (%d,%d) ",
01326 rr_node[inode].xhigh,
01327 rr_node[inode].yhigh);
01328
01329 switch (rr_type)
01330 {
01331
01332 case IPIN:
01333 case OPIN:
01334 if(grid[ilow][jlow].type == IO_TYPE)
01335 {
01336 fprintf(fp, " Pad: ");
01337 }
01338 else
01339 {
01340 fprintf(fp, " Pin: ");
01341 }
01342 break;
01343
01344 case CHANX:
01345 case CHANY:
01346 fprintf(fp, " Track: ");
01347 break;
01348
01349 case SOURCE:
01350 case SINK:
01351 if(grid[ilow][jlow].type == IO_TYPE)
01352 {
01353 fprintf(fp, " Pad: ");
01354 }
01355 else
01356 {
01357 fprintf(fp, " Class: ");
01358 }
01359 break;
01360
01361 default:
01362 printf
01363 ("Error in print_route: Unexpected traceback element "
01364 "type: %d (%s).\n", rr_type,
01365 name_type[rr_type]);
01366 exit(1);
01367 break;
01368 }
01369
01370 fprintf(fp, "%d ", rr_node[inode].ptc_num);
01371
01372
01373
01374
01375
01376 fprintf(fp, "\n");
01377
01378 tptr = tptr->next;
01379 }
01380 }
01381
01382 else
01383 {
01384 fprintf(fp, "\n\nNet %d (%s): global net connecting:\n\n",
01385 inet, net[inet].name);
01386
01387 for(ipin = 0; ipin <= net[inet].num_sinks; ipin++)
01388 {
01389 bnum = net[inet].node_block[ipin];
01390
01391 node_block_pin = net[inet].node_block_pin[ipin];
01392 iclass =
01393 block[bnum].type->pin_class[node_block_pin];
01394
01395 fprintf(fp,
01396 "Block %s (#%d) at (%d, %d), Pin class %d.\n",
01397 block[bnum].name, bnum, block[bnum].x,
01398 block[bnum].y, iclass);
01399 }
01400 }
01401 }
01402
01403 fclose(fp);
01404
01405 #ifdef CREATE_ECHO_FILES
01406 fp = my_fopen("mem.echo", "w");
01407 fprintf(fp, "\nNum_heap_allocated: %d Num_trace_allocated: %d\n",
01408 num_heap_allocated, num_trace_allocated);
01409 fprintf(fp, "Num_linked_f_pointer_allocated: %d\n",
01410 num_linked_f_pointer_allocated);
01411 fclose(fp);
01412 #endif
01413
01414 }
01415
01416
01417 void
01418 reserve_locally_used_opins(float pres_fac,
01419 boolean rip_up_local_opins,
01420 t_ivec ** fb_opins_used_locally)
01421 {
01422
01423
01424
01425
01426
01427
01428
01429
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
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
01467
01468 if(num_local_opin != 0)
01469 {
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 }
01496
01497
01498 static void
01499 adjust_one_rr_occ_and_pcost(int inode,
01500 int add_or_sub,
01501 float pres_fac)
01502 {
01503
01504
01505
01506
01507 int occ, capacity;
01508
01509 occ = rr_node[inode].occ + add_or_sub;
01510 capacity = rr_node[inode].capacity;
01511 rr_node[inode].occ = occ;
01512
01513 if(occ < capacity)
01514 {
01515 rr_node_route_inf[inode].pres_cost = 1.;
01516 }
01517 else
01518 {
01519 rr_node_route_inf[inode].pres_cost = 1. + (occ + 1 - capacity) *
01520 pres_fac;
01521 }
01522 }