VPR-6.0

vpr/SRC/base/place_and_route.c

Go to the documentation of this file.
00001 #include <assert.h>
00002 #include <stdio.h>
00003 #include <sys/types.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 "place_and_route.h"
00010 #include "mst.h"
00011 #include "place.h"
00012 #include "read_place.h"
00013 #include "route_export.h"
00014 #include "draw.h"
00015 #include "stats.h"
00016 #include "check_route.h"
00017 #include "rr_graph.h"
00018 #include "path_delay.h"
00019 #include "net_delay.h"
00020 #include "timing_place.h"
00021 #include "read_xml_arch_file.h"
00022 
00023 /******************* Subroutines local to this module ************************/
00024 
00025 static int binary_search_place_and_route(struct s_placer_opts placer_opts,
00026                                          char *place_file,
00027                                          char *net_file,
00028                                          char *arch_file,
00029                                          char *route_file,
00030                                          boolean full_stats,
00031                                          boolean verify_binary_search,
00032                                          struct s_annealing_sched
00033                                          annealing_sched,
00034                                          struct s_router_opts router_opts,
00035                                          struct s_det_routing_arch
00036                                          det_routing_arch,
00037                                          t_segment_inf * segment_inf,
00038                                          t_timing_inf timing_inf,
00039                                          t_chan_width_dist chan_width_dist,
00040                                          t_mst_edge ** mst,
00041                                          t_model *models);
00042 
00043 static float comp_width(t_chan * chan,
00044                         float x,
00045                         float separation);
00046 
00047 
00048 void post_place_sync(INP int num_blocks,
00049                      INOUTP const struct s_block block_list[]);
00050 
00051 void free_pb_data(t_pb *pb);
00052 
00053 
00054 /************************* Subroutine Definitions ****************************/
00055 
00056 /** This routine controls the overall placement and routing of a circuit. */
00057 void
00058 place_and_route(enum e_operation operation,
00059                 struct s_placer_opts placer_opts,
00060                 char *place_file,
00061                 char *net_file,
00062                 char *arch_file,
00063                 char *route_file,
00064                 struct s_annealing_sched annealing_sched,
00065                 struct s_router_opts router_opts,
00066                 struct s_det_routing_arch det_routing_arch,
00067                 t_segment_inf * segment_inf,
00068                 t_timing_inf timing_inf,
00069                 t_chan_width_dist chan_width_dist,
00070                 struct s_model *models)
00071 {
00072     char msg[BUFSIZE];
00073     int width_fac, inet, i;
00074     boolean success, Fc_clipped;
00075     float **net_delay, **net_slack;
00076     struct s_linked_vptr *net_delay_chunk_list_head;
00077     t_ivec **clb_opins_used_locally;    /* [0..num_blocks-1][0..num_class-1] */
00078     t_mst_edge **mst = NULL;    /* Make sure mst is never undefined */
00079     int max_pins_per_clb;
00080         clock_t begin, end;
00081 
00082         Fc_clipped = FALSE;
00083 
00084     max_pins_per_clb = 0;
00085     for(i = 0; i < num_types; i++)
00086         {
00087             if(type_descriptors[i].num_pins > max_pins_per_clb)
00088                 {
00089                     max_pins_per_clb = type_descriptors[i].num_pins;
00090                 }
00091         }
00092 
00093     if(placer_opts.place_freq == PLACE_NEVER)
00094         {
00095             /* Read the placement from a file */
00096             read_place(place_file, net_file, arch_file, nx, ny, num_blocks,
00097                        block);
00098             sync_grid_to_blocks(num_blocks, block, nx, ny, grid);
00099         }
00100     else
00101         {
00102             assert((PLACE_ONCE == placer_opts.place_freq) ||
00103                    (PLACE_ALWAYS == placer_opts.place_freq));
00104                 begin = clock();
00105             try_place(placer_opts, annealing_sched, chan_width_dist,
00106                       router_opts, det_routing_arch, segment_inf,
00107                       timing_inf, &mst);
00108             print_place(place_file, net_file, arch_file);
00109                 end = clock();
00110 #ifdef CLOCKS_PER_SEC
00111                 printf("Placement took %g seconds\n", (float)(end - begin) / CLOCKS_PER_SEC);
00112 #else
00113                 printf("Placement took %g seconds\n", (float)(end - begin) / CLK_PER_SEC);
00114 #endif
00115         }
00116         begin = clock();
00117     post_place_sync(num_blocks, block);
00118 
00119 
00120     fflush(stdout);
00121 
00122         /* reset mst */
00123         if(mst)
00124         {
00125             for(inet = 0; inet < num_nets; inet++)
00126                 {
00127                         if(mst[inet]) {
00128                                 free(mst[inet]);
00129                         }
00130                 }
00131             free(mst);
00132         }
00133         mst = NULL;
00134 
00135         if(!router_opts.doRouting)
00136         return;
00137 
00138     mst = (t_mst_edge **) my_malloc(sizeof(t_mst_edge *) * num_nets);
00139     for(inet = 0; inet < num_nets; inet++)
00140         {
00141             mst[inet] = get_mst_of_net(inet);
00142         }
00143 
00144     width_fac = router_opts.fixed_channel_width;
00145 
00146     /* If channel width not fixed, use binary search to find min W */
00147     if(NO_FIXED_CHANNEL_WIDTH == width_fac)
00148         {
00149             binary_search_place_and_route(placer_opts, place_file,
00150                                           net_file, arch_file, route_file,
00151                                           router_opts.full_stats, router_opts.verify_binary_search,
00152                                           annealing_sched, router_opts,
00153                                           det_routing_arch, segment_inf,
00154                                           timing_inf,
00155                                           chan_width_dist, mst, models);
00156         }
00157     else
00158         {
00159             if(det_routing_arch.directionality == UNI_DIRECTIONAL)
00160                 {
00161                     if(width_fac % 2 != 0)
00162                         {
00163                             printf
00164                                 ("Error: pack_place_and_route.c: given odd chan width (%d) for udsd architecture\n",
00165                                  width_fac);
00166                             exit(1);
00167                         }
00168                 }
00169             /* Other constraints can be left to rr_graph to check since this is one pass routing */
00170 
00171 
00172             /* Allocate the major routing structures. */
00173 
00174             clb_opins_used_locally = alloc_route_structs();
00175 
00176             if(timing_inf.timing_analysis_enabled)
00177                 {
00178                     net_slack =
00179                         alloc_and_load_timing_graph(timing_inf);
00180                     net_delay = alloc_net_delay(&net_delay_chunk_list_head, clb_net, num_nets);
00181                 }
00182             else
00183                 {
00184                     net_delay = NULL;   /* Defensive coding. */
00185                     net_slack = NULL;
00186                 }
00187 
00188             success =
00189                 try_route(width_fac, router_opts, det_routing_arch,
00190                           segment_inf, timing_inf, net_slack, net_delay,
00191                           chan_width_dist, clb_opins_used_locally, mst,
00192                           &Fc_clipped);
00193 
00194             if(Fc_clipped)
00195                 {
00196                     printf
00197                         ("Warning: Fc_output was too high and was clipped to full (maximum) connectivity.\n");
00198                 }
00199 
00200             if(success == FALSE)
00201                 {
00202                     printf
00203                         ("Circuit is unrouteable with a channel width factor of %d\n\n",
00204                          width_fac);
00205                     sprintf(msg,
00206                             "Routing failed with a channel width factor of %d.  ILLEGAL routing shown.",
00207                             width_fac);
00208                 }
00209 
00210             else
00211                 {
00212                     check_route(router_opts.route_type,
00213                                 det_routing_arch.num_switch,
00214                                 clb_opins_used_locally);
00215                     get_serial_num();
00216 
00217                     printf
00218                         ("Circuit successfully routed with a channel width factor of %d.\n\n",
00219                          width_fac);
00220 
00221                         routing_stats(router_opts.full_stats, router_opts.route_type,
00222                                   det_routing_arch.num_switch, segment_inf,
00223                                   det_routing_arch.num_segment,
00224                                   det_routing_arch.R_minW_nmos,
00225                                   det_routing_arch.R_minW_pmos,
00226                                   det_routing_arch.directionality,
00227                                   timing_inf.timing_analysis_enabled,
00228                                   net_slack, net_delay);
00229 
00230                     print_route(route_file);
00231 
00232 #ifdef CREATE_ECHO_FILES
00233                     /*print_sink_delays("routing_sink_delays.echo"); */
00234 #endif /* CREATE_ECHO_FILES */
00235 
00236                     sprintf(msg,
00237                             "Routing succeeded with a channel width factor of %d.\n\n",
00238                             width_fac);
00239                 }
00240 
00241             init_draw_coords(max_pins_per_clb);
00242             update_screen(MAJOR, msg, ROUTING,
00243                           timing_inf.timing_analysis_enabled);
00244 
00245             if(timing_inf.timing_analysis_enabled)
00246                 {
00247                     assert(net_slack);
00248                         #ifdef CREATE_ECHO_FILES
00249                                 print_timing_graph_as_blif("post_flow_timing_graph.blif", models);
00250                         #endif
00251 
00252                     free_timing_graph(net_slack);
00253 
00254                     assert(net_delay);
00255                     free_net_delay(net_delay, &net_delay_chunk_list_head);
00256                 }
00257 
00258             free_route_structs(clb_opins_used_locally);
00259             fflush(stdout);
00260         }
00261         end = clock();
00262         #ifdef CLOCKS_PER_SEC
00263                 printf("Routing took %g seconds\n", (float)(end - begin) / CLOCKS_PER_SEC);
00264         #else
00265                 printf("Routing took %g seconds\n", (float)(end - begin) / CLK_PER_SEC);
00266         #endif
00267 
00268     /*WMF: cleaning up memory usage */
00269     if(mst)
00270         {
00271             for(inet = 0; inet < num_nets; inet++)
00272                 {
00273                         if(!mst[inet]) {
00274                                 printf("no mst for net %s #%d\n", clb_net[inet].name, inet);
00275                         }
00276                     assert(mst[inet]);
00277                     free(mst[inet]);
00278                 }
00279             free(mst);
00280             mst = NULL;
00281         }
00282 }
00283 
00284 
00285 
00286 /** This routine performs a binary search to find the minimum number of      
00287  * tracks per channel required to successfully route a circuit, and returns 
00288  * that minimum width_fac.                                                  
00289  */
00290 static int
00291 binary_search_place_and_route(struct s_placer_opts placer_opts,
00292                               char *place_file,
00293                               char *net_file,
00294                               char *arch_file,
00295                               char *route_file,
00296                               boolean full_stats,
00297                               boolean verify_binary_search,
00298                               struct s_annealing_sched annealing_sched,
00299                               struct s_router_opts router_opts,
00300                               struct s_det_routing_arch det_routing_arch,
00301                               t_segment_inf * segment_inf,
00302                               t_timing_inf timing_inf,
00303                               t_chan_width_dist chan_width_dist,
00304                               t_mst_edge ** mst,
00305                                   t_model *models)
00306 {
00307 
00308 
00309     struct s_trace **best_routing;      /* Saves the best routing found so far. */
00310     int current, low, high, final;
00311     int max_pins_per_clb, i;
00312     boolean success, prev_success, prev2_success, Fc_clipped = FALSE;
00313     char msg[BUFSIZE];
00314     float **net_delay, **net_slack;
00315     struct s_linked_vptr *net_delay_chunk_list_head;
00316     int try_w_limit;
00317     t_ivec **clb_opins_used_locally, **saved_clb_opins_used_locally;
00318 
00319     /* [0..num_blocks-1][0..num_class-1] */
00320     int attempt_count;
00321     int udsd_multiplier;
00322     int warnings;
00323 
00324         t_graph_type graph_type;
00325 
00326 /* Allocate the major routing structures. */
00327 
00328         if(router_opts.route_type == GLOBAL) {
00329                 graph_type = GRAPH_GLOBAL;
00330         } else {
00331                 graph_type = (det_routing_arch.directionality ==
00332                     BI_DIRECTIONAL ? GRAPH_BIDIR : GRAPH_UNIDIR);
00333         }
00334 
00335     max_pins_per_clb = 0;
00336     for(i = 0; i < num_types; i++)
00337         {
00338             max_pins_per_clb =
00339                 max(max_pins_per_clb, type_descriptors[i].num_pins);
00340         }
00341 
00342     clb_opins_used_locally = alloc_route_structs();
00343     best_routing = alloc_saved_routing(clb_opins_used_locally,
00344                                        &saved_clb_opins_used_locally);
00345 
00346     if(timing_inf.timing_analysis_enabled)
00347         {
00348             net_slack =
00349                 alloc_and_load_timing_graph(timing_inf);
00350             net_delay = alloc_net_delay(&net_delay_chunk_list_head, clb_net, num_nets);
00351         }
00352     else
00353         {
00354             net_delay = NULL;   /* Defensive coding. */
00355             net_slack = NULL;
00356         }
00357 
00358     /* UDSD by AY Start */
00359     if(det_routing_arch.directionality == BI_DIRECTIONAL)
00360         udsd_multiplier = 1;
00361     else
00362         udsd_multiplier = 2;
00363     /* UDSD by AY End */
00364 
00365     if(router_opts.fixed_channel_width != NO_FIXED_CHANNEL_WIDTH)
00366         {
00367             current = router_opts.fixed_channel_width + 5 * udsd_multiplier;
00368             low = router_opts.fixed_channel_width - 1 * udsd_multiplier;
00369         }
00370     else
00371         {
00372             current = max_pins_per_clb + max_pins_per_clb % 2;  /* Binary search part */
00373             low = -1;
00374         }
00375 
00376     /* Constraints must be checked to not break rr_graph generator */
00377     if(det_routing_arch.directionality == UNI_DIRECTIONAL)
00378         {
00379             if(current % 2 != 0)
00380                 {
00381                     printf
00382                         ("Error: pack_place_and_route.c: tried odd chan width (%d) for udsd architecture\n",
00383                          current);
00384                     exit(1);
00385                 }
00386         }
00387 
00388     else
00389         {
00390             if(det_routing_arch.Fs % 3)
00391                 {
00392                     printf("Fs must be three in bidirectional mode\n");
00393                     exit(1);
00394                 }
00395         }
00396 
00397     high = -1;
00398     final = -1;
00399     try_w_limit = 0;
00400 
00401     attempt_count = 0;
00402 
00403     while(final == -1)
00404         {
00405 
00406             printf("low, high, current %d %d %d\n", low, high, current);
00407             fflush(stdout);
00408 
00409 /* Check if the channel width is huge to avoid overflow.  Assume the *
00410  * circuit is unroutable with the current router options if we're    *
00411  * going to overflow.                                                */
00412             if(router_opts.fixed_channel_width != NO_FIXED_CHANNEL_WIDTH)
00413                 {
00414                     if(current > router_opts.fixed_channel_width * 4)
00415                         {
00416                             printf
00417                                 ("This circuit appears to be unroutable with the current "
00418                                  "router options. Last failed at %d\n", low);
00419                             printf("Aborting routing procedure.\n");
00420                             exit(1);
00421                         }
00422                 }
00423             else
00424                 {
00425                     if(current > 1000)
00426                         {
00427                             printf
00428                                 ("This circuit requires a channel width above 1000, probably isn't going to route.\n");
00429                             printf("Aborting routing procedure.\n");
00430                             exit(1);
00431                         }
00432                 }
00433 
00434             if((current * 3) < det_routing_arch.Fs)
00435                 {
00436                     printf
00437                         ("width factor is now below specified Fs. Stop search.\n");
00438                     final = high;
00439                     break;
00440                 }
00441 
00442             if(placer_opts.place_freq == PLACE_ALWAYS)
00443                 {
00444                     placer_opts.place_chan_width = current;
00445                     try_place(placer_opts, annealing_sched, chan_width_dist,
00446                               router_opts, det_routing_arch, segment_inf,
00447                               timing_inf, &mst);
00448                 }
00449             success =
00450                 try_route(current, router_opts, det_routing_arch, segment_inf,
00451                           timing_inf, net_slack, net_delay, chan_width_dist,
00452                           clb_opins_used_locally, mst, &Fc_clipped);
00453             attempt_count++;
00454             fflush(stdout);
00455 #if 1
00456             if(success && (Fc_clipped == FALSE))
00457                 {
00458 #else
00459             if(success
00460                && (Fc_clipped == FALSE
00461                    || det_routing_arch.Fc_type == FRACTIONAL))
00462                 {
00463 #endif
00464                         if(current == high) {
00465                                 /* Can't go any lower */
00466                                 final = current;
00467                         }
00468                         high = current;
00469 
00470                     /* If Fc_output is too high, set to full connectivity but warn the user */
00471                     if(Fc_clipped)
00472                         {
00473                             printf
00474                                 ("Warning: Fc_output was too high and was clipped to full (maximum) connectivity.\n");
00475                         }
00476 
00477 /* If we're re-placing constantly, save placement in case it is best. */
00478 #if 0
00479                     if(placer_opts.place_freq == PLACE_ALWAYS)
00480                         {
00481                             print_place(place_file, net_file, arch_file);
00482                         }
00483 #endif
00484 
00485                     /* Save routing in case it is best. */
00486                     save_routing(best_routing, clb_opins_used_locally,
00487                                  saved_clb_opins_used_locally);
00488 
00489                     if((high - low) <= 1 * udsd_multiplier)
00490                         final = high;
00491 
00492                     if(low != -1)
00493                         {
00494                             current = (high + low) / 2;
00495                         }
00496                     else
00497                         {
00498                             current = high / 2; /* haven't found lower bound yet */
00499                         }
00500                 }
00501             else
00502                 {               /* last route not successful */
00503                     if(success && Fc_clipped)
00504                         {
00505                             printf
00506                                 ("Routing rejected, Fc_output was too high.\n");
00507                             success = FALSE;
00508                         }
00509                     low = current;
00510                     if(high != -1)
00511                         {
00512 
00513                             if((high - low) <= 1 * udsd_multiplier)
00514                                 final = high;
00515 
00516                             current = (high + low) / 2;
00517                         }
00518                     else
00519                         {
00520                             if(router_opts.fixed_channel_width !=
00521                                NO_FIXED_CHANNEL_WIDTH)
00522                                 {
00523                                     /* FOR Wneed = f(Fs) search */
00524                                     if(low <
00525                                        router_opts.fixed_channel_width + 30)
00526                                         {
00527                                             current =
00528                                                 low + 5 * udsd_multiplier;
00529                                         }
00530                                     else
00531                                         {
00532                                             printf
00533                                                 ("Aborting: Wneed = f(Fs) search found exceedingly large Wneed (at least %d)\n",
00534                                                  low);
00535                                             exit(1);
00536                                         }
00537                                 }
00538                             else
00539                                 {
00540                                     current = low * 2;  /* Haven't found upper bound yet */
00541                                 }
00542                         }
00543                 }
00544             current = current + current % udsd_multiplier;
00545         }
00546 
00547 /* The binary search above occassionally does not find the minimum    *
00548  * routeable channel width.  Sometimes a circuit that will not route  *
00549  * in 19 channels will route in 18, due to router flukiness.  If      *  
00550  * verify_binary_search is set, the code below will ensure that FPGAs *
00551  * with channel widths of final-2 and final-3 wil not route           *  
00552  * successfully.  If one does route successfully, the router keeps    *
00553  * trying smaller channel widths until two in a row (e.g. 8 and 9)    *
00554  * fail.                                                              */
00555 
00556     if(verify_binary_search)
00557         {
00558 
00559             printf
00560                 ("\nVerifying that binary search found min. channel width ...\n");
00561 
00562             prev_success = TRUE;        /* Actually final - 1 failed, but this makes router */
00563             /* try final-2 and final-3 even if both fail: safer */
00564             prev2_success = TRUE;
00565 
00566             current = final - 2;
00567 
00568             while(prev2_success || prev_success)
00569                 {
00570                     if((router_opts.fixed_channel_width !=
00571                         NO_FIXED_CHANNEL_WIDTH)
00572                        && (current < router_opts.fixed_channel_width))
00573                         {
00574                             break;
00575                         }
00576                     fflush(stdout);
00577                     if(current < 1)
00578                         break;
00579                     if(placer_opts.place_freq == PLACE_ALWAYS)
00580                         {
00581                             placer_opts.place_chan_width = current;
00582                             try_place(placer_opts, annealing_sched,
00583                                       chan_width_dist, router_opts,
00584                                       det_routing_arch, segment_inf,
00585                                       timing_inf, &mst);
00586                         }
00587 
00588                     success =
00589                         try_route(current, router_opts, det_routing_arch,
00590                                   segment_inf, timing_inf, net_slack,
00591                                   net_delay, chan_width_dist,
00592                                   clb_opins_used_locally, mst, &Fc_clipped);
00593 
00594                     if(success && Fc_clipped == FALSE)
00595                         {
00596                             final = current;
00597                             save_routing(best_routing, clb_opins_used_locally,
00598                                          saved_clb_opins_used_locally);
00599 
00600                             if(placer_opts.place_freq == PLACE_ALWAYS)
00601                                 {
00602                                     print_place(place_file, net_file,
00603                                                 arch_file);
00604                                 }
00605                         }
00606 
00607 
00608                     prev2_success = prev_success;
00609                     prev_success = success;
00610                     current--;
00611                         if(det_routing_arch.directionality == UNI_DIRECTIONAL) {
00612                                 current--; /* width must be even */
00613                         }
00614                 }
00615         }
00616 
00617 
00618 
00619     /* End binary search verification. */
00620     /* Restore the best placement (if necessary), the best routing, and  *
00621      * * the best channel widths for final drawing and statistics output.  */
00622     init_chan(final, chan_width_dist);
00623 #if 0
00624     if(placer_opts.place_freq == PLACE_ALWAYS)
00625         {
00626             printf("Reading best placement back in.\n");
00627             placer_opts.place_chan_width = final;
00628             read_place(place_file, net_file, arch_file, placer_opts,
00629                        router_opts, chan_width_dist, det_routing_arch,
00630                        segment_inf, timing_inf, &mst);
00631         }
00632 #endif
00633     free_rr_graph();
00634 
00635     build_rr_graph(graph_type,
00636                    num_types, type_descriptors, nx, ny, grid,
00637                    chan_width_x[0], NULL,
00638                    det_routing_arch.switch_block_type, det_routing_arch.Fs,
00639                    det_routing_arch.num_segment, det_routing_arch.num_switch, segment_inf,
00640                    det_routing_arch.global_route_switch,
00641                    det_routing_arch.delayless_switch, timing_inf,
00642                    det_routing_arch.wire_to_ipin_switch,
00643                    router_opts.base_cost_type, &warnings);
00644 
00645     restore_routing(best_routing, clb_opins_used_locally,
00646                     saved_clb_opins_used_locally);
00647     check_route(router_opts.route_type, det_routing_arch.num_switch,
00648                 clb_opins_used_locally);
00649     get_serial_num();
00650     if(Fc_clipped)
00651         {
00652             printf
00653                 ("Warning: Best routing Fc_output too high, clipped to full (maximum) connectivity.\n");
00654         }
00655     printf("Best routing used a channel width factor of %d.\n\n", final);
00656 
00657     routing_stats(full_stats, router_opts.route_type,
00658                   det_routing_arch.num_switch, segment_inf,
00659                   det_routing_arch.num_segment,
00660                   det_routing_arch.R_minW_nmos,
00661                   det_routing_arch.R_minW_pmos,
00662                   det_routing_arch.directionality,
00663                   timing_inf.timing_analysis_enabled, net_slack, net_delay);
00664 
00665     print_route(route_file);
00666 
00667 #ifdef CREATE_ECHO_FILES
00668     /* print_sink_delays("routing_sink_delays.echo"); */
00669 #endif /* CREATE_ECHO_FILES */
00670 
00671     init_draw_coords(max_pins_per_clb);
00672     sprintf(msg, "Routing succeeded with a channel width factor of %d.",
00673             final);
00674     update_screen(MAJOR, msg, ROUTING, timing_inf.timing_analysis_enabled);
00675 
00676         if(timing_inf.timing_analysis_enabled)
00677         {
00678                 #ifdef CREATE_ECHO_FILES
00679                         print_timing_graph_as_blif("post_flow_timing_graph.blif", models);
00680                 #endif
00681             free_timing_graph(net_slack);
00682             free_net_delay(net_delay, &net_delay_chunk_list_head);
00683         }
00684 
00685     free_route_structs(clb_opins_used_locally);
00686     free_saved_routing(best_routing, saved_clb_opins_used_locally);
00687     fflush(stdout);
00688 
00689     return (final);
00690 }
00691 
00692 
00693 /** Assigns widths to channels (in tracks).  Minimum one track           
00694  * per channel.  io channels are io_rat * maximum in interior           
00695  * tracks wide.  The channel distributions read from the architecture  
00696  * file are scaled by cfactor.                                         
00697  */
00698 void
00699 init_chan(int cfactor,
00700           t_chan_width_dist chan_width_dist)
00701 {
00702 
00703     float x, separation, chan_width_io;
00704     int nio, i;
00705     t_chan chan_x_dist, chan_y_dist;
00706 
00707     chan_width_io = chan_width_dist.chan_width_io;
00708     chan_x_dist = chan_width_dist.chan_x_dist;
00709     chan_y_dist = chan_width_dist.chan_y_dist;
00710 
00711 /* io channel widths */
00712 
00713     nio = (int)floor(cfactor * chan_width_io + 0.5);
00714     if(nio == 0)
00715         nio = 1;                /* No zero width channels */
00716 
00717     chan_width_x[0] = chan_width_x[ny] = nio;
00718     chan_width_y[0] = chan_width_y[nx] = nio;
00719 
00720     if(ny > 1)
00721         {
00722             separation = 1. / (ny - 2.);        /* Norm. distance between two channels. */
00723             x = 0.;             /* This avoids div by zero if ny = 2. */
00724             chan_width_x[1] = (int)floor(cfactor * comp_width(&chan_x_dist, x,
00725                                                               separation) +
00726                                          0.5);
00727 
00728             /* No zero width channels */
00729             chan_width_x[1] = max(chan_width_x[1], 1);
00730 
00731             for(i = 1; i < ny - 1; i++)
00732                 {
00733                     x = (float)i / ((float)(ny - 2.));
00734                     chan_width_x[i + 1] =
00735                         (int)floor(cfactor *
00736                                    comp_width(&chan_x_dist, x,
00737                                               separation) + 0.5);
00738                     chan_width_x[i + 1] = max(chan_width_x[i + 1], 1);
00739                 }
00740         }
00741 
00742     if(nx > 1)
00743         {
00744             separation = 1. / (nx - 2.);        /* Norm. distance between two channels. */
00745             x = 0.;             /* Avoids div by zero if nx = 2. */
00746             chan_width_y[1] = (int)floor(cfactor * comp_width(&chan_y_dist, x,
00747                                                               separation) +
00748                                          0.5);
00749 
00750             chan_width_y[1] = max(chan_width_y[1], 1);
00751 
00752             for(i = 1; i < nx - 1; i++)
00753                 {
00754                     x = (float)i / ((float)(nx - 2.));
00755                     chan_width_y[i + 1] =
00756                         (int)floor(cfactor *
00757                                    comp_width(&chan_y_dist, x,
00758                                               separation) + 0.5);
00759                     chan_width_y[i + 1] = max(chan_width_y[i + 1], 1);
00760                 }
00761         }
00762 #ifdef VERBOSE
00763     printf("\nchan_width_x:\n");
00764     for(i = 0; i <= ny; i++)
00765         printf("%d  ", chan_width_x[i]);
00766     printf("\n\nchan_width_y:\n");
00767     for(i = 0; i <= nx; i++)
00768         printf("%d  ", chan_width_y[i]);
00769     printf("\n\n");
00770 #endif
00771 
00772 }
00773 
00774 
00775 /** Return the relative channel density.  *chan points to a channel   
00776  * functional description data structure, and x is the distance         
00777  * (between 0 and 1) we are across the chip.  separation is the         
00778  * distance between two channels, in the 0 to 1 coordinate system.   
00779  */
00780 static float
00781 comp_width(t_chan * chan,
00782            float x,
00783            float separation)
00784 {
00785     float val;
00786 
00787     switch (chan->type)
00788         {
00789 
00790         case UNIFORM:
00791             val = chan->peak;
00792             break;
00793 
00794         case GAUSSIAN:
00795             val = (x - chan->xpeak) * (x - chan->xpeak) / (2 * chan->width *
00796                                                            chan->width);
00797             val = chan->peak * exp(-val);
00798             val += chan->dc;
00799             break;
00800 
00801         case PULSE:
00802             val = (float)fabs((double)(x - chan->xpeak));
00803             if(val > chan->width / 2.)
00804                 {
00805                     val = 0;
00806                 }
00807             else
00808                 {
00809                     val = chan->peak;
00810                 }
00811             val += chan->dc;
00812             break;
00813 
00814         case DELTA:
00815             val = x - chan->xpeak;
00816             if(val > -separation / 2. && val <= separation / 2.)
00817                 val = chan->peak;
00818             else
00819                 val = 0.;
00820             val += chan->dc;
00821             break;
00822 
00823         default:
00824             printf("Error in comp_width:  Unknown channel type %d.\n",
00825                    chan->type);
00826             exit(1);
00827             break;
00828         }
00829 
00830     return (val);
00831 }
00832 
00833 /** After placement, logical pins for blocks, and nets must be updated to correspond with physical pins of type.
00834  * This function should only be called once 
00835  */
00836 void
00837 post_place_sync(INP int num_blocks,
00838                 INOUTP const struct s_block block_list[])
00839 {
00840     int iblk, j, k, inet;
00841     t_type_ptr type;
00842     int max_num_block_pins;
00843 
00844     /* Go through each block */
00845     for(iblk = 0; iblk < num_blocks; ++iblk)
00846         {
00847             type = block[iblk].type;
00848             assert(type->num_pins % type->capacity == 0);
00849             max_num_block_pins = type->num_pins / type->capacity;
00850             /* Logical location and physical location is offset by z * max_num_block_pins */
00851             /* Sync blocks and nets */
00852             for(j = 0; j < max_num_block_pins; j++)
00853                 {
00854                     inet = block[iblk].nets[j];
00855                     if(inet != OPEN && block[iblk].z > 0)
00856                         {
00857                             assert(block[iblk].
00858                                    nets[j +
00859                                         block[iblk].z * max_num_block_pins] ==
00860                                    OPEN);
00861                             block[iblk].nets[j +
00862                                              block[iblk].z *
00863                                              max_num_block_pins] =
00864                                 block[iblk].nets[j];
00865                             block[iblk].nets[j] = OPEN;
00866                                 for(k = 0; k <= clb_net[inet].num_sinks; k++)
00867                                 {
00868                                     if(clb_net[inet].node_block[k] == iblk)
00869                                         {
00870                                             assert(clb_net[inet].
00871                                                    node_block_pin[k] == j);
00872                                             clb_net[inet].node_block_pin[k] =
00873                                                 j +
00874                                                 block[iblk].z *
00875                                                 max_num_block_pins;
00876                                             break;
00877                                         }
00878                                 }
00879                                 assert(k <= clb_net[inet].num_sinks);
00880                         }
00881                 }
00882         }
00883 }
00884 
00885 void
00886 free_pb_data(t_pb *pb)
00887 {
00888         int i, j;
00889         const t_pb_type *pb_type;
00890         t_rr_node *temp;
00891 
00892         if(pb == NULL || pb->name == NULL) {
00893                 return;
00894         }
00895 
00896         pb_type = pb->pb_graph_node->pb_type;
00897 
00898         /* free existing rr graph for pb */
00899         if(pb->rr_graph) {
00900                 temp = rr_node;
00901                 rr_node = pb->rr_graph;
00902                 num_rr_nodes = pb->pb_graph_node->total_pb_pins;
00903                 free_rr_graph();
00904                 rr_node = temp;
00905         }
00906 
00907         if(pb_type->num_modes > 0) {
00908                 /* Free children of pb */
00909                 for(i = 0; i < pb_type->modes[pb->mode].num_pb_type_children; i++) {
00910                         for(j = 0; j < pb_type->modes[pb->mode].pb_type_children[i].num_pb; j++) {
00911                                 if(pb->child_pbs[i]) {
00912                                         free_pb_data(&pb->child_pbs[i][j]);
00913                                 }
00914                         }
00915                 }
00916         }
00917 
00918         /* Frees all the pb data structures.                                 */
00919         if(pb->name) {
00920                 free(pb->name);
00921                 if(pb->child_pbs) {
00922                         free(pb->child_pbs);
00923                 }
00924         }
00925 }