VPR-6.0

vpr/SRC/place/timing_place_lookup.c

Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <math.h>
00003 #include <string.h>
00004 #include "util.h"
00005 #include "vpr_types.h"
00006 #include "globals.h"
00007 #include "route_common.h"
00008 #include "place_and_route.h"
00009 #include "route_tree_timing.h"
00010 #include "route_timing.h"
00011 #include "timing_place_lookup.h"
00012 #include "rr_graph.h"
00013 #include "mst.h"
00014 #include "route_export.h"
00015 #include <assert.h>
00016 #include "read_xml_arch_file.h"
00017 
00018 /*
00019  * @file
00020  *
00021  * this file contains routines that generate the array containing
00022  * the delays between blocks, this is used in the timing driven  
00023  * placement routines.
00024  *
00025  * To compute delay between blocks we place temporary blocks at 
00026  * different locations in the FPGA and route nets  between      
00027  * the blocks.  From this procedure we generate a lookup table  
00028  * which tells us the delay between different locations in      
00029  * the FPGA 
00030  *
00031  * Note: these routines assume that there is a uniform and even 
00032  * distribution of the different wire segments. If this is not  
00033  * the case, then this lookup table will be off 
00034  * 
00035  * Note: This code removes all heterogeneous types and creates an
00036  * artificial 1x1 tile.  A good lookup for heterogeniety requires 
00037  * more research 
00038  */
00039 
00040 #define NET_COUNT 1             /**< we only use one net in these routines,   
00041                                      it is repeatedly routed and ripped up    
00042                                      to compute delays between different      
00043                                      locations, this value should not change  */
00044 #define NET_USED 0              /**< we use net at location zero of the net structure */
00045 #define NET_USED_SOURCE_BLOCK 0 /**< net.block[0] is source block */
00046 #define NET_USED_SINK_BLOCK 1   /**< net.block[1] is sink block */
00047 #define SOURCE_BLOCK 0          /**< block[0] is source */
00048 #define SINK_BLOCK 1            /**< block[1] is sink */
00049 
00050 #define BLOCK_COUNT 2           /**< use 2 blocks to compute delay between  
00051                                  * the various FPGA locations             
00052                                  * do not change this number unless you   
00053                                  * really know what you are doing, it is  
00054                                  * assumed that the net only connects to  
00055                                  * two blocks */
00056 
00057 #define NUM_TYPES_USED 3        /**< number of types used in look up */
00058 
00059 #define DEBUG_TIMING_PLACE_LOOKUP       /**< initialize arrays to known state */
00060 
00061 #define DUMPFILE "lookup_dump.echo"
00062 /* #define PRINT_ARRAYS *//**<only used during debugging, calls routine to  
00063                            * print out the various lookup arrays           */
00064 
00065 /***variables that are exported to other modules***/
00066 
00067 /**@{*/
00068 /** the delta arrays are used to contain the best case routing delay 
00069  * between different locations on the FPGA. 
00070  */
00071 float **delta_io_to_clb;
00072 float **delta_clb_to_clb;
00073 float **delta_clb_to_io;
00074 float **delta_io_to_io;
00075 /**@}*/
00076 
00077 /*** Other Global Arrays ******/
00078 /* I could have allocated these as local variables, and passed them all */
00079 /* around, but was too lazy, since this is a small file, it should not  */
00080 /* be a big problem */
00081 
00082 static float **net_delay;
00083 static float **net_slack;
00084 static float *pin_criticality;
00085 static int *sink_order;
00086 static t_rt_node **rt_node_of_sink;
00087 static t_type_ptr IO_TYPE_BACKUP;
00088 static t_type_ptr EMPTY_TYPE_BACKUP;
00089 static t_type_ptr FILL_TYPE_BACKUP;
00090 static t_type_descriptor dummy_type_descriptors[NUM_TYPES_USED];
00091 static t_type_descriptor *type_descriptors_backup;
00092 static struct s_grid_tile **grid_backup;
00093 static int num_types_backup;
00094 
00095 static t_ivec **clb_opins_used_locally;
00096 
00097 #ifdef PRINT_ARRAYS
00098 static FILE *lookup_dump;       /**< If debugging mode is on, print out to
00099                                  * the file defined in DUMPFILE */
00100 #endif /* PRINT_ARRAYS */
00101 
00102 /*** Function Prototypes *****/
00103 
00104 static void alloc_net(void);
00105 
00106 static void alloc_block(void);
00107 
00108 static void load_simplified_device(void);
00109 static void restore_original_device(void);
00110 
00111 static void alloc_and_assign_internal_structures(struct s_net **original_net,
00112                                                  struct s_block
00113                                                  **original_block,
00114                                                  int *original_num_nets,
00115                                                  int *original_num_blocks);
00116 
00117 static void free_and_reset_internal_structures(struct s_net *original_net,
00118                                                struct s_block *original_block,
00119                                                int original_num_nets,
00120                                                int original_num_blocks);
00121 
00122 static void setup_chan_width(struct s_router_opts router_opts,
00123                              t_chan_width_dist chan_width_dist);
00124 
00125 static void alloc_routing_structs(struct s_router_opts router_opts,
00126                                   struct s_det_routing_arch det_routing_arch,
00127                                   t_segment_inf * segment_inf,
00128                                   t_timing_inf timing_inf);
00129 
00130 static void free_routing_structs(struct s_router_opts router_opts,
00131                                  struct s_det_routing_arch det_routing_arch,
00132                                  t_segment_inf * segment_inf,
00133                                  t_timing_inf timing_inf);
00134 
00135 static void assign_locations(t_type_ptr source_type,
00136                              int source_x_loc,
00137                              int source_y_loc,
00138                              int source_z_loc,
00139                              t_type_ptr sink_type,
00140                              int sink_x_loc,
00141                              int sink_y_loc,
00142                              int sink_z_loc);
00143 
00144 static float assign_blocks_and_route_net(t_type_ptr source_type,
00145                                          int source_x_loc,
00146                                          int source_y_loc,
00147                                          t_type_ptr sink_type,
00148                                          int sink_x_loc,
00149                                          int sink_y_loc,
00150                                          struct s_router_opts router_opts,
00151                                          struct s_det_routing_arch
00152                                          det_routing_arch,
00153                                          t_segment_inf * segment_inf,
00154                                          t_timing_inf timing_inf);
00155 
00156 static void alloc_delta_arrays(void);
00157 
00158 static void free_delta_arrays(void);
00159 
00160 static void generic_compute_matrix(float ***matrix_ptr,
00161                                    t_type_ptr source_type,
00162                                    t_type_ptr sink_type,
00163                                    int source_x,
00164                                    int source_y,
00165                                    int start_x,
00166                                    int end_x,
00167                                    int start_y,
00168                                    int end_y,
00169                                    struct s_router_opts router_opts,
00170                                    struct s_det_routing_arch det_routing_arch,
00171                                    t_segment_inf * segment_inf,
00172                                    t_timing_inf timing_inf);
00173 
00174 static void compute_delta_clb_to_clb(struct s_router_opts router_opts,
00175                                    struct s_det_routing_arch det_routing_arch,
00176                                    t_segment_inf * segment_inf,
00177                                    t_timing_inf timing_inf,
00178                                    int longest_length);
00179 
00180 static void compute_delta_io_to_clb(struct s_router_opts router_opts,
00181                                    struct s_det_routing_arch det_routing_arch,
00182                                    t_segment_inf * segment_inf,
00183                                    t_timing_inf timing_inf);
00184 
00185 static void compute_delta_clb_to_io(struct s_router_opts router_opts,
00186                                    struct s_det_routing_arch det_routing_arch,
00187                                    t_segment_inf * segment_inf,
00188                                    t_timing_inf timing_inf);
00189 
00190 static void compute_delta_io_to_io(struct s_router_opts router_opts,
00191                                    struct s_det_routing_arch det_routing_arch,
00192                                    t_segment_inf * segment_inf,
00193                                    t_timing_inf timing_inf);
00194 
00195 static void compute_delta_arrays(struct s_router_opts router_opts,
00196                                  struct s_det_routing_arch det_routing_arch,
00197                                  t_segment_inf * segment_inf,
00198                                  t_timing_inf timing_inf,
00199                                  int longest_length);
00200 
00201 static int get_first_pin(enum e_pin_type pintype,
00202                          t_type_ptr type);
00203 
00204 static int get_longest_segment_length(struct s_det_routing_arch
00205                                       det_routing_arch,
00206                                       t_segment_inf * segment_inf);
00207 static void reset_placement(void);
00208 
00209 #ifdef PRINT_ARRAYS
00210 static void print_array(float **array_to_print,
00211                         int x1,
00212                         int x2,
00213                         int y1,
00214                         int y2);
00215 #endif
00216 /**************************************/
00217 /** this code assumes logical equivilance between all driving pins 
00218  * global pins are not hooked up to the temporary net 
00219  */
00220 static int
00221 get_first_pin(enum e_pin_type pintype,
00222               t_type_ptr type)
00223 {
00224 
00225     int i, currpin;
00226 
00227     currpin = 0;
00228     for(i = 0; i < type->num_class; i++)
00229         {
00230             if(type->class_inf[i].type == pintype
00231                && !type->is_global_pin[currpin])
00232                 return (type->class_inf[i].pinlist[0]);
00233             else
00234                 currpin += type->class_inf[i].num_pins;
00235         }
00236     assert(0);
00237     exit(0);                    /*should never hit this line */
00238 }
00239 
00240 /**************************************/
00241 static int
00242 get_longest_segment_length(struct s_det_routing_arch det_routing_arch,
00243                            t_segment_inf * segment_inf)
00244 {
00245 
00246     int i, length;
00247 
00248     length = 0;
00249     for(i = 0; i < det_routing_arch.num_segment; i++)
00250         {
00251             if(segment_inf[i].length > length)
00252                 length = segment_inf[i].length;
00253         }
00254     return (length);
00255 }
00256 
00257 /**************************************/
00258 static void
00259 alloc_net(void)
00260 {
00261 
00262     int i, len;
00263 
00264     clb_net = (struct s_net *)my_malloc(num_nets * sizeof(struct s_net));
00265     for(i = 0; i < NET_COUNT; i++)
00266         {
00267             /* FIXME: We *really* shouldn't be allocating write-once copies */
00268             len = strlen("TEMP_NET");
00269             clb_net[i].name = (char *)my_malloc((len + 1) * sizeof(char));
00270             clb_net[i].is_global = FALSE;
00271             strcpy(clb_net[NET_USED].name, "TEMP_NET");
00272 
00273             clb_net[i].num_sinks = (BLOCK_COUNT - 1);
00274             clb_net[i].node_block = (int *)my_malloc(BLOCK_COUNT * sizeof(int));
00275             clb_net[i].node_block[NET_USED_SOURCE_BLOCK] = NET_USED_SOURCE_BLOCK;       /*driving block */
00276             clb_net[i].node_block[NET_USED_SINK_BLOCK] = NET_USED_SINK_BLOCK;   /*target block */
00277 
00278             clb_net[i].node_block_pin =
00279                 (int *)my_malloc(BLOCK_COUNT * sizeof(int));
00280             /*the values for this are allocated in assign_blocks_and_route_net */
00281 
00282         }
00283 }
00284 
00285 /**************************************/
00286 /** allocates block structure, and assigns values to known parameters 
00287  * type and x,y fields are left undefined at this stage since they  
00288  * are not known until we start moving blocks through the clb array 
00289  */
00290 static void
00291 alloc_block(void)
00292 {
00293 
00294     int ix_b, ix_p, len, i;
00295     int max_pins;
00296 
00297     max_pins = 0;
00298     for(i = 0; i < NUM_TYPES_USED; i++)
00299         {
00300             max_pins = max(max_pins, type_descriptors[i].num_pins);
00301         }
00302 
00303     block = (struct s_block *)my_malloc(num_blocks * sizeof(struct s_block));
00304 
00305     for(ix_b = 0; ix_b < BLOCK_COUNT; ix_b++)
00306         {
00307             len = strlen("TEMP_BLOCK");
00308             block[ix_b].name = (char *)my_malloc((len + 1) * sizeof(char));
00309             strcpy(block[ix_b].name, "TEMP_BLOCK");
00310 
00311             block[ix_b].nets = (int *)my_malloc(max_pins * sizeof(int));
00312             block[ix_b].nets[0] = 0;
00313             for(ix_p = 1; ix_p < max_pins; ix_p++)
00314                 block[ix_b].nets[ix_p] = OPEN;
00315         }
00316 }
00317 
00318 /**************************************/
00319 static void
00320 load_simplified_device(void)
00321 {
00322     int i, j;
00323 
00324     /* Backup original globals */
00325     EMPTY_TYPE_BACKUP = EMPTY_TYPE;
00326     IO_TYPE_BACKUP = IO_TYPE;
00327     FILL_TYPE_BACKUP = FILL_TYPE;
00328     type_descriptors_backup = type_descriptors;
00329     num_types_backup = num_types;
00330     num_types = NUM_TYPES_USED;
00331 
00332     /* Fill in homogeneous core type info */
00333     dummy_type_descriptors[0] = *EMPTY_TYPE;
00334     dummy_type_descriptors[0].index = 0;
00335     dummy_type_descriptors[1] = *IO_TYPE;
00336     dummy_type_descriptors[1].index = 1;
00337     dummy_type_descriptors[2] = *FILL_TYPE;
00338     dummy_type_descriptors[2].index = 2;
00339     type_descriptors = dummy_type_descriptors;
00340     EMPTY_TYPE = &dummy_type_descriptors[0];
00341     IO_TYPE = &dummy_type_descriptors[1];
00342     FILL_TYPE = &dummy_type_descriptors[2];
00343 
00344     /* Fill in homogeneous core grid info */
00345     grid_backup = grid;
00346     grid =
00347         (struct s_grid_tile **)alloc_matrix(0, nx + 1, 0, ny + 1,
00348                                             sizeof(struct s_grid_tile));
00349     for(i = 0; i < nx + 2; i++)
00350         {
00351             for(j = 0; j < ny + 2; j++)
00352                 {
00353                     if((i == 0 && j == 0) ||
00354                        (i == nx + 1 && j == 0) ||
00355                        (i == 0 && j == ny + 1) || (i == nx + 1
00356                                                    && j == ny + 1))
00357                         {
00358                             grid[i][j].type = EMPTY_TYPE;
00359                         }
00360                     else if(i == 0 || i == nx + 1 || j == 0 || j == ny + 1)
00361                         {
00362                             grid[i][j].type = IO_TYPE;
00363                         }
00364                     else
00365                         {
00366                             grid[i][j].type = FILL_TYPE;
00367                         }
00368                     grid[i][j].blocks =
00369                         my_malloc(grid[i][j].type->capacity * sizeof(int));
00370                     grid[i][j].offset = 0;
00371                 }
00372         }
00373 }
00374 static void
00375 restore_original_device(void)
00376 {
00377     int i, j;
00378 
00379     /* restore previous globals */
00380     IO_TYPE = IO_TYPE_BACKUP;
00381     EMPTY_TYPE = EMPTY_TYPE_BACKUP;
00382     FILL_TYPE = FILL_TYPE_BACKUP;
00383     type_descriptors = type_descriptors_backup;
00384     num_types = num_types_backup;
00385 
00386     /* free allocatd data */
00387     for(i = 0; i < nx + 2; i++)
00388         {
00389             for(j = 0; j < ny + 2; j++)
00390                 {
00391                     free(grid[i][j].blocks);
00392                 }
00393         }
00394     free_matrix(grid, 0, nx + 1, 0, sizeof(struct s_grid_tile));
00395     grid = grid_backup;
00396 }
00397 
00398 /**************************************/
00399 static void
00400 reset_placement(void)
00401 {
00402     int i, j, k;
00403 
00404     for(i = 0; i <= nx + 1; i++)
00405         {
00406             for(j = 0; j <= ny + 1; j++)
00407                 {
00408                     grid[i][j].usage = 0;
00409                     for(k = 0; k < grid[i][j].type->capacity; k++)
00410                         {
00411                             grid[i][j].blocks[k] = EMPTY;
00412                         }
00413                 }
00414         }
00415 }
00416 
00417 /**************************************/
00418 /** allocate new data structures to hold net, and block info */
00419 static void
00420 alloc_and_assign_internal_structures(struct s_net **original_net,
00421                                      struct s_block **original_block,
00422                                      int *original_num_nets,
00423                                      int *original_num_blocks)
00424 {
00425 
00426     *original_net = clb_net;
00427     *original_num_nets = num_nets;
00428     num_nets = NET_COUNT;
00429     alloc_net();
00430 
00431     *original_block = block;
00432     *original_num_blocks = num_blocks;
00433     num_blocks = BLOCK_COUNT;
00434     alloc_block();
00435 
00436 
00437     /* [0..num_nets-1][1..num_pins-1] */
00438     net_delay =
00439         (float **)alloc_matrix(0, NET_COUNT - 1, 1, BLOCK_COUNT - 1,
00440                                sizeof(float));
00441     net_slack =
00442         (float **)alloc_matrix(0, NET_COUNT - 1, 1, BLOCK_COUNT - 1,
00443                                sizeof(float));
00444 
00445     reset_placement();
00446 }
00447 
00448 /**************************************/
00449 /** reset gloabal data structures to the state that they were in before these 
00450  * lookup computation routines were called 
00451  */
00452 static void
00453 free_and_reset_internal_structures(struct s_net *original_net,
00454                                    struct s_block *original_block,
00455                                    int original_num_nets,
00456                                    int original_num_blocks)
00457 {
00458     int i;
00459 
00460 
00461     /*there should be only one net to free, but this is safer */
00462     for(i = 0; i < NET_COUNT; i++)
00463         {
00464             free(clb_net[i].name);
00465             free(clb_net[i].node_block);
00466             free(clb_net[i].node_block_pin);
00467         }
00468     free(clb_net);
00469     clb_net = original_net;
00470 
00471     for(i = 0; i < BLOCK_COUNT; i++)
00472         {
00473             free(block[i].name);
00474             free(block[i].nets);
00475         }
00476     free(block);
00477     block = original_block;
00478 
00479     num_nets = original_num_nets;
00480     num_blocks = original_num_blocks;
00481 
00482     free_matrix(net_delay, 0, NET_COUNT - 1, 1, sizeof(float));
00483     free_matrix(net_slack, 0, NET_COUNT - 1, 1, sizeof(float));
00484 
00485 }
00486 
00487 /**************************************/
00488 /** we give plenty of tracks, this increases routability for the 
00489  * lookup table generation */
00490 static void
00491 setup_chan_width(struct s_router_opts router_opts,
00492                  t_chan_width_dist chan_width_dist)
00493 {
00494     int width_fac, i, max_pins_per_clb;
00495 
00496     max_pins_per_clb = 0;
00497     for(i = 0; i < num_types; i++)
00498         {
00499             max_pins_per_clb =
00500                 max(max_pins_per_clb, type_descriptors[i].num_pins);
00501         }
00502 
00503     if(router_opts.fixed_channel_width == NO_FIXED_CHANNEL_WIDTH)
00504         width_fac = 4 * max_pins_per_clb;       /*this is 2x the value that binary search starts */
00505     /*this should be enough to allow most pins to   */
00506     /*connect to tracks in the architecture */
00507     else
00508         width_fac = router_opts.fixed_channel_width;
00509 
00510     init_chan(width_fac, chan_width_dist);
00511 }
00512 
00513 /**************************************/
00514 /** calls routines that set up routing resource graph and associated structures */
00515 static void
00516 alloc_routing_structs(struct s_router_opts router_opts,
00517                       struct s_det_routing_arch det_routing_arch,
00518                       t_segment_inf * segment_inf,
00519                       t_timing_inf timing_inf)
00520 {
00521 
00522     int bb_factor;
00523     int warnings;
00524     t_graph_type graph_type;
00525     
00526     /*must set up dummy blocks for the first pass through to setup locally used opins */
00527     /* Only one block per tile */
00528     assign_locations(FILL_TYPE, 1, 1, 0, FILL_TYPE, nx, ny, 0);
00529 
00530     clb_opins_used_locally = alloc_route_structs();
00531 
00532     free_rr_graph();
00533         
00534         if(router_opts.route_type == GLOBAL) {
00535                 graph_type = GRAPH_GLOBAL;
00536         } else {
00537                 graph_type = (det_routing_arch.directionality ==
00538                     BI_DIRECTIONAL ? GRAPH_BIDIR : GRAPH_UNIDIR);
00539         }
00540     
00541         build_rr_graph(graph_type, num_types, dummy_type_descriptors, nx,
00542                        ny, grid, chan_width_x[0], NULL,
00543                        det_routing_arch.switch_block_type,
00544                            det_routing_arch.Fs, det_routing_arch.num_segment, det_routing_arch.num_switch,
00545                        segment_inf, det_routing_arch.global_route_switch,
00546                        det_routing_arch.delayless_switch, timing_inf,
00547                        det_routing_arch.wire_to_ipin_switch,
00548                        router_opts.base_cost_type, &warnings);
00549 
00550     alloc_and_load_rr_node_route_structs();
00551 
00552     alloc_timing_driven_route_structs(&pin_criticality, &sink_order,
00553                                       &rt_node_of_sink);
00554 
00555 
00556     bb_factor = nx + ny;        /*set it to a huge value */
00557     init_route_structs(bb_factor);
00558 }
00559 
00560 /**************************************/
00561 static void
00562 free_routing_structs(struct s_router_opts router_opts,
00563                      struct s_det_routing_arch det_routing_arch,
00564                      t_segment_inf * segment_inf,
00565                      t_timing_inf timing_inf)
00566 {
00567     free_rr_graph();
00568 
00569     free_rr_node_route_structs();
00570     free_route_structs(clb_opins_used_locally);
00571     free_trace_structs();
00572 
00573     free_timing_driven_route_structs(pin_criticality, sink_order,
00574                                      rt_node_of_sink);
00575 }
00576 
00577 /**************************************/
00578 static void
00579 assign_locations(t_type_ptr source_type,
00580                  int source_x_loc,
00581                  int source_y_loc,
00582                  int source_z_loc,
00583                  t_type_ptr sink_type,
00584                  int sink_x_loc,
00585                  int sink_y_loc,
00586                  int sink_z_loc)
00587 {
00588     /*all routing occurs between block 0 (source) and block 1 (sink) */
00589     block[SOURCE_BLOCK].type = source_type;
00590     block[SOURCE_BLOCK].x = source_x_loc;
00591     block[SOURCE_BLOCK].y = source_y_loc;
00592     block[SOURCE_BLOCK].z = source_z_loc;
00593 
00594     block[SINK_BLOCK].type = sink_type;
00595     block[SINK_BLOCK].x = sink_x_loc;
00596     block[SINK_BLOCK].y = sink_y_loc;
00597     block[SINK_BLOCK].z = sink_z_loc;
00598 
00599     grid[source_x_loc][source_y_loc].blocks[source_z_loc] = SOURCE_BLOCK;
00600     grid[sink_x_loc][sink_y_loc].blocks[sink_z_loc] = SINK_BLOCK;
00601 
00602     clb_net[NET_USED].node_block_pin[NET_USED_SOURCE_BLOCK] =
00603         get_first_pin(DRIVER, block[SOURCE_BLOCK].type);
00604     clb_net[NET_USED].node_block_pin[NET_USED_SINK_BLOCK] =
00605         get_first_pin(RECEIVER, block[SINK_BLOCK].type);
00606 
00607     grid[source_x_loc][source_y_loc].usage += 1;
00608     grid[sink_x_loc][sink_y_loc].usage += 1;
00609 
00610 }
00611 
00612 /**************************************/
00613 /** places blocks at the specified locations, and routes a net between them
00614  * @returns the delay of this net 
00615  */
00616 static float
00617 assign_blocks_and_route_net(t_type_ptr source_type,
00618                             int source_x_loc,
00619                             int source_y_loc,
00620                             t_type_ptr sink_type,
00621                             int sink_x_loc,
00622                             int sink_y_loc,
00623                             struct s_router_opts router_opts,
00624                             struct s_det_routing_arch det_routing_arch,
00625                             t_segment_inf * segment_inf,
00626                             t_timing_inf timing_inf)
00627 {
00628     boolean is_routeable;
00629     int ipin;
00630     float pres_fac, T_crit;
00631     float net_delay_value;
00632 
00633     int source_z_loc, sink_z_loc;
00634 
00635     /* Only one block per tile */
00636     source_z_loc = 0;
00637     sink_z_loc = 0;
00638 
00639     net_delay_value = IMPOSSIBLE;       /*set to known value for debug purposes */
00640 
00641     assign_locations(source_type, source_x_loc, source_y_loc, source_z_loc,
00642                      sink_type, sink_x_loc, sink_y_loc, sink_z_loc);
00643 
00644     load_net_rr_terminals(rr_node_indices);
00645 
00646     T_crit = 1;
00647     pres_fac = 0;               /* ignore congestion */
00648 
00649     for(ipin = 1; ipin <= clb_net[NET_USED].num_sinks; ipin++)
00650         net_slack[NET_USED][ipin] = 0;
00651 
00652     is_routeable = timing_driven_route_net(NET_USED, pres_fac,
00653                                            router_opts.max_criticality,
00654                                            router_opts.criticality_exp,
00655                                            router_opts.astar_fac,
00656                                            router_opts.bend_cost,
00657                                            net_slack[NET_USED],
00658                                            pin_criticality, sink_order,
00659                                            rt_node_of_sink, T_crit,
00660                                            net_delay[NET_USED]);
00661 
00662     net_delay_value = net_delay[NET_USED][NET_USED_SINK_BLOCK];
00663 
00664     grid[source_x_loc][source_y_loc].usage = 0;
00665     grid[source_x_loc][source_y_loc].blocks[source_z_loc] = EMPTY;
00666     grid[sink_x_loc][sink_y_loc].usage = 0;
00667     grid[sink_x_loc][sink_y_loc].blocks[sink_z_loc] = EMPTY;
00668 
00669     return (net_delay_value);
00670 }
00671 
00672 /**************************************/
00673 static void
00674 alloc_delta_arrays(void)
00675 {
00676     int id_x, id_y;
00677 
00678     delta_clb_to_clb =
00679         (float **)alloc_matrix(0, nx - 1, 0, ny - 1, sizeof(float));
00680     delta_io_to_clb = (float **)alloc_matrix(0, nx, 0, ny, sizeof(float));
00681     delta_clb_to_io = (float **)alloc_matrix(0, nx, 0, ny, sizeof(float));
00682     delta_io_to_io =
00683         (float **)alloc_matrix(0, nx + 1, 0, ny + 1, sizeof(float));
00684 
00685 
00686     /*initialize all of the array locations to -1 */
00687 
00688     for(id_x = 0; id_x <= nx; id_x++)
00689         {
00690             for(id_y = 0; id_y <= ny; id_y++)
00691                 {
00692                     delta_io_to_clb[id_x][id_y] = IMPOSSIBLE;
00693                 }
00694         }
00695     for(id_x = 0; id_x <= nx - 1; id_x++)
00696         {
00697             for(id_y = 0; id_y <= ny - 1; id_y++)
00698                 {
00699                     delta_clb_to_clb[id_x][id_y] = IMPOSSIBLE;
00700                 }
00701         }
00702     for(id_x = 0; id_x <= nx; id_x++)
00703         {
00704             for(id_y = 0; id_y <= ny; id_y++)
00705                 {
00706                     delta_clb_to_io[id_x][id_y] = IMPOSSIBLE;
00707                 }
00708         }
00709     for(id_x = 0; id_x <= nx + 1; id_x++)
00710         {
00711             for(id_y = 0; id_y <= ny + 1; id_y++)
00712                 {
00713                     delta_io_to_io[id_x][id_y] = IMPOSSIBLE;
00714                 }
00715         }
00716 }
00717 
00718 /**************************************/
00719 static void
00720 free_delta_arrays(void)
00721 {
00722 
00723     free_matrix(delta_io_to_clb, 0, nx, 0, sizeof(float));
00724     free_matrix(delta_clb_to_clb, 0, nx - 1, 0, sizeof(float));
00725     free_matrix(delta_clb_to_io, 0, nx, 0, sizeof(float));
00726     free_matrix(delta_io_to_io, 0, nx + 1, 0, sizeof(float));
00727 
00728 }
00729 
00730 /**************************************/
00731 static void
00732 generic_compute_matrix(float ***matrix_ptr,
00733                        t_type_ptr source_type,
00734                        t_type_ptr sink_type,
00735                        int source_x,
00736                        int source_y,
00737                        int start_x,
00738                        int end_x,
00739                        int start_y,
00740                        int end_y,
00741                        struct s_router_opts router_opts,
00742                        struct s_det_routing_arch det_routing_arch,
00743                        t_segment_inf * segment_inf,
00744                        t_timing_inf timing_inf)
00745 {
00746 
00747     int delta_x, delta_y;
00748     int sink_x, sink_y;
00749 
00750     for(sink_x = start_x; sink_x <= end_x; sink_x++)
00751         {
00752             for(sink_y = start_y; sink_y <= end_y; sink_y++)
00753                 {
00754                     delta_x = abs(sink_x - source_x);
00755                     delta_y = abs(sink_y - source_y);
00756 
00757                     if(delta_x == 0 && delta_y == 0)
00758                         continue;       /*do not compute distance from a block to itself     */
00759                     /*if a value is desired, pre-assign it somewhere else */
00760 
00761                     (*matrix_ptr)[delta_x][delta_y] =
00762                         assign_blocks_and_route_net(source_type, source_x,
00763                                                     source_y, sink_type,
00764                                                     sink_x, sink_y,
00765                                                     router_opts,
00766                                                     det_routing_arch,
00767                                                     segment_inf, timing_inf);
00768                 }
00769         }
00770 }
00771 
00772 /**************************************/
00773 /** this routine must compute delay values in a slightly different way than the 
00774  * other compute routines. We cannot use a location close to the edge as the  
00775  * source location for the majority of the delay computations  because this   
00776  * would give gradually increasing delay values. To avoid this from happening 
00777  * a clb that is at least longest_length away from an edge should be chosen   
00778  * as a source , if longest_length is more than 0.5 of the total size then    
00779  * choose a CLB at the center as the source CLB 
00780  */
00781 static void
00782 compute_delta_clb_to_clb(struct s_router_opts router_opts,
00783                        struct s_det_routing_arch det_routing_arch,
00784                        t_segment_inf * segment_inf,
00785                        t_timing_inf timing_inf,
00786                        int longest_length)
00787 {
00788 
00789     int source_x, source_y, sink_x, sink_y;
00790     int start_x, start_y, end_x, end_y;
00791     int delta_x, delta_y;
00792     t_type_ptr source_type, sink_type;
00793 
00794     source_type = FILL_TYPE;
00795     sink_type = FILL_TYPE;
00796 
00797     if(longest_length < 0.5 * (nx))
00798         {
00799             start_x = longest_length;
00800         }
00801     else
00802         {
00803             start_x = (int)(0.5 * nx);
00804         }
00805     end_x = nx;
00806     source_x = start_x;
00807 
00808     if(longest_length < 0.5 * (ny))
00809         {
00810             start_y = longest_length;
00811         }
00812     else
00813         {
00814             start_y = (int)(0.5 * ny);
00815         }
00816     end_y = ny;
00817     source_y = start_y;
00818 
00819 
00820     /*don't put the sink all the way to the corner, until it is necessary */
00821     for(sink_x = start_x; sink_x <= end_x - 1; sink_x++)
00822         {
00823             for(sink_y = start_y; sink_y <= end_y - 1; sink_y++)
00824                 {
00825                     delta_x = abs(sink_x - source_x);
00826                     delta_y = abs(sink_y - source_y);
00827 
00828                     if(delta_x == 0 && delta_y == 0)
00829                         {
00830                             delta_clb_to_clb[delta_x][delta_y] = 0.0;
00831                             continue;
00832                         }
00833                     delta_clb_to_clb[delta_x][delta_y] =
00834                         assign_blocks_and_route_net(source_type, source_x,
00835                                                     source_y, sink_type,
00836                                                     sink_x, sink_y,
00837                                                     router_opts,
00838                                                     det_routing_arch,
00839                                                     segment_inf, timing_inf);
00840                 }
00841 
00842         }
00843 
00844 
00845     sink_x = end_x - 1;
00846     sink_y = end_y - 1;
00847 
00848     for(source_x = start_x - 1; source_x >= 1; source_x--)
00849         {
00850             for(source_y = start_y; source_y <= end_y - 1; source_y++)
00851                 {
00852                     delta_x = abs(sink_x - source_x);
00853                     delta_y = abs(sink_y - source_y);
00854 
00855                     delta_clb_to_clb[delta_x][delta_y] =
00856                         assign_blocks_and_route_net(source_type, source_x,
00857                                                     source_y, sink_type,
00858                                                     sink_x, sink_y,
00859                                                     router_opts,
00860                                                     det_routing_arch,
00861                                                     segment_inf, timing_inf);
00862                 }
00863         }
00864 
00865     for(source_x = 1; source_x <= end_x - 1; source_x++)
00866         {
00867             for(source_y = 1; source_y < start_y; source_y++)
00868                 {
00869                     delta_x = abs(sink_x - source_x);
00870                     delta_y = abs(sink_y - source_y);
00871 
00872                     delta_clb_to_clb[delta_x][delta_y] =
00873                         assign_blocks_and_route_net(source_type, source_x,
00874                                                     source_y, sink_type,
00875                                                     sink_x, sink_y,
00876                                                     router_opts,
00877                                                     det_routing_arch,
00878                                                     segment_inf, timing_inf);
00879                 }
00880         }
00881 
00882 
00883     /*now move sink into the top right corner */
00884     sink_x = end_x;
00885     sink_y = end_y;
00886     source_x = 1;
00887     for(source_y = 1; source_y <= end_y; source_y++)
00888         {
00889             delta_x = abs(sink_x - source_x);
00890             delta_y = abs(sink_y - source_y);
00891 
00892             delta_clb_to_clb[delta_x][delta_y] =
00893                 assign_blocks_and_route_net(source_type, source_x, source_y,
00894                                             sink_type, sink_x, sink_y,
00895                                             router_opts, det_routing_arch,
00896                                             segment_inf, timing_inf);
00897 
00898         }
00899 
00900     sink_x = end_x;
00901     sink_y = end_y;
00902     source_y = 1;
00903     for(source_x = 1; source_x <= end_x; source_x++)
00904         {
00905             delta_x = abs(sink_x - source_x);
00906             delta_y = abs(sink_y - source_y);
00907 
00908             delta_clb_to_clb[delta_x][delta_y] =
00909                 assign_blocks_and_route_net(source_type, source_x, source_y,
00910                                             sink_type, sink_x, sink_y,
00911                                             router_opts, det_routing_arch,
00912                                             segment_inf, timing_inf);
00913         }
00914 }
00915 
00916 /**************************************/
00917 static void
00918 compute_delta_io_to_clb(struct s_router_opts router_opts,
00919                        struct s_det_routing_arch det_routing_arch,
00920                        t_segment_inf * segment_inf,
00921                        t_timing_inf timing_inf)
00922 {
00923     int source_x, source_y;
00924     int start_x, start_y, end_x, end_y;
00925     t_type_ptr source_type, sink_type;
00926 
00927     source_type = IO_TYPE;
00928     sink_type = FILL_TYPE;
00929 
00930     delta_io_to_clb[0][0] = IMPOSSIBLE;
00931     delta_io_to_clb[nx][ny] = IMPOSSIBLE;
00932 
00933     source_x = 0;
00934     source_y = 1;
00935 
00936     start_x = 1;
00937     end_x = nx;
00938     start_y = 1;
00939     end_y = ny;
00940     generic_compute_matrix(&delta_io_to_clb, source_type, sink_type,
00941                            source_x, source_y, start_x, end_x, start_y,
00942                            end_y, router_opts, det_routing_arch,
00943                            segment_inf, timing_inf);
00944 
00945     source_x = 1;
00946     source_y = 0;
00947 
00948     start_x = 1;
00949     end_x = 1;
00950     start_y = 1;
00951     end_y = ny;
00952     generic_compute_matrix(&delta_io_to_clb, source_type, sink_type,
00953                            source_x, source_y, start_x, end_x, start_y,
00954                            end_y, router_opts, det_routing_arch,
00955                            segment_inf, timing_inf);
00956 
00957     start_x = 1;
00958     end_x = nx;
00959     start_y = ny;
00960     end_y = ny;
00961     generic_compute_matrix(&delta_io_to_clb, source_type, sink_type,
00962                            source_x, source_y, start_x, end_x, start_y,
00963                            end_y, router_opts, det_routing_arch,
00964                            segment_inf, timing_inf);
00965 }
00966 
00967 /**************************************/
00968 static void
00969 compute_delta_clb_to_io(struct s_router_opts router_opts,
00970                        struct s_det_routing_arch det_routing_arch,
00971                        t_segment_inf * segment_inf,
00972                        t_timing_inf timing_inf)
00973 {
00974     int source_x, source_y, sink_x, sink_y;
00975     int delta_x, delta_y;
00976     t_type_ptr source_type, sink_type;
00977 
00978     source_type = FILL_TYPE;
00979     sink_type = IO_TYPE;
00980 
00981     delta_clb_to_io[0][0] = IMPOSSIBLE;
00982     delta_clb_to_io[nx][ny] = IMPOSSIBLE;
00983 
00984     sink_x = 0;
00985     sink_y = 1;
00986     for(source_x = 1; source_x <= nx; source_x++)
00987         {
00988             for(source_y = 1; source_y <= ny; source_y++)
00989                 {
00990                     delta_x = abs(source_x - sink_x);
00991                     delta_y = abs(source_y - sink_y);
00992 
00993                     delta_clb_to_io[delta_x][delta_y] =
00994                         assign_blocks_and_route_net(source_type, source_x,
00995                                                     source_y, sink_type,
00996                                                     sink_x, sink_y,
00997                                                     router_opts,
00998                                                     det_routing_arch,
00999                                                     segment_inf, timing_inf);
01000                 }
01001         }
01002 
01003     sink_x = 1;
01004     sink_y = 0;
01005     source_x = 1;
01006     delta_x = abs(source_x - sink_x);
01007     for(source_y = 1; source_y <= ny; source_y++)
01008         {
01009             delta_y = abs(source_y - sink_y);
01010             delta_clb_to_io[delta_x][delta_y] =
01011                 assign_blocks_and_route_net(source_type, source_x, source_y,
01012                                             sink_type, sink_x, sink_y,
01013                                             router_opts, det_routing_arch,
01014                                             segment_inf, timing_inf);
01015         }
01016 
01017     sink_x = 1;
01018     sink_y = 0;
01019     source_y = ny;
01020     delta_y = abs(source_y - sink_y);
01021     for(source_x = 2; source_x <= nx; source_x++)
01022         {
01023             delta_x = abs(source_x - sink_x);
01024             delta_clb_to_io[delta_x][delta_y] =
01025                 assign_blocks_and_route_net(source_type, source_x, source_y,
01026                                             sink_type, sink_x, sink_y,
01027                                             router_opts, det_routing_arch,
01028                                             segment_inf, timing_inf);
01029         }
01030 }
01031 
01032 /**************************************/
01033 static void
01034 compute_delta_io_to_io(struct s_router_opts router_opts,
01035                        struct s_det_routing_arch det_routing_arch,
01036                        t_segment_inf * segment_inf,
01037                        t_timing_inf timing_inf)
01038 {
01039     int source_x, source_y, sink_x, sink_y;
01040     int delta_x, delta_y;
01041     t_type_ptr source_type, sink_type;
01042 
01043     source_type = IO_TYPE;
01044     sink_type = IO_TYPE;
01045 
01046     delta_io_to_io[0][0] = 0;   /*delay to itself is 0 (this can happen) */
01047     delta_io_to_io[nx + 1][ny + 1] = IMPOSSIBLE;
01048     delta_io_to_io[0][ny] = IMPOSSIBLE;
01049     delta_io_to_io[nx][0] = IMPOSSIBLE;
01050     delta_io_to_io[nx][ny + 1] = IMPOSSIBLE;
01051     delta_io_to_io[nx + 1][ny] = IMPOSSIBLE;
01052 
01053 
01054     source_x = 0;
01055     source_y = 1;
01056     sink_x = 0;
01057     delta_x = abs(sink_x - source_x);
01058 
01059 
01060     for(sink_y = 2; sink_y <= ny; sink_y++)
01061         {
01062             delta_y = abs(sink_y - source_y);
01063             delta_io_to_io[delta_x][delta_y] =
01064                 assign_blocks_and_route_net(source_type, source_x, source_y,
01065                                             sink_type, sink_x, sink_y,
01066                                             router_opts, det_routing_arch,
01067                                             segment_inf, timing_inf);
01068 
01069         }
01070 
01071     source_x = 0;
01072     source_y = 1;
01073     sink_x = nx + 1;
01074     delta_x = abs(sink_x - source_x);
01075 
01076     for(sink_y = 1; sink_y <= ny; sink_y++)
01077         {
01078             delta_y = abs(sink_y - source_y);
01079             delta_io_to_io[delta_x][delta_y] =
01080                 assign_blocks_and_route_net(source_type, source_x, source_y,
01081                                             sink_type, sink_x, sink_y,
01082                                             router_opts, det_routing_arch,
01083                                             segment_inf, timing_inf);
01084 
01085         }
01086 
01087 
01088     source_x = 1;
01089     source_y = 0;
01090     sink_y = 0;
01091     delta_y = abs(sink_y - source_y);
01092 
01093     for(sink_x = 2; sink_x <= nx; sink_x++)
01094         {
01095             delta_x = abs(sink_x - source_x);
01096             delta_io_to_io[delta_x][delta_y] =
01097                 assign_blocks_and_route_net(source_type, source_x, source_y,
01098                                             sink_type, sink_x, sink_y,
01099                                             router_opts, det_routing_arch,
01100                                             segment_inf, timing_inf);
01101 
01102         }
01103 
01104     source_x = 1;
01105     source_y = 0;
01106     sink_y = ny + 1;
01107     delta_y = abs(sink_y - source_y);
01108 
01109     for(sink_x = 1; sink_x <= nx; sink_x++)
01110         {
01111             delta_x = abs(sink_x - source_x);
01112             delta_io_to_io[delta_x][delta_y] =
01113                 assign_blocks_and_route_net(source_type, source_x, source_y,
01114                                             sink_type, sink_x, sink_y,
01115                                             router_opts, det_routing_arch,
01116                                             segment_inf, timing_inf);
01117 
01118         }
01119 
01120     source_x = 0;
01121     sink_y = ny + 1;
01122     for(source_y = 1; source_y <= ny; source_y++)
01123         {
01124             for(sink_x = 1; sink_x <= nx; sink_x++)
01125                 {
01126                     delta_y = abs(source_y - sink_y);
01127                     delta_x = abs(source_x - sink_x);
01128                     delta_io_to_io[delta_x][delta_y] =
01129                         assign_blocks_and_route_net(source_type, source_x,
01130                                                     source_y, sink_type,
01131                                                     sink_x, sink_y,
01132                                                     router_opts,
01133                                                     det_routing_arch,
01134                                                     segment_inf, timing_inf);
01135 
01136                 }
01137         }
01138 }
01139 
01140 /**************************************/
01141 #ifdef PRINT_ARRAYS
01142 static void
01143 print_array(float **array_to_print,
01144             int x1,
01145             int x2,
01146             int y1,
01147             int y2)
01148 {
01149 
01150 
01151     int idx_x, idx_y;
01152 
01153     fprintf(lookup_dump, "\nPrinting Array \n\n");
01154 
01155     for(idx_y = y2; idx_y >= y1; idx_y--)
01156         {
01157             for(idx_x = x1; idx_x <= x2; idx_x++)
01158                 {
01159                     fprintf(lookup_dump, " %9.2e",
01160                             array_to_print[idx_x][idx_y]);
01161                 }
01162             fprintf(lookup_dump, "\n");
01163         }
01164     fprintf(lookup_dump, "\n\n");
01165 }
01166 #endif
01167 /**************************************/
01168 static void
01169 compute_delta_arrays(struct s_router_opts router_opts,
01170                      struct s_det_routing_arch det_routing_arch,
01171                      t_segment_inf * segment_inf,
01172                      t_timing_inf timing_inf,
01173                      int longest_length)
01174 {
01175 
01176     printf
01177         ("Computing delta_io_to_io lookup matrix, may take a few seconds, please wait...\n");
01178     compute_delta_io_to_io(router_opts, det_routing_arch, segment_inf,
01179                            timing_inf);
01180     printf
01181         ("Computing delta_io_to_clb lookup matrix, may take a few seconds, please wait...\n");
01182     compute_delta_io_to_clb(router_opts, det_routing_arch, segment_inf,
01183                            timing_inf);
01184     printf
01185         ("Computing delta_clb_to_io lookup matrix, may take a few seconds, please wait...\n");
01186     compute_delta_clb_to_io(router_opts, det_routing_arch, segment_inf,
01187                            timing_inf);
01188     printf
01189         ("Computing delta_clb_to_clb lookup matrix, may take a few seconds, please wait...\n");
01190     compute_delta_clb_to_clb(router_opts, det_routing_arch, segment_inf,
01191                            timing_inf, longest_length);
01192 
01193 #ifdef PRINT_ARRAYS
01194     lookup_dump = my_fopen(DUMPFILE, "w", 0);
01195     fprintf(lookup_dump, "\n\nprinting delta_clb_to_clb\n");
01196     print_array(delta_clb_to_clb, 0, nx - 1, 0, ny - 1);
01197     fprintf(lookup_dump, "\n\nprinting delta_io_to_clb\n");
01198     print_array(delta_io_to_clb, 0, nx, 0, ny);
01199     fprintf(lookup_dump, "\n\nprinting delta_clb_to_io\n");
01200     print_array(delta_clb_to_io, 0, nx, 0, ny);
01201     fprintf(lookup_dump, "\n\nprinting delta_io_to_io\n");
01202     print_array(delta_io_to_io, 0, nx + 1, 0, ny + 1);
01203     fclose(lookup_dump);
01204 #endif
01205 
01206 }
01207 
01208 /******* Globally Accessable Functions **********/
01209 
01210 /**************************************/
01211 void
01212 compute_delay_lookup_tables(struct s_router_opts router_opts,
01213                             struct s_det_routing_arch det_routing_arch,
01214                             t_segment_inf * segment_inf,
01215                             t_timing_inf timing_inf,
01216                             t_chan_width_dist chan_width_dist)
01217 {
01218 
01219     static struct s_net *original_net;  /*this will be used as a pointer to remember what */
01220 
01221     /*the "real" nets in the circuit are. This is    */
01222     /*required because we are using the net structure */
01223     /*in these routines to find delays between blocks */
01224     static struct s_block *original_block;      /*same def as original_nets, but for block  */
01225 
01226     static int original_num_nets;
01227     static int original_num_blocks;
01228     static int longest_length;
01229 
01230     load_simplified_device();
01231 
01232     alloc_and_assign_internal_structures(&original_net,
01233                                          &original_block,
01234                                          &original_num_nets,
01235                                          &original_num_blocks);
01236     setup_chan_width(router_opts, chan_width_dist);
01237 
01238     alloc_routing_structs(router_opts, det_routing_arch, segment_inf,
01239                           timing_inf);
01240 
01241     longest_length =
01242         get_longest_segment_length(det_routing_arch, segment_inf);
01243 
01244 
01245     /*now setup and compute the actual arrays */
01246     alloc_delta_arrays();
01247     compute_delta_arrays(router_opts, det_routing_arch, segment_inf,
01248                          timing_inf, longest_length);
01249 
01250     /*free all data structures that are no longer needed */
01251     free_routing_structs(router_opts, det_routing_arch, segment_inf,
01252                          timing_inf);
01253 
01254     restore_original_device();
01255 
01256     free_and_reset_internal_structures(original_net, original_block,
01257                                        original_num_nets,
01258                                        original_num_blocks);
01259 }
01260 
01261 /**************************************/
01262 void
01263 free_place_lookup_structs(void)
01264 {
01265 
01266     free_delta_arrays();
01267 
01268 }