VPR-7.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
timing_place_lookup.c
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <math.h>
3 #include <string.h>
4 #include "util.h"
5 #include "vpr_types.h"
6 #include "globals.h"
7 #include "route_common.h"
8 #include "place_and_route.h"
9 #include "route_tree_timing.h"
10 #include "route_timing.h"
11 #include "timing_place_lookup.h"
12 #include "rr_graph.h"
13 #include "route_export.h"
14 #include <assert.h>
15 #include "read_xml_arch_file.h"
16 
17 /*this file contains routines that generate the array containing*/
18 /*the delays between blocks, this is used in the timing driven */
19 /*placement routines */
20 
21 /*To compute delay between blocks we place temporary blocks at */
22 /*different locations in the FPGA and route nets between */
23 /*the blocks. From this procedure we generate a lookup table */
24 /*which tells us the delay between different locations in */
25 /*the FPGA */
26 
27 /*Note: these routines assume that there is a uniform and even */
28 /*distribution of the different wire segments. If this is not */
29 /*the case, then this lookup table will be off */
30 
31 /*Note: This code removes all heterogeneous types and creates an
32  artificial 1x1 tile. A good lookup for heterogeniety
33  requires more research */
34 
35 #define NET_COUNT 1 /*we only use one net in these routines, */
36 /*it is repeatedly routed and ripped up */
37 /*to compute delays between different */
38 /*locations, this value should not change */
39 #define NET_USED 0 /*we use net at location zero of the net */
40 /*structure */
41 #define NET_USED_SOURCE_BLOCK 0 /*net.block[0] is source block */
42 #define NET_USED_SINK_BLOCK 1 /*net.block[1] is sink block */
43 #define SOURCE_BLOCK 0 /*block[0] is source */
44 #define SINK_BLOCK 1 /*block[1] is sink */
45 
46 #define BLOCK_COUNT 2 /*use 2 blocks to compute delay between */
47 /*the various FPGA locations */
48 /*do not change this number unless you */
49 /*really know what you are doing, it is */
50 /*assumed that the net only connects to */
51 /*two blocks */
52 
53 #define NUM_TYPES_USED 3 /* number of types used in look up */
54 
55 #define DEBUG_TIMING_PLACE_LOOKUP /*initialize arrays to known state */
56 
57 #define DUMPFILE "lookup_dump.echo"
58 /* #define PRINT_ARRAYS *//*only used during debugging, calls routine to */
59 /*print out the various lookup arrays */
60 
61 /***variables that are exported to other modules***/
62 
63 /*the delta arrays are used to contain the best case routing delay */
64 /*between different locations on the FPGA. */
65 
70 
71 /*** Other Global Arrays ******/
72 /* I could have allocated these as local variables, and passed them all */
73 /* around, but was too lazy, since this is a small file, it should not */
74 /* be a big problem */
75 
76 static float **net_delay;
77 static float *pin_criticality;
78 static int *sink_order;
85 static struct s_grid_tile **grid_backup;
86 static int num_types_backup;
87 
89 
90 #ifdef PRINT_ARRAYS
91 static FILE *lookup_dump; /* If debugging mode is on, print out to
92  * the file defined in DUMPFILE */
93 #endif /* PRINT_ARRAYS */
94 
95 /*** Function Prototypes *****/
96 
97 static void alloc_net(void);
98 
99 static void alloc_block(void);
100 
101 static void load_simplified_device(void);
102 static void restore_original_device(void);
103 
104 static void alloc_and_assign_internal_structures(struct s_net **original_net,
105  struct s_block **original_block, int *original_num_nets,
106  int *original_num_blocks);
107 
108 static void free_and_reset_internal_structures(struct s_net *original_net,
109  struct s_block *original_block, int original_num_nets,
110  int original_num_blocks);
111 
112 static void setup_chan_width(struct s_router_opts router_opts,
113  t_chan_width_dist chan_width_dist);
114 
115 static void alloc_routing_structs(struct s_router_opts router_opts,
116  struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
117  t_timing_inf timing_inf, INP t_direct_inf *directs,
118  INP int num_directs);
119 
120 static void free_routing_structs(struct s_router_opts router_opts,
121  struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
122  t_timing_inf timing_inf);
123 
124 static void assign_locations(t_type_ptr source_type, int source_x_loc,
125  int source_y_loc, int source_z_loc, t_type_ptr sink_type,
126  int sink_x_loc, int sink_y_loc, int sink_z_loc);
127 
128 static float assign_blocks_and_route_net(t_type_ptr source_type,
129  int source_x_loc, int source_y_loc, t_type_ptr sink_type,
130  int sink_x_loc, int sink_y_loc, struct s_router_opts router_opts,
131  struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
132  t_timing_inf timing_inf);
133 
134 static void alloc_delta_arrays(void);
135 
136 static void free_delta_arrays(void);
137 
138 static void generic_compute_matrix(float ***matrix_ptr, t_type_ptr source_type,
139  t_type_ptr sink_type, int source_x, int source_y, int start_x,
140  int end_x, int start_y, int end_y, struct s_router_opts router_opts,
141  struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
142  t_timing_inf timing_inf);
143 
144 static void compute_delta_clb_to_clb(struct s_router_opts router_opts,
145  struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
146  t_timing_inf timing_inf, int longest_length);
147 
148 static void compute_delta_io_to_clb(struct s_router_opts router_opts,
149  struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
150  t_timing_inf timing_inf);
151 
152 static void compute_delta_clb_to_io(struct s_router_opts router_opts,
153  struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
154  t_timing_inf timing_inf);
155 
156 static void compute_delta_io_to_io(struct s_router_opts router_opts,
157  struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
158  t_timing_inf timing_inf);
159 
160 static void compute_delta_arrays(struct s_router_opts router_opts,
161  struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
162  t_timing_inf timing_inf, int longest_length);
163 
164 static int get_first_pin(enum e_pin_type pintype, t_type_ptr type);
165 
166 static int get_longest_segment_length(
167  struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf);
168 static void reset_placement(void);
169 
170 #ifdef PRINT_ARRAYS
171 static void print_array(float **array_to_print,
172  int x1,
173  int x2,
174  int y1,
175  int y2);
176 #endif
177 /**************************************/
178 static int get_first_pin(enum e_pin_type pintype, t_type_ptr type) {
179 
180  /*this code assumes logical equivilance between all driving pins */
181  /*global pins are not hooked up to the temporary net */
182 
183  int i, currpin;
184 
185  currpin = 0;
186  for (i = 0; i < type->num_class; i++) {
187  if (type->class_inf[i].type == pintype && !type->is_global_pin[currpin])
188  return (type->class_inf[i].pinlist[0]);
189  else
190  currpin += type->class_inf[i].num_pins;
191  }
192  assert(0);
193  exit(0); /*should never hit this line */
194 }
195 
196 /**************************************/
198  struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf) {
199 
200  int i, length;
201 
202  length = 0;
203  for (i = 0; i < det_routing_arch.num_segment; i++) {
204  if (segment_inf[i].length > length)
205  length = segment_inf[i].length;
206  }
207  return (length);
208 }
209 
210 /**************************************/
211 static void alloc_net(void) {
212 
213  int i, len;
214 
215  clb_net = (struct s_net *) my_malloc(num_nets * sizeof(struct s_net));
216  for (i = 0; i < NET_COUNT; i++) {
217  /* FIXME: We *really* shouldn't be allocating write-once copies */
218  len = strlen("TEMP_NET");
219  clb_net[i].name = (char *) my_malloc((len + 1) * sizeof(char));
220  clb_net[i].is_global = FALSE;
221  strcpy(clb_net[NET_USED].name, "TEMP_NET");
222 
223  clb_net[i].num_sinks = (BLOCK_COUNT - 1);
224  clb_net[i].node_block = (int *) my_malloc(BLOCK_COUNT * sizeof(int));
227 
228  clb_net[i].node_block_pin = (int *) my_malloc(
229  BLOCK_COUNT * sizeof(int));
230  /*the values for this are allocated in assign_blocks_and_route_net */
231 
232  }
233 }
234 
235 /**************************************/
236 static void alloc_block(void) {
237 
238  /*allocates block structure, and assigns values to known parameters */
239  /*type and x,y fields are left undefined at this stage since they */
240  /*are not known until we start moving blocks through the clb array */
241 
242  int ix_b, ix_p, len, i;
243  int max_pins;
244 
245  max_pins = 0;
246  for (i = 0; i < NUM_TYPES_USED; i++) {
247  max_pins = std::max(max_pins, type_descriptors[i].num_pins);
248  }
249 
250  block = (struct s_block *) my_malloc(num_blocks * sizeof(struct s_block));
251 
252  for (ix_b = 0; ix_b < BLOCK_COUNT; ix_b++) {
253  len = strlen("TEMP_BLOCK");
254  block[ix_b].name = (char *) my_malloc((len + 1) * sizeof(char));
255  strcpy(block[ix_b].name, "TEMP_BLOCK");
256 
257  block[ix_b].nets = (int *) my_malloc(max_pins * sizeof(int));
258  block[ix_b].nets[0] = 0;
259  for (ix_p = 1; ix_p < max_pins; ix_p++)
260  block[ix_b].nets[ix_p] = OPEN;
261  }
262 }
263 
264 /**************************************/
265 static void load_simplified_device(void) {
266  int i, j;
267 
268  /* Backup original globals */
269  EMPTY_TYPE_BACKUP = EMPTY_TYPE;
270  IO_TYPE_BACKUP = IO_TYPE;
271  FILL_TYPE_BACKUP = FILL_TYPE;
272  type_descriptors_backup = type_descriptors;
275 
276  /* Fill in homogeneous core type info */
277  dummy_type_descriptors[0] = *EMPTY_TYPE;
278  dummy_type_descriptors[0].index = 0;
279  dummy_type_descriptors[1] = *IO_TYPE;
280  dummy_type_descriptors[1].index = 1;
281  dummy_type_descriptors[2] = *FILL_TYPE;
282  dummy_type_descriptors[2].index = 2;
284  EMPTY_TYPE = &dummy_type_descriptors[0];
285  IO_TYPE = &dummy_type_descriptors[1];
286  FILL_TYPE = &dummy_type_descriptors[2];
287 
288  /* Fill in homogeneous core grid info */
289  grid_backup = grid;
290  grid = (struct s_grid_tile **) alloc_matrix(0, nx + 1, 0, ny + 1,
291  sizeof(struct s_grid_tile));
292  for (i = 0; i < nx + 2; i++) {
293  for (j = 0; j < ny + 2; j++) {
294  if ((i == 0 && j == 0) || (i == nx + 1 && j == 0)
295  || (i == 0 && j == ny + 1)
296  || (i == nx + 1 && j == ny + 1)) {
297  grid[i][j].type = EMPTY_TYPE;
298  } else if (i == 0 || i == nx + 1 || j == 0 || j == ny + 1) {
299  grid[i][j].type = IO_TYPE;
300  } else {
301  grid[i][j].type = FILL_TYPE;
302  }
303  grid[i][j].blocks = (int*)my_malloc(
304  grid[i][j].type->capacity * sizeof(int));
305  grid[i][j].offset = 0;
306  }
307  }
308 }
309 static void restore_original_device(void) {
310  int i, j;
311 
312  /* restore previous globals */
318 
319  /* free allocatd data */
320  for (i = 0; i < nx + 2; i++) {
321  for (j = 0; j < ny + 2; j++) {
322  free(grid[i][j].blocks);
323  }
324  }
325  free_matrix(grid, 0, nx + 1, 0, sizeof(struct s_grid_tile));
326  grid = grid_backup;
327 }
328 
329 /**************************************/
330 static void reset_placement(void) {
331  int i, j, k;
332 
333  for (i = 0; i <= nx + 1; i++) {
334  for (j = 0; j <= ny + 1; j++) {
335  grid[i][j].usage = 0;
336  for (k = 0; k < grid[i][j].type->capacity; k++) {
337  grid[i][j].blocks[k] = EMPTY;
338  }
339  }
340  }
341 }
342 
343 /**************************************/
344 static void alloc_and_assign_internal_structures(struct s_net **original_net,
345  struct s_block **original_block, int *original_num_nets,
346  int *original_num_blocks) {
347  /*allocate new data structures to hold net, and block info */
348 
349  *original_net = clb_net;
350  *original_num_nets = num_nets;
352  alloc_net();
353 
354  *original_block = block;
355  *original_num_blocks = num_blocks;
357  alloc_block();
358 
359  /* [0..num_nets-1][1..num_pins-1] */
360  net_delay = (float **) alloc_matrix(0, NET_COUNT - 1, 1, BLOCK_COUNT - 1,
361  sizeof(float));
362 
363  reset_placement();
364 }
365 
366 /**************************************/
367 static void free_and_reset_internal_structures(struct s_net *original_net,
368  struct s_block *original_block, int original_num_nets,
369  int original_num_blocks) {
370  /*reset gloabal data structures to the state that they were in before these */
371  /*lookup computation routines were called */
372 
373  int i;
374 
375  /*there should be only one net to free, but this is safer */
376  for (i = 0; i < NET_COUNT; i++) {
377  free(clb_net[i].name);
378  free(clb_net[i].node_block);
379  free(clb_net[i].node_block_pin);
380  }
381  free(clb_net);
382  clb_net = original_net;
383 
384  for (i = 0; i < BLOCK_COUNT; i++) {
385  free(block[i].name);
386  free(block[i].nets);
387  }
388  free(block);
389  block = original_block;
390 
391  num_nets = original_num_nets;
392  num_blocks = original_num_blocks;
393 
394  free_matrix(net_delay, 0, NET_COUNT - 1, 1, sizeof(float));
395 
396 }
397 
398 /**************************************/
399 static void setup_chan_width(struct s_router_opts router_opts,
400  t_chan_width_dist chan_width_dist) {
401  /*we give plenty of tracks, this increases routability for the */
402  /*lookup table generation */
403 
404  int width_fac, i, max_pins_per_clb;
405 
406  max_pins_per_clb = 0;
407  for (i = 0; i < num_types; i++) {
408  max_pins_per_clb = std::max(max_pins_per_clb, type_descriptors[i].num_pins);
409  }
410 
411  if (router_opts.fixed_channel_width == NO_FIXED_CHANNEL_WIDTH)
412  width_fac = 4 * max_pins_per_clb; /*this is 2x the value that binary search starts */
413  /*this should be enough to allow most pins to */
414  /*connect to tracks in the architecture */
415  else
416  width_fac = router_opts.fixed_channel_width;
417 
418  init_chan(width_fac, chan_width_dist);
419 }
420 
421 /**************************************/
422 static void alloc_routing_structs(struct s_router_opts router_opts,
423  struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
424  t_timing_inf timing_inf, INP t_direct_inf *directs,
425  INP int num_directs) {
426 
427  int bb_factor;
428  int warnings;
429  t_graph_type graph_type;
430 
431  /*calls routines that set up routing resource graph and associated structures */
432 
433  /*must set up dummy blocks for the first pass through to setup locally used opins */
434  /* Only one block per tile */
435  assign_locations(FILL_TYPE, 1, 1, 0, FILL_TYPE, nx, ny, 0);
436 
437  clb_opins_used_locally = alloc_route_structs();
438 
439  free_rr_graph();
440 
441  if (router_opts.route_type == GLOBAL) {
442  graph_type = GRAPH_GLOBAL;
443  } else {
444  graph_type = (
445  det_routing_arch.directionality == BI_DIRECTIONAL ?
447  }
448 
449  build_rr_graph(graph_type, num_types, dummy_type_descriptors, nx, ny, grid,
450  chan_width_x[0], NULL, det_routing_arch.switch_block_type,
451  det_routing_arch.Fs, det_routing_arch.num_segment,
452  det_routing_arch.num_switch, segment_inf,
453  det_routing_arch.global_route_switch,
454  det_routing_arch.delayless_switch, timing_inf,
455  det_routing_arch.wire_to_ipin_switch, router_opts.base_cost_type,
456  NULL, 0, TRUE, /* do not send in direct connections because we care about general placement timing instead of special pin placement timing */
457  &warnings);
458 
460 
462  &rt_node_of_sink);
463 
464  bb_factor = nx + ny; /*set it to a huge value */
465  init_route_structs(bb_factor);
466 }
467 
468 /**************************************/
469 static void free_routing_structs(struct s_router_opts router_opts,
470  struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
471  t_timing_inf timing_inf) {
472  int i;
473  free_rr_graph();
474 
478 
480  rt_node_of_sink);
481 
482  if (clb_opins_used_locally != NULL) {
483  for (i = 0; i < num_blocks; i++) {
484  free_ivec_vector(clb_opins_used_locally[i], 0,
485  block[i].type->num_class - 1);
486  }
487  free(clb_opins_used_locally);
488  clb_opins_used_locally = NULL;
489  }
490 }
491 
492 /**************************************/
493 static void assign_locations(t_type_ptr source_type, int source_x_loc,
494  int source_y_loc, int source_z_loc, t_type_ptr sink_type,
495  int sink_x_loc, int sink_y_loc, int sink_z_loc) {
496  /*all routing occurs between block 0 (source) and block 1 (sink) */
497  block[SOURCE_BLOCK].type = source_type;
498  block[SOURCE_BLOCK].x = source_x_loc;
499  block[SOURCE_BLOCK].y = source_y_loc;
500  block[SOURCE_BLOCK].z = source_z_loc;
501 
502  block[SINK_BLOCK].type = sink_type;
503  block[SINK_BLOCK].x = sink_x_loc;
504  block[SINK_BLOCK].y = sink_y_loc;
505  block[SINK_BLOCK].z = sink_z_loc;
506 
507  grid[source_x_loc][source_y_loc].blocks[source_z_loc] = SOURCE_BLOCK;
508  grid[sink_x_loc][sink_y_loc].blocks[sink_z_loc] = SINK_BLOCK;
509 
513  RECEIVER, block[SINK_BLOCK].type);
514 
515  grid[source_x_loc][source_y_loc].usage += 1;
516  grid[sink_x_loc][sink_y_loc].usage += 1;
517 
518 }
519 
520 /**************************************/
521 static float assign_blocks_and_route_net(t_type_ptr source_type,
522  int source_x_loc, int source_y_loc, t_type_ptr sink_type,
523  int sink_x_loc, int sink_y_loc, struct s_router_opts router_opts,
524  struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
525  t_timing_inf timing_inf) {
526  /*places blocks at the specified locations, and routes a net between them */
527  /*returns the delay of this net */
528 
529  float pres_fac, net_delay_value;
530 
531  int source_z_loc, sink_z_loc;
532 
533  /* Only one block per tile */
534  source_z_loc = 0;
535  sink_z_loc = 0;
536 
537  net_delay_value = IMPOSSIBLE; /*set to known value for debug purposes */
538 
539  assign_locations(source_type, source_x_loc, source_y_loc, source_z_loc,
540  sink_type, sink_x_loc, sink_y_loc, sink_z_loc);
541 
543 
544  pres_fac = 0; /* ignore congestion */
545 
546  /* Route this net with a dummy criticality of 0 by calling
547  timing_driven_route_net with slacks set to NULL. */
549  router_opts.max_criticality, router_opts.criticality_exp,
550  router_opts.astar_fac, router_opts.bend_cost,
551  pin_criticality, sink_order, rt_node_of_sink,
552  net_delay[NET_USED], NULL);
553 
554  net_delay_value = net_delay[NET_USED][NET_USED_SINK_BLOCK];
555 
556  grid[source_x_loc][source_y_loc].usage = 0;
557  grid[source_x_loc][source_y_loc].blocks[source_z_loc] = EMPTY;
558  grid[sink_x_loc][sink_y_loc].usage = 0;
559  grid[sink_x_loc][sink_y_loc].blocks[sink_z_loc] = EMPTY;
560 
561  return (net_delay_value);
562 }
563 
564 /**************************************/
565 static void alloc_delta_arrays(void) {
566  int id_x, id_y;
567 
568  delta_clb_to_clb = (float **) alloc_matrix(0, nx - 1, 0, ny - 1,
569  sizeof(float));
570  delta_io_to_clb = (float **) alloc_matrix(0, nx, 0, ny, sizeof(float));
571  delta_clb_to_io = (float **) alloc_matrix(0, nx, 0, ny, sizeof(float));
572  delta_io_to_io = (float **) alloc_matrix(0, nx + 1, 0, ny + 1,
573  sizeof(float));
574 
575  /*initialize all of the array locations to -1 */
576 
577  for (id_x = 0; id_x <= nx; id_x++) {
578  for (id_y = 0; id_y <= ny; id_y++) {
579  delta_io_to_clb[id_x][id_y] = IMPOSSIBLE;
580  }
581  }
582  for (id_x = 0; id_x <= nx - 1; id_x++) {
583  for (id_y = 0; id_y <= ny - 1; id_y++) {
584  delta_clb_to_clb[id_x][id_y] = IMPOSSIBLE;
585  }
586  }
587  for (id_x = 0; id_x <= nx; id_x++) {
588  for (id_y = 0; id_y <= ny; id_y++) {
589  delta_clb_to_io[id_x][id_y] = IMPOSSIBLE;
590  }
591  }
592  for (id_x = 0; id_x <= nx + 1; id_x++) {
593  for (id_y = 0; id_y <= ny + 1; id_y++) {
594  delta_io_to_io[id_x][id_y] = IMPOSSIBLE;
595  }
596  }
597 }
598 
599 /**************************************/
600 static void free_delta_arrays(void) {
601 
602  free_matrix(delta_io_to_clb, 0, nx, 0, sizeof(float));
603  free_matrix(delta_clb_to_clb, 0, nx - 1, 0, sizeof(float));
604  free_matrix(delta_clb_to_io, 0, nx, 0, sizeof(float));
605  free_matrix(delta_io_to_io, 0, nx + 1, 0, sizeof(float));
606 
607 }
608 
609 /**************************************/
610 static void generic_compute_matrix(float ***matrix_ptr, t_type_ptr source_type,
611  t_type_ptr sink_type, int source_x, int source_y, int start_x,
612  int end_x, int start_y, int end_y, struct s_router_opts router_opts,
613  struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
614  t_timing_inf timing_inf) {
615 
616  int delta_x, delta_y;
617  int sink_x, sink_y;
618 
619  for (sink_x = start_x; sink_x <= end_x; sink_x++) {
620  for (sink_y = start_y; sink_y <= end_y; sink_y++) {
621  delta_x = abs(sink_x - source_x);
622  delta_y = abs(sink_y - source_y);
623 
624  if (delta_x == 0 && delta_y == 0)
625  continue; /*do not compute distance from a block to itself */
626  /*if a value is desired, pre-assign it somewhere else */
627 
628  (*matrix_ptr)[delta_x][delta_y] = assign_blocks_and_route_net(
629  source_type, source_x, source_y, sink_type, sink_x, sink_y,
630  router_opts, det_routing_arch, segment_inf, timing_inf);
631  }
632  }
633 }
634 
635 /**************************************/
636 static void compute_delta_clb_to_clb(struct s_router_opts router_opts,
637  struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
638  t_timing_inf timing_inf, int longest_length) {
639 
640  /*this routine must compute delay values in a slightly different way than the */
641  /*other compute routines. We cannot use a location close to the edge as the */
642  /*source location for the majority of the delay computations because this */
643  /*would give gradually increasing delay values. To avoid this from happening */
644  /*a clb that is at least longest_length away from an edge should be chosen */
645  /*as a source , if longest_length is more than 0.5 of the total size then */
646  /*choose a CLB at the center as the source CLB */
647 
648  int source_x, source_y, sink_x, sink_y;
649  int start_x, start_y, end_x, end_y;
650  int delta_x, delta_y;
651  t_type_ptr source_type, sink_type;
652 
653  source_type = FILL_TYPE;
654  sink_type = FILL_TYPE;
655 
656  if (longest_length < 0.5 * (nx)) {
657  start_x = longest_length;
658  } else {
659  start_x = (int) (0.5 * nx);
660  }
661  end_x = nx;
662  source_x = start_x;
663 
664  if (longest_length < 0.5 * (ny)) {
665  start_y = longest_length;
666  } else {
667  start_y = (int) (0.5 * ny);
668  }
669  end_y = ny;
670  source_y = start_y;
671 
672  /*don't put the sink all the way to the corner, until it is necessary */
673  for (sink_x = start_x; sink_x <= end_x - 1; sink_x++) {
674  for (sink_y = start_y; sink_y <= end_y - 1; sink_y++) {
675  delta_x = abs(sink_x - source_x);
676  delta_y = abs(sink_y - source_y);
677 
678  if (delta_x == 0 && delta_y == 0) {
679  delta_clb_to_clb[delta_x][delta_y] = 0.0;
680  continue;
681  }
682  delta_clb_to_clb[delta_x][delta_y] = assign_blocks_and_route_net(
683  source_type, source_x, source_y, sink_type, sink_x, sink_y,
684  router_opts, det_routing_arch, segment_inf, timing_inf);
685  }
686 
687  }
688 
689  sink_x = end_x - 1;
690  sink_y = end_y - 1;
691 
692  for (source_x = start_x - 1; source_x >= 1; source_x--) {
693  for (source_y = start_y; source_y <= end_y - 1; source_y++) {
694  delta_x = abs(sink_x - source_x);
695  delta_y = abs(sink_y - source_y);
696 
697  delta_clb_to_clb[delta_x][delta_y] = assign_blocks_and_route_net(
698  source_type, source_x, source_y, sink_type, sink_x, sink_y,
699  router_opts, det_routing_arch, segment_inf, timing_inf);
700  }
701  }
702 
703  for (source_x = 1; source_x <= end_x - 1; source_x++) {
704  for (source_y = 1; source_y < start_y; source_y++) {
705  delta_x = abs(sink_x - source_x);
706  delta_y = abs(sink_y - source_y);
707 
708  delta_clb_to_clb[delta_x][delta_y] = assign_blocks_and_route_net(
709  source_type, source_x, source_y, sink_type, sink_x, sink_y,
710  router_opts, det_routing_arch, segment_inf, timing_inf);
711  }
712  }
713 
714  /*now move sink into the top right corner */
715  sink_x = end_x;
716  sink_y = end_y;
717  source_x = 1;
718  for (source_y = 1; source_y <= end_y; source_y++) {
719  delta_x = abs(sink_x - source_x);
720  delta_y = abs(sink_y - source_y);
721 
722  delta_clb_to_clb[delta_x][delta_y] = assign_blocks_and_route_net(
723  source_type, source_x, source_y, sink_type, sink_x, sink_y,
724  router_opts, det_routing_arch, segment_inf, timing_inf);
725 
726  }
727 
728  sink_x = end_x;
729  sink_y = end_y;
730  source_y = 1;
731  for (source_x = 1; source_x <= end_x; source_x++) {
732  delta_x = abs(sink_x - source_x);
733  delta_y = abs(sink_y - source_y);
734 
735  delta_clb_to_clb[delta_x][delta_y] = assign_blocks_and_route_net(
736  source_type, source_x, source_y, sink_type, sink_x, sink_y,
737  router_opts, det_routing_arch, segment_inf, timing_inf);
738  }
739 }
740 
741 /**************************************/
742 static void compute_delta_io_to_clb(struct s_router_opts router_opts,
743  struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
744  t_timing_inf timing_inf) {
745  int source_x, source_y;
746  int start_x, start_y, end_x, end_y;
747  t_type_ptr source_type, sink_type;
748 
749  source_type = IO_TYPE;
750  sink_type = FILL_TYPE;
751 
752  delta_io_to_clb[0][0] = IMPOSSIBLE;
754 
755  source_x = 0;
756  source_y = 1;
757 
758  start_x = 1;
759  end_x = nx;
760  start_y = 1;
761  end_y = ny;
762  generic_compute_matrix(&delta_io_to_clb, source_type, sink_type, source_x,
763  source_y, start_x, end_x, start_y, end_y, router_opts,
764  det_routing_arch, segment_inf, timing_inf);
765 
766  source_x = 1;
767  source_y = 0;
768 
769  start_x = 1;
770  end_x = 1;
771  start_y = 1;
772  end_y = ny;
773  generic_compute_matrix(&delta_io_to_clb, source_type, sink_type, source_x,
774  source_y, start_x, end_x, start_y, end_y, router_opts,
775  det_routing_arch, segment_inf, timing_inf);
776 
777  start_x = 1;
778  end_x = nx;
779  start_y = ny;
780  end_y = ny;
781  generic_compute_matrix(&delta_io_to_clb, source_type, sink_type, source_x,
782  source_y, start_x, end_x, start_y, end_y, router_opts,
783  det_routing_arch, segment_inf, timing_inf);
784 }
785 
786 /**************************************/
787 static void compute_delta_clb_to_io(struct s_router_opts router_opts,
788  struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
789  t_timing_inf timing_inf) {
790  int source_x, source_y, sink_x, sink_y;
791  int delta_x, delta_y;
792  t_type_ptr source_type, sink_type;
793 
794  source_type = FILL_TYPE;
795  sink_type = IO_TYPE;
796 
797  delta_clb_to_io[0][0] = IMPOSSIBLE;
799 
800  sink_x = 0;
801  sink_y = 1;
802  for (source_x = 1; source_x <= nx; source_x++) {
803  for (source_y = 1; source_y <= ny; source_y++) {
804  delta_x = abs(source_x - sink_x);
805  delta_y = abs(source_y - sink_y);
806 
807  delta_clb_to_io[delta_x][delta_y] = assign_blocks_and_route_net(
808  source_type, source_x, source_y, sink_type, sink_x, sink_y,
809  router_opts, det_routing_arch, segment_inf, timing_inf);
810  }
811  }
812 
813  sink_x = 1;
814  sink_y = 0;
815  source_x = 1;
816  delta_x = abs(source_x - sink_x);
817  for (source_y = 1; source_y <= ny; source_y++) {
818  delta_y = abs(source_y - sink_y);
819  delta_clb_to_io[delta_x][delta_y] = assign_blocks_and_route_net(
820  source_type, source_x, source_y, sink_type, sink_x, sink_y,
821  router_opts, det_routing_arch, segment_inf, timing_inf);
822  }
823 
824  sink_x = 1;
825  sink_y = 0;
826  source_y = ny;
827  delta_y = abs(source_y - sink_y);
828  for (source_x = 2; source_x <= nx; source_x++) {
829  delta_x = abs(source_x - sink_x);
830  delta_clb_to_io[delta_x][delta_y] = assign_blocks_and_route_net(
831  source_type, source_x, source_y, sink_type, sink_x, sink_y,
832  router_opts, det_routing_arch, segment_inf, timing_inf);
833  }
834 }
835 
836 /**************************************/
837 static void compute_delta_io_to_io(struct s_router_opts router_opts,
838  struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
839  t_timing_inf timing_inf) {
840  int source_x, source_y, sink_x, sink_y;
841  int delta_x, delta_y;
842  t_type_ptr source_type, sink_type;
843 
844  source_type = IO_TYPE;
845  sink_type = IO_TYPE;
846 
847  delta_io_to_io[0][0] = 0; /*delay to itself is 0 (this can happen) */
848  delta_io_to_io[nx + 1][ny + 1] = IMPOSSIBLE;
851  delta_io_to_io[nx][ny + 1] = IMPOSSIBLE;
852  delta_io_to_io[nx + 1][ny] = IMPOSSIBLE;
853 
854  source_x = 0;
855  source_y = 1;
856  sink_x = 0;
857  delta_x = abs(sink_x - source_x);
858 
859  for (sink_y = 2; sink_y <= ny; sink_y++) {
860  delta_y = abs(sink_y - source_y);
861  delta_io_to_io[delta_x][delta_y] = assign_blocks_and_route_net(
862  source_type, source_x, source_y, sink_type, sink_x, sink_y,
863  router_opts, det_routing_arch, segment_inf, timing_inf);
864 
865  }
866 
867  source_x = 0;
868  source_y = 1;
869  sink_x = nx + 1;
870  delta_x = abs(sink_x - source_x);
871 
872  for (sink_y = 1; sink_y <= ny; sink_y++) {
873  delta_y = abs(sink_y - source_y);
874  delta_io_to_io[delta_x][delta_y] = assign_blocks_and_route_net(
875  source_type, source_x, source_y, sink_type, sink_x, sink_y,
876  router_opts, det_routing_arch, segment_inf, timing_inf);
877 
878  }
879 
880  source_x = 1;
881  source_y = 0;
882  sink_y = 0;
883  delta_y = abs(sink_y - source_y);
884 
885  for (sink_x = 2; sink_x <= nx; sink_x++) {
886  delta_x = abs(sink_x - source_x);
887  delta_io_to_io[delta_x][delta_y] = assign_blocks_and_route_net(
888  source_type, source_x, source_y, sink_type, sink_x, sink_y,
889  router_opts, det_routing_arch, segment_inf, timing_inf);
890 
891  }
892 
893  source_x = 1;
894  source_y = 0;
895  sink_y = ny + 1;
896  delta_y = abs(sink_y - source_y);
897 
898  for (sink_x = 1; sink_x <= nx; sink_x++) {
899  delta_x = abs(sink_x - source_x);
900  delta_io_to_io[delta_x][delta_y] = assign_blocks_and_route_net(
901  source_type, source_x, source_y, sink_type, sink_x, sink_y,
902  router_opts, det_routing_arch, segment_inf, timing_inf);
903 
904  }
905 
906  source_x = 0;
907  sink_y = ny + 1;
908  for (source_y = 1; source_y <= ny; source_y++) {
909  for (sink_x = 1; sink_x <= nx; sink_x++) {
910  delta_y = abs(source_y - sink_y);
911  delta_x = abs(source_x - sink_x);
912  delta_io_to_io[delta_x][delta_y] = assign_blocks_and_route_net(
913  source_type, source_x, source_y, sink_type, sink_x, sink_y,
914  router_opts, det_routing_arch, segment_inf, timing_inf);
915 
916  }
917  }
918 }
919 
920 /**************************************/
921 #ifdef PRINT_ARRAYS
922 static void
923 print_array(float **array_to_print,
924  int x1,
925  int x2,
926  int y1,
927  int y2)
928 {
929 
930  int idx_x, idx_y;
931 
932  fprintf(lookup_dump, "\nPrinting Array \n\n");
933 
934  for (idx_y = y2; idx_y >= y1; idx_y--)
935  {
936  for (idx_x = x1; idx_x <= x2; idx_x++)
937  {
938  fprintf(lookup_dump, " %9.2e",
939  array_to_print[idx_x][idx_y]);
940  }
941  fprintf(lookup_dump, "\n");
942  }
943  fprintf(lookup_dump, "\n\n");
944 }
945 #endif
946 /**************************************/
947 static void compute_delta_arrays(struct s_router_opts router_opts,
948  struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
949  t_timing_inf timing_inf, int longest_length) {
950 
951  vpr_printf(TIO_MESSAGE_INFO, "Computing delta_io_to_io lookup matrix, may take a few seconds, please wait...\n");
952  compute_delta_io_to_io(router_opts, det_routing_arch, segment_inf, timing_inf);
953  vpr_printf(TIO_MESSAGE_INFO, "Computing delta_io_to_clb lookup matrix, may take a few seconds, please wait...\n");
954  compute_delta_io_to_clb(router_opts, det_routing_arch, segment_inf, timing_inf);
955  vpr_printf(TIO_MESSAGE_INFO, "Computing delta_clb_to_io lookup matrix, may take a few seconds, please wait...\n");
956  compute_delta_clb_to_io(router_opts, det_routing_arch, segment_inf, timing_inf);
957  vpr_printf(TIO_MESSAGE_INFO, "Computing delta_clb_to_clb lookup matrix, may take a few seconds, please wait...\n");
958  compute_delta_clb_to_clb(router_opts, det_routing_arch, segment_inf, timing_inf, longest_length);
959 
960 #ifdef PRINT_ARRAYS
961  lookup_dump = my_fopen(DUMPFILE, "w", 0);
962  fprintf(lookup_dump, "\n\nprinting delta_clb_to_clb\n");
963  print_array(delta_clb_to_clb, 0, nx - 1, 0, ny - 1);
964  fprintf(lookup_dump, "\n\nprinting delta_io_to_clb\n");
965  print_array(delta_io_to_clb, 0, nx, 0, ny);
966  fprintf(lookup_dump, "\n\nprinting delta_clb_to_io\n");
967  print_array(delta_clb_to_io, 0, nx, 0, ny);
968  fprintf(lookup_dump, "\n\nprinting delta_io_to_io\n");
969  print_array(delta_io_to_io, 0, nx + 1, 0, ny + 1);
970  fclose(lookup_dump);
971 #endif
972 
973 }
974 
975 /******* Globally Accessable Functions **********/
976 
977 /**************************************/
979  struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
980  t_timing_inf timing_inf, t_chan_width_dist chan_width_dist, INP t_direct_inf *directs,
981  INP int num_directs) {
982 
983  static struct s_net *original_net; /*this will be used as a pointer to remember what */
984 
985  /*the "real" nets in the circuit are. This is */
986  /*required because we are using the net structure */
987  /*in these routines to find delays between blocks */
988  static struct s_block *original_block; /*same def as original_nets, but for block */
989 
990  static int original_num_nets;
991  static int original_num_blocks;
992  static int longest_length;
993 
995 
996  alloc_and_assign_internal_structures(&original_net, &original_block,
997  &original_num_nets, &original_num_blocks);
998  setup_chan_width(router_opts, chan_width_dist);
999 
1000  alloc_routing_structs(router_opts, det_routing_arch, segment_inf,
1001  timing_inf, directs, num_directs);
1002 
1003  longest_length = get_longest_segment_length(det_routing_arch, segment_inf);
1004 
1005  /*now setup and compute the actual arrays */
1007  compute_delta_arrays(router_opts, det_routing_arch, segment_inf, timing_inf,
1008  longest_length);
1009 
1010  /*free all data structures that are no longer needed */
1011  free_routing_structs(router_opts, det_routing_arch, segment_inf,
1012  timing_inf);
1013 
1015 
1016  free_and_reset_internal_structures(original_net, original_block,
1017  original_num_nets, original_num_blocks);
1018 }
1019 
1020 /**************************************/
1022 
1024 
1025 }
int * node_block_pin
Definition: vpr_types.h:509
t_type_ptr type
Definition: vpr_types.h:522
static int get_first_pin(enum e_pin_type pintype, t_type_ptr type)
static struct s_grid_tile ** grid_backup
#define NET_USED
static void load_simplified_device(void)
t_type_ptr FILL_TYPE
Definition: globals.c:42
#define SINK_BLOCK
FILE * my_fopen(const char *fname, const char *flag, int prompt)
Definition: util.c:54
void free_rr_graph(void)
Definition: rr_graph.c:798
void free_timing_driven_route_structs(float *pin_criticality, int *sink_order, t_rt_node **rt_node_of_sink)
Definition: route_timing.c:279
void ** alloc_matrix(int nrmin, int nrmax, int ncmin, int ncmax, size_t elsize)
Definition: util.c:551
static t_type_ptr EMPTY_TYPE_BACKUP
static void compute_delta_io_to_io(struct s_router_opts router_opts, struct s_det_routing_arch det_routing_arch, t_segment_inf *segment_inf, t_timing_inf timing_inf)
static void alloc_net(void)
t_type_ptr EMPTY_TYPE
Definition: globals.c:41
struct s_class * class_inf
void free_matrix(void *vptr, int nrmin, int nrmax, int ncmin, size_t elsize)
Definition: util.c:573
#define SOURCE_BLOCK
short delayless_switch
Definition: vpr_types.h:764
static void alloc_block(void)
short global_route_switch
Definition: vpr_types.h:763
int fixed_channel_width
Definition: vpr_types.h:704
static void alloc_delta_arrays(void)
static void free_and_reset_internal_structures(struct s_net *original_net, struct s_block *original_block, int original_num_nets, int original_num_blocks)
static void assign_locations(t_type_ptr source_type, int source_x_loc, int source_y_loc, int source_z_loc, t_type_ptr sink_type, int sink_x_loc, int sink_y_loc, int sink_z_loc)
static float ** net_delay
int x
Definition: vpr_types.h:563
enum e_graph_type t_graph_type
Definition: rr_graph.h:11
float ** delta_clb_to_clb
int * chan_width_x
Definition: globals.c:56
static t_type_ptr IO_TYPE_BACKUP
#define NET_USED_SOURCE_BLOCK
#define NET_COUNT
void free_trace_structs(void)
Definition: route_common.c:733
void free_place_lookup_structs(void)
int num_nets
Definition: globals.c:27
int * node_block
Definition: vpr_types.h:507
float ** delta_io_to_clb
static void free_routing_structs(struct s_router_opts router_opts, struct s_det_routing_arch det_routing_arch, t_segment_inf *segment_inf, t_timing_inf timing_inf)
static void compute_delta_clb_to_io(struct s_router_opts router_opts, struct s_det_routing_arch det_routing_arch, t_segment_inf *segment_inf, t_timing_inf timing_inf)
char * name
Definition: vpr_types.h:505
static t_type_descriptor * type_descriptors_backup
static void compute_delta_arrays(struct s_router_opts router_opts, struct s_det_routing_arch det_routing_arch, t_segment_inf *segment_inf, t_timing_inf timing_inf, int longest_length)
t_type_ptr type
Definition: vpr_types.h:561
int num_blocks
Definition: globals.c:30
#define IMPOSSIBLE
char * name
Definition: vpr_types.h:560
void load_net_rr_terminals(t_ivec ***L_rr_node_indices)
Definition: rr_graph.c:855
static void setup_chan_width(struct s_router_opts router_opts, t_chan_width_dist chan_width_dist)
Definition: util.h:12
static float pres_fac
static void reset_placement(void)
#define DUMPFILE
int y
Definition: vpr_types.h:564
static t_ivec ** clb_opins_used_locally
#define EMPTY
Definition: vpr_types.h:90
static t_type_ptr FILL_TYPE_BACKUP
float bend_cost
Definition: vpr_types.h:700
static void * my_malloc(int ibytes)
Definition: graphics.c:499
void alloc_and_load_rr_node_route_structs(void)
Definition: route_common.c:785
void init_route_structs(int bb_factor)
Definition: route_common.c:394
int * pinlist
enum e_directionality directionality
Definition: vpr_types.h:758
#define max(a, b)
Definition: graphics.c:171
void build_rr_graph(INP t_graph_type graph_type, INP int L_num_types, INP t_type_ptr types, INP int L_nx, INP int L_ny, INP struct s_grid_tile **L_grid, INP int chan_width, INP struct s_chan_width_dist *chan_capacity_inf, INP enum e_switch_block_type sb_type, INP int Fs, INP int num_seg_types, INP int num_switches, INP t_segment_inf *segment_inf, INP int global_route_switch, INP int delayless_switch, INP t_timing_inf timing_inf, INP int wire_to_ipin_switch, INP enum e_base_cost_type base_cost_type, INP t_direct_inf *directs, INP int num_directs, INP boolean ignore_Fc_0, OUTP int *Warnings)
Definition: rr_graph.c:192
static float * pin_criticality
struct s_block * block
Definition: globals.c:31
struct s_net * clb_net
Definition: globals.c:28
#define INP
Definition: util.h:19
int nx
Definition: globals.c:46
void init_chan(int cfactor, t_chan_width_dist chan_width_dist)
void free_ivec_vector(struct s_ivec *ivec_vector, int nrmin, int nrmax)
Definition: util.c:498
float ** delta_io_to_io
float ** delta_clb_to_io
t_ivec ** alloc_route_structs(void)
Definition: route_common.c:611
e_pin_type
void alloc_timing_driven_route_structs(float **pin_criticality_ptr, int **sink_order_ptr, t_rt_node ***rt_node_of_sink_ptr)
Definition: route_timing.c:253
enum e_route_type route_type
Definition: vpr_types.h:703
struct s_grid_tile ** grid
Definition: globals.c:59
float astar_fac
Definition: vpr_types.h:707
Definition: util.h:47
boolean is_global
Definition: vpr_types.h:510
void compute_delay_lookup_tables(struct s_router_opts router_opts, struct s_det_routing_arch det_routing_arch, t_segment_inf *segment_inf, t_timing_inf timing_inf, t_chan_width_dist chan_width_dist, INP t_direct_inf *directs, INP int num_directs)
int * blocks
Definition: vpr_types.h:525
static int get_longest_segment_length(struct s_det_routing_arch det_routing_arch, t_segment_inf *segment_inf)
static void restore_original_device(void)
t_ivec *** rr_node_indices
Definition: globals.c:71
boolean timing_driven_route_net(int inet, float pres_fac, float max_criticality, float criticality_exp, float astar_fac, float bend_cost, float *pin_criticality, int *sink_order, t_rt_node **rt_node_of_sink, float *net_delay, t_slack *slacks)
Definition: route_timing.c:307
static int num_types_backup
enum e_switch_block_type switch_block_type
Definition: vpr_types.h:760
int num_types
Definition: globals.c:37
t_type_ptr IO_TYPE
Definition: globals.c:40
float max_criticality
Definition: vpr_types.h:708
#define NO_FIXED_CHANNEL_WIDTH
Definition: vpr_types.h:692
static t_type_descriptor dummy_type_descriptors[NUM_TYPES_USED]
Definition: slre.c:50
int * nets
Definition: vpr_types.h:562
static void alloc_routing_structs(struct s_router_opts router_opts, struct s_det_routing_arch det_routing_arch, t_segment_inf *segment_inf, t_timing_inf timing_inf, INP t_direct_inf *directs, INP int num_directs)
#define NUM_TYPES_USED
void free_rr_node_route_structs(void)
Definition: route_common.c:828
int z
Definition: vpr_types.h:565
float criticality_exp
Definition: vpr_types.h:709
struct s_type_descriptor * type_descriptors
Definition: globals.c:38
enum e_pin_type type
static t_rt_node ** rt_node_of_sink
static void compute_delta_clb_to_clb(struct s_router_opts router_opts, struct s_det_routing_arch det_routing_arch, t_segment_inf *segment_inf, t_timing_inf timing_inf, int longest_length)
#define NET_USED_SINK_BLOCK
boolean * is_global_pin
int ny
Definition: globals.c:47
void free_route_structs()
Definition: route_common.c:750
messagelogger vpr_printf
Definition: util.c:17
static float assign_blocks_and_route_net(t_type_ptr source_type, int source_x_loc, int source_y_loc, t_type_ptr sink_type, int sink_x_loc, int sink_y_loc, struct s_router_opts router_opts, struct s_det_routing_arch det_routing_arch, t_segment_inf *segment_inf, t_timing_inf timing_inf)
int num_sinks
Definition: vpr_types.h:506
short wire_to_ipin_switch
Definition: vpr_types.h:765
enum e_base_cost_type base_cost_type
Definition: vpr_types.h:706
static void alloc_and_assign_internal_structures(struct s_net **original_net, struct s_block **original_block, int *original_num_nets, int *original_num_blocks)
static void free_delta_arrays(void)
#define BLOCK_COUNT
Definition: util.h:12
static int * sink_order
static void generic_compute_matrix(float ***matrix_ptr, t_type_ptr source_type, t_type_ptr sink_type, int source_x, int source_y, int start_x, int end_x, int start_y, int end_y, struct s_router_opts router_opts, struct s_det_routing_arch det_routing_arch, t_segment_inf *segment_inf, t_timing_inf timing_inf)
static void compute_delta_io_to_clb(struct s_router_opts router_opts, struct s_det_routing_arch det_routing_arch, t_segment_inf *segment_inf, t_timing_inf timing_inf)