00001 #include <stdio.h>
00002 #include <assert.h>
00003 #include <sys/types.h>
00004 #include "util.h"
00005 #include "vpr_types.h"
00006 #include "globals.h"
00007 #include "mst.h"
00008 #include "route_export.h"
00009 #include "route_common.h"
00010 #include "route_directed_search.h"
00011 #include "draw.h"
00012
00013
00014
00015
00016 static boolean directed_search_route_net(int inet,
00017 float pres_fac,
00018 float astar_fac,
00019 float bend_cost,
00020 t_mst_edge ** mst);
00021
00022 static void directed_search_expand_trace_segment(struct s_trace *start_ptr,
00023 int target_node,
00024 float astar_fac,
00025 int
00026 remaining_connections_to_sink);
00027
00028 static void directed_search_expand_neighbours(struct s_heap *current,
00029 int inet,
00030 float bend_cost,
00031 int target_node,
00032 float astar_fac);
00033
00034 static void directed_search_add_source_to_heap(int inet,
00035 int target_node,
00036 float astar_fac);
00037
00038 static float get_directed_search_expected_cost(int inode,
00039 int target_node);
00040
00041 static int get_expected_segs_to_target(int inode,
00042 int target_node,
00043 int *num_segs_ortho_dir_ptr);
00044
00045
00046
00047 boolean
00048 try_directed_search_route(struct s_router_opts router_opts,
00049 t_ivec ** fb_opins_used_locally,
00050 int width_fac,
00051 t_mst_edge ** mst)
00052 {
00053
00054
00055
00056
00057
00058 float pres_fac;
00059 boolean success, is_routable, rip_up_local_opins;
00060 int itry, inet;
00061
00062
00063
00064
00065
00066 if(mst)
00067 {
00068 for(inet = 0; inet < num_nets; inet++)
00069 {
00070 free(mst[inet]);
00071 mst[inet] = get_mst_of_net(inet);
00072 }
00073 }
00074
00075
00076
00077
00078
00079 pres_fac = router_opts.first_iter_pres_fac;
00080
00081 for(itry = 1; itry <= router_opts.max_router_iterations; itry++)
00082 {
00083
00084 for(inet = 0; inet < num_nets; inet++)
00085 {
00086 if(net[inet].is_global == FALSE)
00087 {
00088
00089 is_routable =
00090 directed_search_route_net(inet, pres_fac,
00091 router_opts.
00092 astar_fac,
00093 router_opts.
00094 bend_cost, mst);
00095
00096
00097
00098 if(!is_routable)
00099 {
00100 printf("Routing failed.\n");
00101 return (FALSE);
00102 }
00103
00104 }
00105 }
00106
00107
00108
00109
00110 if(itry == 1)
00111 rip_up_local_opins = FALSE;
00112 else
00113 rip_up_local_opins = TRUE;
00114
00115 reserve_locally_used_opins(pres_fac, rip_up_local_opins,
00116 fb_opins_used_locally);
00117
00118 success = feasible_routing();
00119 if(success)
00120 {
00121 printf
00122 ("Successfully routed after %d routing iterations by Directed Search.\n",
00123 itry);
00124 return (TRUE);
00125 }
00126 #if 0
00127 else
00128 {
00129 sprintf(msg,
00130 "After iteration %d routing failed (A*) with a channel width factor of %d and Fc_int of %d, Fs_int of %d.",
00131 itry, width_fac, Fc_int, Fs_int);
00132 init_draw_coords(pins_per_clb);
00133 update_screen(MAJOR, msg, ROUTING, FALSE);
00134 }
00135 #endif
00136
00137
00138 if(itry == 1)
00139 {
00140 pres_fac = router_opts.initial_pres_fac;
00141 pathfinder_update_cost(pres_fac, 0.);
00142 }
00143 else
00144 {
00145 pres_fac *= router_opts.pres_fac_mult;
00146 pathfinder_update_cost(pres_fac, router_opts.acc_fac);
00147 }
00148
00149 }
00150
00151 printf("Routing failed.\n");
00152
00153 return (FALSE);
00154 }
00155
00156
00157 static boolean
00158 directed_search_route_net(int inet,
00159 float pres_fac,
00160 float astar_fac,
00161 float bend_cost,
00162 t_mst_edge ** mst)
00163 {
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179 int inode, remaining_connections_to_sink;
00180 int itarget, target_pin, target_node;
00181 struct s_heap *current;
00182 struct s_trace *new_route_start_tptr;
00183 float old_tcost, new_tcost, old_back_cost, new_back_cost;
00184
00185
00186
00187
00188
00189
00190 pathfinder_update_one_cost(trace_head[inet], -1, pres_fac);
00191 free_traceback(inet);
00192
00193
00194 target_pin = mst[inet][0].to_node;
00195 target_node = net_rr_terminals[inet][target_pin];
00196 directed_search_add_source_to_heap(inet, target_node, astar_fac);
00197
00198 mark_ends(inet);
00199
00200 remaining_connections_to_sink = 0;
00201
00202 for(itarget = 0; itarget < net[inet].num_sinks; itarget++)
00203 {
00204 target_pin = mst[inet][itarget].to_node;
00205 target_node = net_rr_terminals[inet][target_pin];
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217 directed_search_expand_trace_segment(trace_head[inet],
00218 target_node, astar_fac,
00219 remaining_connections_to_sink);
00220
00221 current = get_heap_head();
00222
00223 if(current == NULL)
00224 {
00225 reset_path_costs();
00226 return (FALSE);
00227 }
00228
00229 inode = current->index;
00230
00231 while(inode != target_node)
00232 {
00233 old_tcost = rr_node_route_inf[inode].path_cost;
00234 new_tcost = current->cost;
00235
00236
00237
00238 if(old_tcost > 0.99 * HUGE_FLOAT)
00239 old_back_cost = HUGE_FLOAT;
00240 else
00241 old_back_cost =
00242 rr_node_route_inf[inode].backward_path_cost;
00243
00244 new_back_cost = current->backward_path_cost;
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 if(old_tcost > new_tcost && old_back_cost > new_back_cost)
00256 {
00257
00258 rr_node_route_inf[inode].prev_node =
00259 current->u.prev_node;
00260 rr_node_route_inf[inode].prev_edge =
00261 current->prev_edge;
00262 rr_node_route_inf[inode].path_cost = new_tcost;
00263 rr_node_route_inf[inode].backward_path_cost =
00264 new_back_cost;
00265
00266 if(old_tcost > 0.99 * HUGE_FLOAT)
00267 add_to_mod_list(&rr_node_route_inf[inode].
00268 path_cost);
00269
00270 directed_search_expand_neighbours(current, inet,
00271 bend_cost,
00272 target_node,
00273 astar_fac);
00274 }
00275
00276 free_heap_data(current);
00277 current = get_heap_head();
00278
00279 if(current == NULL)
00280 {
00281 reset_path_costs();
00282 return (FALSE);
00283 }
00284
00285 inode = current->index;
00286 }
00287
00288 rr_node_route_inf[inode].target_flag--;
00289 remaining_connections_to_sink =
00290 rr_node_route_inf[inode].target_flag;
00291
00292
00293 new_route_start_tptr = update_traceback(current, inet);
00294
00295 free_heap_data(current);
00296
00297
00298
00299 pathfinder_update_one_cost(new_route_start_tptr, 1, pres_fac);
00300
00301
00302
00303
00304
00305 empty_heap();
00306 reset_path_costs();
00307 }
00308
00309 return (TRUE);
00310 }
00311
00312 static void
00313 directed_search_expand_trace_segment(struct s_trace *start_ptr,
00314 int target_node,
00315 float astar_fac,
00316 int remaining_connections_to_sink)
00317 {
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335 struct s_trace *tptr;
00336 int inode, backward_path_cost, tot_cost;
00337
00338 tptr = start_ptr;
00339
00340 if(remaining_connections_to_sink == 0)
00341 {
00342 while(tptr != NULL)
00343 {
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 inode = tptr->index;
00356
00357 if(!
00358 (rr_node[inode].type == IPIN
00359 || rr_node[inode].type == SINK))
00360 {
00361
00362 backward_path_cost = 0;
00363 tot_cost =
00364 backward_path_cost +
00365 astar_fac *
00366 get_directed_search_expected_cost(inode,
00367 target_node);
00368 node_to_heap(inode, tot_cost, NO_PREVIOUS,
00369 NO_PREVIOUS, backward_path_cost,
00370 OPEN);
00371 }
00372
00373 tptr = tptr->next;
00374 }
00375 }
00376
00377 else
00378 {
00379 printf("Warning: Multiple connections from net to the same sink. "
00380 "This should not happen for LUT/Cluster based logic blocks. Aborting.\n");
00381 exit(1);
00382 }
00383 }
00384
00385 static void
00386 directed_search_expand_neighbours(struct s_heap *current,
00387 int inet,
00388 float bend_cost,
00389 int target_node,
00390 float astar_fac)
00391 {
00392
00393
00394
00395
00396
00397
00398 int iconn, to_node, num_edges, inode, target_x, target_y;
00399 t_rr_type from_type, to_type;
00400 float new_tot_cost, old_back_pcost, new_back_pcost;
00401
00402 inode = current->index;
00403 old_back_pcost = current->backward_path_cost;
00404 num_edges = rr_node[inode].num_edges;
00405
00406 target_x = rr_node[target_node].xhigh;
00407 target_y = rr_node[target_node].yhigh;
00408
00409 for(iconn = 0; iconn < num_edges; iconn++)
00410 {
00411 to_node = rr_node[inode].edges[iconn];
00412
00413 if(rr_node[to_node].xhigh < route_bb[inet].xmin ||
00414 rr_node[to_node].xlow > route_bb[inet].xmax ||
00415 rr_node[to_node].yhigh < route_bb[inet].ymin ||
00416 rr_node[to_node].ylow > route_bb[inet].ymax)
00417 continue;
00418
00419
00420
00421
00422
00423
00424 to_type = rr_node[to_node].type;
00425 if(to_type == IPIN && (rr_node[to_node].xhigh != target_x ||
00426 rr_node[to_node].yhigh != target_y))
00427 continue;
00428
00429
00430
00431
00432
00433
00434 new_back_pcost = old_back_pcost + get_rr_cong_cost(to_node);
00435
00436 if(bend_cost != 0.)
00437 {
00438 from_type = rr_node[inode].type;
00439 to_type = rr_node[to_node].type;
00440 if((from_type == CHANX && to_type == CHANY) ||
00441 (from_type == CHANY && to_type == CHANX))
00442 new_back_pcost += bend_cost;
00443 }
00444
00445
00446 new_tot_cost = new_back_pcost + astar_fac *
00447 get_directed_search_expected_cost(to_node, target_node);
00448
00449 node_to_heap(to_node, new_tot_cost, inode, iconn, new_back_pcost,
00450 OPEN);
00451 }
00452 }
00453
00454
00455 static void
00456 directed_search_add_source_to_heap(int inet,
00457 int target_node,
00458 float astar_fac)
00459 {
00460
00461
00462
00463 int inode;
00464 float back_cost, tot_cost;
00465
00466 inode = net_rr_terminals[inet][0];
00467 back_cost = 0.0 + get_rr_cong_cost(inode);
00468
00469
00470 if(!is_empty_heap())
00471 {
00472 printf
00473 ("Error: Wrong Assumption: in directed_search_add_source_to_heap "
00474 "the heap is not empty. Need to properly calculate source node's cost.\n");
00475 exit(1);
00476 }
00477
00478
00479
00480 tot_cost =
00481 back_cost + astar_fac * get_directed_search_expected_cost(inode,
00482 target_node);
00483 node_to_heap(inode, tot_cost, NO_PREVIOUS, NO_PREVIOUS, back_cost, OPEN);
00484
00485 }
00486
00487
00488 static float
00489 get_directed_search_expected_cost(int inode,
00490 int target_node)
00491 {
00492
00493
00494
00495
00496
00497 t_rr_type rr_type;
00498 int cost_index, ortho_cost_index, num_segs_same_dir, num_segs_ortho_dir;
00499 float cong_cost;
00500
00501 rr_type = rr_node[inode].type;
00502
00503 if(rr_type == CHANX || rr_type == CHANY)
00504 {
00505 num_segs_same_dir =
00506 get_expected_segs_to_target(inode, target_node,
00507 &num_segs_ortho_dir);
00508 cost_index = rr_node[inode].cost_index;
00509 ortho_cost_index = rr_indexed_data[cost_index].ortho_cost_index;
00510
00511 cong_cost =
00512 num_segs_same_dir * rr_indexed_data[cost_index].base_cost +
00513 num_segs_ortho_dir *
00514 rr_indexed_data[ortho_cost_index].base_cost;
00515 cong_cost +=
00516 rr_indexed_data[IPIN_COST_INDEX].base_cost +
00517 rr_indexed_data[SINK_COST_INDEX].base_cost;
00518
00519 return (cong_cost);
00520 }
00521
00522 else if(rr_type == IPIN)
00523 {
00524 return (rr_indexed_data[SINK_COST_INDEX].base_cost);
00525 }
00526
00527 else
00528 {
00529 return (0.);
00530 }
00531 }
00532
00533
00534
00535
00536
00537 #define ROUND_UP(x) (ceil (x - 0.001))
00538
00539
00540 static int
00541 get_expected_segs_to_target(int inode,
00542 int target_node,
00543 int *num_segs_ortho_dir_ptr)
00544 {
00545
00546
00547
00548
00549
00550 t_rr_type rr_type;
00551 int target_x, target_y, num_segs_same_dir, cost_index, ortho_cost_index;
00552 int no_need_to_pass_by_clb;
00553 float inv_length, ortho_inv_length, ylow, yhigh, xlow, xhigh;
00554
00555 target_x = rr_node[target_node].xlow;
00556 target_y = rr_node[target_node].ylow;
00557 cost_index = rr_node[inode].cost_index;
00558 inv_length = rr_indexed_data[cost_index].inv_length;
00559 ortho_cost_index = rr_indexed_data[cost_index].ortho_cost_index;
00560 ortho_inv_length = rr_indexed_data[ortho_cost_index].inv_length;
00561 rr_type = rr_node[inode].type;
00562
00563 if(rr_type == CHANX)
00564 {
00565 ylow = rr_node[inode].ylow;
00566 xhigh = rr_node[inode].xhigh;
00567 xlow = rr_node[inode].xlow;
00568
00569
00570
00571 if(ylow > target_y)
00572 {
00573 *num_segs_ortho_dir_ptr =
00574 ROUND_UP((ylow - target_y + 1.) * ortho_inv_length);
00575 no_need_to_pass_by_clb = 1;
00576 }
00577 else if(ylow < target_y - 1)
00578 {
00579 *num_segs_ortho_dir_ptr = ROUND_UP((target_y - ylow) *
00580 ortho_inv_length);
00581 no_need_to_pass_by_clb = 1;
00582 }
00583 else
00584 {
00585 *num_segs_ortho_dir_ptr = 0;
00586 no_need_to_pass_by_clb = 0;
00587 }
00588
00589
00590
00591 if(xlow > target_x + no_need_to_pass_by_clb)
00592 {
00593 num_segs_same_dir =
00594 ROUND_UP((xlow - no_need_to_pass_by_clb -
00595 target_x) * inv_length);
00596 }
00597 else if(xhigh < target_x - no_need_to_pass_by_clb)
00598 {
00599 num_segs_same_dir =
00600 ROUND_UP((target_x - no_need_to_pass_by_clb -
00601 xhigh) * inv_length);
00602 }
00603 else
00604 {
00605 num_segs_same_dir = 0;
00606 }
00607 }
00608
00609 else
00610 {
00611 ylow = rr_node[inode].ylow;
00612 yhigh = rr_node[inode].yhigh;
00613 xlow = rr_node[inode].xlow;
00614
00615
00616
00617 if(xlow > target_x)
00618 {
00619 *num_segs_ortho_dir_ptr =
00620 ROUND_UP((xlow - target_x + 1.) * ortho_inv_length);
00621 no_need_to_pass_by_clb = 1;
00622 }
00623 else if(xlow < target_x - 1)
00624 {
00625 *num_segs_ortho_dir_ptr = ROUND_UP((target_x - xlow) *
00626 ortho_inv_length);
00627 no_need_to_pass_by_clb = 1;
00628 }
00629 else
00630 {
00631 *num_segs_ortho_dir_ptr = 0;
00632 no_need_to_pass_by_clb = 0;
00633 }
00634
00635
00636
00637 if(ylow > target_y + no_need_to_pass_by_clb)
00638 {
00639 num_segs_same_dir =
00640 ROUND_UP((ylow - no_need_to_pass_by_clb -
00641 target_y) * inv_length);
00642 }
00643 else if(yhigh < target_y - no_need_to_pass_by_clb)
00644 {
00645 num_segs_same_dir =
00646 ROUND_UP((target_y - no_need_to_pass_by_clb -
00647 yhigh) * inv_length);
00648 }
00649 else
00650 {
00651 num_segs_same_dir = 0;
00652 }
00653 }
00654
00655 return (num_segs_same_dir);
00656 }