VPR-7.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
draw.c
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <string.h>
3 #include <algorithm>
4 #include <math.h>
5 #include "vpr_types.h"
6 #include "vpr_utils.h"
7 #include "globals.h"
8 #include "graphics.h"
9 #include "path_delay.h"
10 #include "draw.h"
11 #include <assert.h>
12 #include "read_xml_arch_file.h"
13 #include "util.h"
14 
15 #ifdef DEBUG
16 #include "rr_graph.h"
17 #endif
18 
19 
20 /*************** Types local to this module *********************************/
21 #define MAX_BLOCK_COLOURS 5
22 
30 };
31 
34 };
35 
36 enum e_edge_dir {
38 };
39 /* Chanx to chany or vice versa? */
40 
41 /****************** Variables local to this module. *************************/
42 
43 static boolean show_nets = FALSE; /* Show nets of placement or routing? */
44 
45 /* Controls drawing of routing resources on screen, if pic_on_screen is *
46  * ROUTING. */
47 
48 /* Can toggle to DRAW_NO_RR;*/
49 static enum e_draw_rr_toggle draw_rr_toggle = DRAW_NO_RR; /* UDSD by AY */
50 
52 
53 /* Controls if congestion is shown, when ROUTING is on screen. */
54 
55 static boolean show_congestion = FALSE;
56 
57 static boolean show_defects = FALSE; /* Show defective stuff */
58 
59 static boolean show_graphics; /* Graphics enabled or not? */
60 
61 static char default_message[BUFSIZE]; /* Default screen message on screen */
62 
63 static int gr_automode; /* Need user input after: 0: each t, *
64  * 1: each place, 2: never */
65 
66 static enum pic_type pic_on_screen = NO_PICTURE; /* What do I draw? */
67 
68 static float *tile_x, *tile_y;
69 
70 /* The left and bottom coordinates of each grid_tile in the FPGA. *
71  * tile_x[0..nx+1] and tile_y[0..ny+1]. *
72  * COORDINATE SYSTEM goes from (0,0) at the lower left corner to *
73  * (tile_x[nx+1]+tile_width, tile_y[ny+1]+tile_width) in the *
74  * upper right corner. */
75 
76 static float tile_width, pin_size;
77 
78 /* Drawn width (and height) of a grid_tile, and the half-width or half-height of *
79  * a pin, respectiviely. Set when init_draw_coords is called. */
80 
82 
83 /* Color in which each block and net should be drawn. *
84  * [0..num_nets-1] and [0..num_blocks-1], respectively. */
85 
86 static float line_fuz = 0.3;
87 static const char *name_type[] = { "SOURCE", "SINK", "IPIN", "OPIN", "CHANX", "CHANY",
88  "INTRA_CLUSTER_EDGE" };
89 
90 static float *x_rr_node_left = NULL;
91 static float *x_rr_node_right = NULL;
92 static float *y_rr_node_top = NULL;
93 static float *y_rr_node_bottom = NULL;
94 static enum color_types *rr_node_color = NULL;
95 static int old_num_rr_nodes = 0;
96 
97 /********************** Subroutines local to this module ********************/
98 
99 static void toggle_nets(void (*drawscreen)(void));
100 static void toggle_rr(void (*drawscreen)(void));
101 static void toggle_defects(void (*drawscreen)(void));
102 static void toggle_congestion(void (*drawscreen)(void));
103 static void highlight_crit_path(void (*drawscreen_ptr)(void));
104 
105 static void drawscreen(void);
106 static void redraw_screen(void);
107 static void drawplace(void);
108 static void drawnets(void);
109 static void drawroute(enum e_draw_net_type draw_net_type);
110 static void draw_congestion(void);
111 
112 static void highlight_blocks(float x, float y);
113 static void get_block_center(int bnum, float *x, float *y);
114 static void deselect_all(void);
115 
116 static void draw_rr(void);
117 static void draw_rr_edges(int from_node);
118 static void draw_rr_pin(int inode, enum color_types color);
119 static void draw_rr_chanx(int inode, int itrack);
120 static void draw_rr_chany(int inode, int itrack);
121 static void get_rr_pin_draw_coords(int inode, int iside, int ioff, float *xcen,
122  float *ycen);
123 static void draw_pin_to_chan_edge(int pin_node, int chan_node);
124 static void draw_pin_to_pin(int opin, int ipin);
125 static void draw_x(float x, float y, float size);
126 static void draw_chany_to_chany_edge(int from_node, int from_track, int to_node,
127  int to_track, short switch_type);
128 static void draw_chanx_to_chanx_edge(int from_node, int from_track, int to_node,
129  int to_track, short switch_type);
130 static void draw_chanx_to_chany_edge(int chanx_node, int chanx_track,
131  int chany_node, int chany_track, enum e_edge_dir edge_dir,
132  short switch_type);
133 static int get_track_num(int inode, int **chanx_track, int **chany_track);
134 static void draw_rr_switch(float from_x, float from_y, float to_x, float to_y,
135  boolean buffered);
136 static void draw_triangle_along_line(float xend, float yend, /* UDSD by AY */
137 
138 float x1, float x2, /* UDSD by AY */
139 
140 float y1, float y2); /* UDSD by AY */
141 
142 /********************** Subroutine definitions ******************************/
143 
144 void set_graphics_state(boolean show_graphics_val, int gr_automode_val,
145  enum e_route_type route_type) {
146 
147  /* Sets the static show_graphics and gr_automode variables to the *
148  * desired values. They control if graphics are enabled and, if so, *
149  * how often the user is prompted for input. */
150 
151  show_graphics = show_graphics_val;
152  gr_automode = gr_automode_val;
153  draw_route_type = route_type;
154 }
155 
156 void update_screen(int priority, char *msg, enum pic_type pic_on_screen_val,
157  boolean crit_path_button_enabled) {
158 
159  /* Updates the screen if the user has requested graphics. The priority *
160  * value controls whether or not the Proceed button must be clicked to *
161  * continue. Saves the pic_on_screen_val to allow pan and zoom redraws. */
162 
163  if (!show_graphics) /* Graphics turned off */
164  return;
165 
166  /* If it's the type of picture displayed has changed, set up the proper *
167  * buttons. */
168  if (pic_on_screen != pic_on_screen_val) {
169  if (pic_on_screen_val == PLACEMENT && pic_on_screen == NO_PICTURE) {
170  create_button("Window", "Toggle Nets", toggle_nets);
171  } else if (pic_on_screen_val == ROUTING && pic_on_screen == PLACEMENT) {
172  create_button("Toggle Nets", "Toggle RR", toggle_rr);
173  create_button("Toggle RR", "Tog Defects", toggle_defects);
174  create_button("Toggle RR", "Congestion", toggle_congestion);
175 
176  if (crit_path_button_enabled) {
177  create_button("Congestion", "Crit. Path", highlight_crit_path);
178  }
179  } else if (pic_on_screen_val == PLACEMENT && pic_on_screen == ROUTING) {
180  destroy_button("Toggle RR");
181  destroy_button("Congestion");
182 
183  if (crit_path_button_enabled) {
184  destroy_button("Crit. Path");
185  }
186  } else if (pic_on_screen_val == ROUTING
187  && pic_on_screen == NO_PICTURE) {
188  create_button("Window", "Toggle Nets", toggle_nets);
189  create_button("Toggle Nets", "Toggle RR", toggle_rr);
190  create_button("Toggle RR", "Tog Defects", toggle_defects);
191  create_button("Tog Defects", "Congestion", toggle_congestion);
192 
193  if (crit_path_button_enabled) {
194  create_button("Congestion", "Crit. Path", highlight_crit_path);
195  }
196  }
197  }
198  /* Save the main message. */
199 
201 
202  pic_on_screen = pic_on_screen_val;
203  update_message(msg);
204  drawscreen();
205  if (priority >= gr_automode) {
206  event_loop(highlight_blocks, NULL, NULL, drawscreen);
207  } else {
208  flushinput();
209  }
210 }
211 
212 static void drawscreen() {
213 
214  /* This is the screen redrawing routine that event_loop assumes exists. *
215  * It erases whatever is on screen, then calls redraw_screen to redraw *
216  * it. */
217 
218  clearscreen();
219  redraw_screen();
220 }
221 
222 static void redraw_screen() {
223 
224  /* The screen redrawing routine called by drawscreen and *
225  * highlight_blocks. Call this routine instead of drawscreen if *
226  * you know you don't need to erase the current graphics, and want *
227  * to avoid a screen "flash". */
228 
229  setfontsize(14); /* UDSD Modification by WMF */
230  if (pic_on_screen == PLACEMENT) {
231  drawplace();
232  if (show_nets) {
233  drawnets();
234  }
235  } else { /* ROUTING on screen */
236  drawplace();
237 
238  if (show_nets) {
240  } else {
241  draw_rr();
242  }
243 
244  if (show_congestion) {
245  draw_congestion();
246  }
247  }
248 }
249 
250 static void toggle_nets(void (*drawscreen_ptr)(void)) {
251 
252  /* Enables/disables drawing of nets when a the user clicks on a button. *
253  * Also disables drawing of routing resources. See graphics.c for details *
254  * of how buttons work. */
255 
256  show_nets = (show_nets == FALSE) ? TRUE : FALSE;
259 
261  drawscreen_ptr();
262 }
263 
264 static void toggle_rr(void (*drawscreen_ptr)(void)) {
265 
266  /* Cycles through the options for viewing the routing resources available *
267  * in an FPGA. If a routing isn't on screen, the routing graph hasn't been *
268  * built, and this routine doesn't switch the view. Otherwise, this routine *
269  * switches to the routing resource view. Clicking on the toggle cycles *
270  * through the options: DRAW_NO_RR, DRAW_ALL_RR, DRAW_ALL_BUT_BUFFERS_RR, *
271  * DRAW_NODES_AND_SBOX_RR, and DRAW_NODES_RR. */
272 
273  draw_rr_toggle = (enum e_draw_rr_toggle) (((int)draw_rr_toggle + 1) % ((int)DRAW_RR_TOGGLE_MAX));
274  show_nets = FALSE;
276 
278  drawscreen_ptr();
279 }
280 
281 static void toggle_defects(void (*drawscreen_ptr)(void)) {
284  drawscreen_ptr();
285 }
286 
287 static void toggle_congestion(void (*drawscreen_ptr)(void)) {
288 
289  /* Turns the congestion display on and off. */
290  char msg[BUFSIZE];
291  int inode, num_congested;
292 
293  show_nets = FALSE;
296 
297  if (!show_congestion) {
299  } else {
300  num_congested = 0;
301  for (inode = 0; inode < num_rr_nodes; inode++) {
302  if (rr_node[inode].occ > rr_node[inode].capacity) {
303  num_congested++;
304  }
305  }
306 
307  sprintf(msg, "%d routing resources are overused.", num_congested);
308  update_message(msg);
309  }
310 
311  drawscreen_ptr();
312 }
313 
314 static void highlight_crit_path(void (*drawscreen_ptr)(void)) {
315 
316  /* Highlights all the blocks and nets on the critical path. */
317 
318  t_linked_int *critical_path_head, *critical_path_node;
319  int inode, iblk, inet, num_nets_seen;
320  static int nets_to_highlight = 1;
321  char msg[BUFSIZE];
322 
323  if (nets_to_highlight == 0) { /* Clear the display of all highlighting. */
324  nets_to_highlight = 1;
325  deselect_all();
327  drawscreen_ptr();
328  return;
329  }
330 
331  critical_path_head = allocate_and_load_critical_path();
332  critical_path_node = critical_path_head;
333  num_nets_seen = 0;
334 
335  while (critical_path_node != NULL) {
336  inode = critical_path_node->data;
337  get_tnode_block_and_output_net(inode, &iblk, &inet);
338 
339  if (num_nets_seen == nets_to_highlight) { /* Last block */
340  block_color[iblk] = MAGENTA;
341  } else if (num_nets_seen == nets_to_highlight - 1) { /* 2nd last block */
342  block_color[iblk] = YELLOW;
343  } else if (num_nets_seen < nets_to_highlight) { /* Earlier block */
344  block_color[iblk] = DARKGREEN;
345  }
346 
347  if (inet != OPEN) {
348  num_nets_seen++;
349 
350  if (num_nets_seen < nets_to_highlight) { /* First nets. */
351  net_color[inet] = DARKGREEN;
352  } else if (num_nets_seen == nets_to_highlight) {
353  net_color[inet] = CYAN; /* Last (new) net. */
354  }
355  }
356 
357  critical_path_node = critical_path_node->next;
358  }
359 
360  if (nets_to_highlight == num_nets_seen) {
361  nets_to_highlight = 0;
362  sprintf(msg, "All %d nets on the critical path highlighted.",
363  num_nets_seen);
364  } else {
365  sprintf(msg, "First %d nets on the critical path highlighted.",
366  nets_to_highlight);
367  nets_to_highlight++;
368  }
369 
370  free_int_list(&critical_path_head);
371 
372  update_message(msg);
373  drawscreen_ptr();
374 }
375 
376 void alloc_draw_structs(void) {
377 
378  /* Allocate the structures needed to draw the placement and routing. Set *
379  * up the default colors for blocks and nets. */
380 
381  tile_x = (float *) my_malloc((nx + 2) * sizeof(float));
382  tile_y = (float *) my_malloc((ny + 2) * sizeof(float));
383 
384  net_color = (enum color_types *) my_malloc(
385  num_nets * sizeof(enum color_types));
386 
387  block_color = (enum color_types *) my_malloc(
388  num_blocks * sizeof(enum color_types));
389 
390  x_rr_node_left = (float *) my_malloc(num_rr_nodes * sizeof(float));
391  x_rr_node_right = (float *) my_malloc(num_rr_nodes * sizeof(float));
392  y_rr_node_top = (float *) my_malloc(num_rr_nodes * sizeof(float));
393  y_rr_node_bottom = (float *) my_malloc(num_rr_nodes * sizeof(float));
395  num_rr_nodes * sizeof(enum color_types));
396 
397  deselect_all(); /* Set initial colors */
398 }
399 
400 void free_draw_structs(void) {
401 
402  /* Free everything allocated by alloc_draw_structs. Called after close_graphics() *
403  * in vpr_api.c.
404  *
405  * For safety, set all the array pointers to NULL in case any data
406  * structure gets freed twice. */
407 
408  free(tile_x);
409  tile_x = NULL;
410  free(tile_y);
411  tile_y = NULL;
412 
413  free(net_color);
414  net_color = NULL;
415  free(block_color);
416  block_color = NULL;
417 
418  free(x_rr_node_left);
419  x_rr_node_left = NULL;
420  free(x_rr_node_right);
421  x_rr_node_right = NULL;
422  free(y_rr_node_top);
423  y_rr_node_top = NULL;
424  free(y_rr_node_bottom);
425  y_rr_node_bottom = NULL;
426  free(rr_node_color);
427  rr_node_color = NULL;
428 }
429 
430 void init_draw_coords(float width_val) {
431 
432  /* Load the arrays containing the left and bottom coordinates of the clbs *
433  * forming the FPGA. tile_width_val sets the width and height of a drawn *
434  * clb. */
435 
436  int i;
437  int j;
438 
439  if (!show_graphics)
440  return; /* -nodisp was selected. */
441 
444  (num_rr_nodes) * sizeof(float));
446  (num_rr_nodes) * sizeof(float));
448  (num_rr_nodes) * sizeof(float));
450  (num_rr_nodes) * sizeof(float));
452  (num_rr_nodes) * sizeof(enum color_types));
453  for (i = 0; i < num_rr_nodes; i++) {
454  x_rr_node_left[i] = -1;
455  x_rr_node_right[i] = -1;
456  y_rr_node_top[i] = -1;
457  y_rr_node_bottom[i] = -1;
458  rr_node_color[i] = BLACK;
459  }
460  }
461 
462  tile_width = width_val;
463  pin_size = 0.3;
464  for (i = 0; i < num_types; ++i) {
466  (tile_width / (4.0F * type_descriptors[i].num_pins)));
467  }
468 
469  j = 0;
470  for (i = 0; i < (nx + 1); i++) {
471  tile_x[i] = (i * tile_width) + j;
472  j += chan_width_y[i] + 1; /* N wires need N+1 units of space */
473  }
474  tile_x[nx + 1] = ((nx + 1) * tile_width) + j;
475 
476  j = 0;
477  for (i = 0; i < (ny + 1); ++i) {
478  tile_y[i] = (i * tile_width) + j;
479  j += chan_width_x[i] + 1;
480  }
481  tile_y[ny + 1] = ((ny + 1) * tile_width) + j;
482 
483  init_world(0.0, tile_y[ny + 1] + tile_width, tile_x[nx + 1] + tile_width,
484  0.0);
485 }
486 
487 static void drawplace(void) {
488 
489  /* Draws the blocks placed on the proper clbs. Occupied blocks are darker colours *
490  * while empty ones are lighter colours and have a dashed border. */
491 
492  float sub_tile_step;
493  float x1, y1, x2, y2;
494  int i, j, k, bnum;
495  int num_sub_tiles;
496  int height;
497 
498  setlinewidth(0);
499 
500  for (i = 0; i <= (nx + 1); i++) {
501  for (j = 0; j <= (ny + 1); j++) {
502  /* Only the first block of a group should control drawing */
503  if (grid[i][j].offset > 0)
504  continue;
505 
506  /* Don't draw corners */
507  if (((i < 1) || (i > nx)) && ((j < 1) || (j > ny)))
508  continue;
509 
510  num_sub_tiles = grid[i][j].type->capacity;
511  sub_tile_step = tile_width / num_sub_tiles;
512  height = grid[i][j].type->height;
513 
514  if (num_sub_tiles < 1) {
515  setcolor(BLACK);
517  drawrect(tile_x[i], tile_y[j], tile_x[i] + tile_width,
518  tile_y[j] + tile_width);
519  draw_x(tile_x[i] + (tile_width / 2),
520  tile_y[j] + (tile_width / 2), (tile_width / 2));
521  }
522 
523  for (k = 0; k < num_sub_tiles; ++k) {
524  /* Graphics will look unusual for multiple height and capacity */
525  assert(height == 1 || num_sub_tiles == 1);
526  /* Get coords of current sub_tile */
527  if ((i < 1) || (i > nx)) { /* left and right fringes */
528  x1 = tile_x[i];
529  y1 = tile_y[j] + (k * sub_tile_step);
530  x2 = x1 + tile_width;
531  y2 = y1 + sub_tile_step;
532  } else if ((j < 1) || (j > ny)) { /* top and bottom fringes */
533  x1 = tile_x[i] + (k * sub_tile_step);
534  y1 = tile_y[j];
535  x2 = x1 + sub_tile_step;
536  y2 = y1 + tile_width;
537  } else {
538  assert(num_sub_tiles <= 1);
539  /* Need to change draw code to support */
540 
541  x1 = tile_x[i];
542  y1 = tile_y[j];
543  x2 = x1 + tile_width;
544  y2 = tile_y[j + height - 1] + tile_width;
545  }
546 
547  /* Look at the tile at start of large block */
548  bnum = grid[i][j].blocks[k];
549 
550  /* Draw background */
551  if (bnum != EMPTY) {
552  setcolor(block_color[bnum]);
553  fillrect(x1, y1, x2, y2);
554  } else {
555  /* colour empty blocks a particular colour depending on type */
556  if (grid[i][j].type->index < 3) {
557  setcolor(WHITE);
558  } else if (grid[i][j].type->index < 3 + MAX_BLOCK_COLOURS) {
559  setcolor(BISQUE + grid[i][j].type->index - 3);
560  } else {
562  }
563  fillrect(x1, y1, x2, y2);
564  }
565 
566  setcolor(BLACK);
567 
568  setlinestyle((EMPTY == bnum) ? DASHED : SOLID);
569  drawrect(x1, y1, x2, y2);
570 
571  /* Draw text if the space has parts of the netlist */
572  if (bnum != EMPTY) {
573  drawtext((x1 + x2) / 2.0, (y1 + y2) / 2.0, block[bnum].name,
574  tile_width);
575  }
576 
577  /* Draw text for block type so that user knows what block */
578  if (grid[i][j].offset == 0) {
579  if (i > 0 && i <= nx && j > 0 && j <= ny) {
580  drawtext((x1 + x2) / 2.0, y1 + (tile_width / 4.0),
581  grid[i][j].type->name, tile_width);
582  }
583  }
584  }
585  }
586  }
587 }
588 
589 static void drawnets(void) {
590 
591  /* This routine draws the nets on the placement. The nets have not *
592  * yet been routed, so we just draw a chain showing a possible path *
593  * for each net. This gives some idea of future congestion. */
594 
595  int inet, ipin, b1, b2;
596  float x1, y1, x2, y2;
597 
599  setlinewidth(0);
600 
601  /* Draw the net as a star from the source to each sink. Draw from centers of *
602  * blocks (or sub blocks in the case of IOs). */
603 
604  for (inet = 0; inet < num_nets; inet++) {
605  if (clb_net[inet].is_global)
606  continue; /* Don't draw global nets. */
607 
608  setcolor(net_color[inet]);
609  b1 = clb_net[inet].node_block[0]; /* The DRIVER */
610  get_block_center(b1, &x1, &y1);
611 
612  for (ipin = 1; ipin < (clb_net[inet].num_sinks + 1); ipin++) {
613  b2 = clb_net[inet].node_block[ipin];
614  get_block_center(b2, &x2, &y2);
615  drawline(x1, y1, x2, y2);
616 
617  /* Uncomment to draw a chain instead of a star. */
618  /* x1 = x2; */
619  /* y1 = y2; */
620  }
621  }
622 }
623 
624 static void get_block_center(int bnum, float *x, float *y) {
625 
626  /* This routine finds the center of block bnum in the current placement, *
627  * and returns it in *x and *y. This is used in routine shownets. */
628 
629  int i, j, k;
630  float sub_tile_step;
631 
632  i = block[bnum].x;
633  j = block[bnum].y;
634  k = block[bnum].z;
635 
636  sub_tile_step = tile_width / block[bnum].type->capacity;
637 
638  if ((i < 1) || (i > nx)) { /* Left and right fringe */
639  *x = tile_x[i] + (sub_tile_step * (k + 0.5));
640  } else {
641  *x = tile_x[i] + (tile_width / 2.0);
642  }
643 
644  if ((j < 1) || (j > ny)) { /* Top and bottom fringe */
645  *y = tile_y[j] + (sub_tile_step * (k + 0.5));
646  } else {
647  *y = tile_y[j] + (tile_width / 2.0);
648  }
649 }
650 
651 static void draw_congestion(void) {
652 
653  /* Draws all the overused routing resources (i.e. congestion) in RED. */
654 
655  int inode, itrack;
656 
657  setcolor(RED);
658  setlinewidth(2);
659 
660  for (inode = 0; inode < num_rr_nodes; inode++) {
661  if (rr_node[inode].occ > rr_node[inode].capacity) {
662  switch (rr_node[inode].type) {
663  case CHANX:
664  itrack = rr_node[inode].ptc_num;
665  draw_rr_chanx(inode, itrack);
666  break;
667 
668  case CHANY:
669  itrack = rr_node[inode].ptc_num;
670  draw_rr_chany(inode, itrack);
671  break;
672 
673  case IPIN:
674  case OPIN:
675  draw_rr_pin(inode, RED);
676  break;
677  default:
678  break;
679  }
680  }
681  }
682 }
683 
684 void draw_rr(void) {
685 
686  /* Draws the routing resources that exist in the FPGA, if the user wants *
687  * them drawn. */
688 
689  int inode, itrack;
690 
691  if (draw_rr_toggle == DRAW_NO_RR) {
692  setlinewidth(3);
694  setlinewidth(0);
695  return;
696  }
697 
699  setlinewidth(0);
700 
701  for (inode = 0; inode < num_rr_nodes; inode++) {
702  switch (rr_node[inode].type) {
703 
704  case SOURCE:
705  case SINK:
706  break; /* Don't draw. */
707 
708  case CHANX:
709  if (show_defects && (rr_node[inode].capacity <= 0))
710  setcolor(RED);
711  else
712  setcolor(BLACK);
713  if (show_defects && (rr_node[inode].occ > 0))
714  setcolor(CYAN);
715  itrack = rr_node[inode].ptc_num;
716  draw_rr_chanx(inode, itrack);
717  draw_rr_edges(inode);
718  break;
719 
720  case CHANY:
721  if (show_defects && (rr_node[inode].capacity <= 0))
722  setcolor(RED);
723  else
724  setcolor(BLACK);
725  if (show_defects && (rr_node[inode].occ > 0))
726  setcolor(CYAN);
727  itrack = rr_node[inode].ptc_num;
728  draw_rr_chany(inode, itrack);
729  draw_rr_edges(inode);
730  break;
731 
732  case IPIN:
733  if (show_defects) {
734  if (rr_node[inode].capacity < 0)
735  draw_rr_pin(inode, RED);
736  else if (rr_node[inode].occ > 0)
737  draw_rr_pin(inode, CYAN);
738  else
739  draw_rr_pin(inode, BLACK);
740  } else
741  draw_rr_pin(inode, BLUE);
742  break;
743 
744  case OPIN:
745  if (show_defects) {
746  if (rr_node[inode].capacity < 0)
747  draw_rr_pin(inode, RED);
748  else if (rr_node[inode].occ > 0)
749  draw_rr_pin(inode, CYAN);
750  else
751  draw_rr_pin(inode, BLACK);
752  setcolor(BLACK);
753  } else {
754  draw_rr_pin(inode, RED);
755  setcolor(RED);
756  }
757  setcolor(RED);
758  draw_rr_edges(inode);
759  break;
760 
761  default:
762  vpr_printf(TIO_MESSAGE_ERROR, "in draw_rr: Unexpected rr_node type: %d.\n", rr_node[inode].type);
763  exit(1);
764  }
765  }
766 
767  setlinewidth(3);
769  setlinewidth(0);
770 }
771 
772 static void draw_rr_chanx(int inode, int itrack) {
773 
774  /* Draws an x-directed channel segment. */
775 
776  enum {
777  BUFFSIZE = 80
778  };
779  float x1, x2, y;
780  float y1, y2; /* UDSD by AY */
781  int k; /* UDSD by AY */
782  char str[BUFFSIZE];
783  int savecolor;
784 
785  /* Track 0 at bottom edge, closest to "owning" clb. */
786 
787  x1 = tile_x[rr_node[inode].xlow];
788  x2 = tile_x[rr_node[inode].xhigh] + tile_width;
789  y = tile_y[rr_node[inode].ylow] + tile_width + 1.0 + itrack;
790  x_rr_node_left[inode] = x1;
791  x_rr_node_right[inode] = x2;
792  y_rr_node_bottom[inode] = y - line_fuz;
793  y_rr_node_top[inode] = y + line_fuz;
794  if (rr_node_color[inode] != BLACK) {
795  savecolor = getcolor();
796  setcolor(rr_node_color[inode]);
797  setlinewidth(3);
798  drawline(x1, y, x2, y);
799  setlinewidth(0);
800  setcolor(savecolor);
801  } else {
802  drawline(x1, y, x2, y);
803  }
804  /* UDSD by AY Start */
805  y1 = y - 0.25;
806  y2 = y + 0.25;
807 
808  if (rr_node[inode].direction == INC_DIRECTION) {
809  setlinewidth(2);
810  setcolor(YELLOW);
811  drawline(x1, y1, x1, y2); /* Draw a line at start of wire to indicate mux */
812 
813  /* Mux balence numbers */
814  setcolor(BLACK);
815  sprintf(str, "%d", rr_node[inode].fan_in);
816  drawtext(x1, y, str, 5);
817 
818  setcolor(BLACK);
819  setlinewidth(0);
820  draw_triangle_along_line(x2 - 0.15, y, x1, x2, y, y);
821 
823  /* TODO: this looks odd, why does it ignore final block? does this mean nothing appears with L=1 ? */
824  for (k = rr_node[inode].xlow; k < rr_node[inode].xhigh; k++) {
825  x2 = tile_x[k] + tile_width;
826  draw_triangle_along_line(x2 - 0.15, y, x1, x2, y, y);
827  x2 = tile_x[k + 1];
828  draw_triangle_along_line(x2 + 0.15, y, x1, x2, y, y);
829  }
830  setcolor(BLACK);
831  } else if (rr_node[inode].direction == DEC_DIRECTION) {
832  setlinewidth(2);
833  setcolor(YELLOW);
834  drawline(x2, y1, x2, y2);
835 
836  /* Mux balance numbers */
837  setcolor(BLACK);
838  sprintf(str, "%d", rr_node[inode].fan_in);
839  drawtext(x2, y, str, 5);
840 
841  setlinewidth(0);
842  draw_triangle_along_line(x1 + 0.15, y, x2, x1, y, y);
844  for (k = rr_node[inode].xhigh; k > rr_node[inode].xlow; k--) {
845  x1 = tile_x[k];
846  draw_triangle_along_line(x1 + 0.15, y, x2, x1, y, y);
847  x1 = tile_x[k - 1] + tile_width;
848  draw_triangle_along_line(x1 - 0.15, y, x2, x1, y, y);
849  }
850  setcolor(BLACK);
851  }
852  /* UDSD by AY End */
853 }
854 
855 static void draw_rr_chany(int inode, int itrack) {
856 
857  /* Draws a y-directed channel segment. */
858  enum {
859  BUFFSIZE = 80
860  };
861  float x, y1, y2;
862  float x1, x2; /* UDSD by AY */
863  int k; /* UDSD by AY */
864  char str[BUFFSIZE];
865  int savecolor;
866 
867  /* Track 0 at left edge, closest to "owning" clb. */
868 
869  x = tile_x[rr_node[inode].xlow] + tile_width + 1. + itrack;
870  y1 = tile_y[rr_node[inode].ylow];
871  y2 = tile_y[rr_node[inode].yhigh] + tile_width;
872  x_rr_node_left[inode] = x - line_fuz;
873  x_rr_node_right[inode] = x + line_fuz;
874  y_rr_node_bottom[inode] = y1;
875  y_rr_node_top[inode] = y2;
876  if (rr_node_color[inode] != BLACK) {
877  savecolor = getcolor();
878  setcolor(rr_node_color[inode]);
879  setlinewidth(3);
880  drawline(x, y1, x, y2);
881  setlinewidth(0);
882  setcolor(savecolor);
883  } else {
884  drawline(x, y1, x, y2);
885  }
886 
887  /* UDSD by AY Start */
888  x1 = x - 0.25;
889  x2 = x + 0.25;
890  if (rr_node[inode].direction == INC_DIRECTION) {
891  setlinewidth(2);
892  setcolor(YELLOW);
893  drawline(x1, y1, x2, y1);
894 
895  /* UDSD Modifications by WMF Begin */
896  setcolor(BLACK);
897  sprintf(str, "%d", rr_node[inode].fan_in);
898  drawtext(x, y1, str, 5);
899  setcolor(BLACK);
900  /* UDSD Modifications by WMF End */
901 
902  setlinewidth(0);
903  draw_triangle_along_line(x, y2 - 0.15, x, x, y1, y2);
905  for (k = rr_node[inode].ylow; k < rr_node[inode].yhigh; k++) {
906  y2 = tile_y[k] + tile_width;
907  draw_triangle_along_line(x, y2 - 0.15, x, x, y1, y2);
908  y2 = tile_y[k + 1];
909  draw_triangle_along_line(x, y2 + 0.15, x, x, y1, y2);
910  }
911  setcolor(BLACK);
912  } else if (rr_node[inode].direction == DEC_DIRECTION) {
913  setlinewidth(2);
914  setcolor(YELLOW);
915  drawline(x1, y2, x2, y2);
916 
917  /* UDSD Modifications by WMF Begin */
918  setcolor(BLACK);
919  sprintf(str, "%d", rr_node[inode].fan_in);
920  drawtext(x, y2, str, 5);
921  setcolor(BLACK);
922  /* UDSD Modifications by WMF End */
923 
924  setlinewidth(0);
925  draw_triangle_along_line(x, y1 + 0.15, x, x, y2, y1);
927  for (k = rr_node[inode].yhigh; k > rr_node[inode].ylow; k--) {
928  y1 = tile_y[k];
929  draw_triangle_along_line(x, y1 + 0.15, x, x, y2, y1);
930  y1 = tile_y[k - 1] + tile_width;
931  draw_triangle_along_line(x, y1 - 0.15, x, x, y2, y1);
932  }
933  setcolor(BLACK);
934  }
935  /* UDSD by AY End */
936 }
937 
938 static void draw_rr_edges(int inode) {
939 
940  /* Draws all the edges that the user wants shown between inode and what it *
941  * connects to. inode is assumed to be a CHANX, CHANY, or OPIN. */
942 
943  t_rr_type from_type, to_type;
944  int iedge, to_node, from_ptc_num, to_ptc_num;
945  short switch_type;
946  boolean defective = FALSE;
947 
948  from_type = rr_node[inode].type;
949 
951  || (draw_rr_toggle == DRAW_NODES_AND_SBOX_RR && from_type == OPIN)) {
952  return; /* Nothing to draw. */
953  }
954 
955  from_ptc_num = rr_node[inode].ptc_num;
956 
957  for (iedge = 0; iedge < rr_node[inode].num_edges; iedge++) {
958  to_node = rr_node[inode].edges[iedge];
959  to_type = rr_node[to_node].type;
960  to_ptc_num = rr_node[to_node].ptc_num;
961 
962  if (show_defects)
963  defective = (boolean)(switch_inf[rr_node[inode].switches[iedge]].R < 0);
964  switch (from_type) {
965 
966  case OPIN:
967  switch (to_type) {
968  case CHANX:
969  case CHANY:
970  if (show_defects) {
971  if (defective)
972  setcolor(RED);
973  else
974  setcolor(BLACK);
975  } else
976  setcolor(RED);
977  draw_pin_to_chan_edge(inode, to_node);
978  break;
979  case IPIN:
980  setcolor(RED);
981  draw_pin_to_pin(inode, to_node);
982  break;
983  default:
984  vpr_printf(TIO_MESSAGE_ERROR, "in draw_rr_edges: node %d (type: %d) connects to node %d (type: %d).\n",
985  inode, from_type, to_node, to_type);
986  exit(1);
987  break;
988  }
989  break;
990 
991  case CHANX: /* from_type */
992  switch (to_type) {
993  case IPIN:
995  break;
996  }
997 
998  if (show_defects) {
999  if (defective)
1000  setcolor(RED);
1001  else
1002  setcolor(BLACK);
1003  } else
1004  setcolor(BLUE);
1005  draw_pin_to_chan_edge(to_node, inode);
1006  break;
1007 
1008  case CHANX:
1009  if (show_defects) {
1010  if (defective)
1011  setcolor(RED);
1012  else
1013  setcolor(BLACK);
1014  } else
1016  switch_type = rr_node[inode].switches[iedge];
1017  draw_chanx_to_chanx_edge(inode, from_ptc_num, to_node,
1018  to_ptc_num, switch_type);
1019  break;
1020 
1021  case CHANY:
1022  if (show_defects) {
1023  if (defective)
1024  setcolor(RED);
1025  else
1026  setcolor(BLACK);
1027  } else
1029  switch_type = rr_node[inode].switches[iedge];
1030  draw_chanx_to_chany_edge(inode, from_ptc_num, to_node,
1031  to_ptc_num, FROM_X_TO_Y, switch_type);
1032  break;
1033 
1034  default:
1035  vpr_printf(TIO_MESSAGE_ERROR, "in draw_rr_edges: node %d (type: %d) connects to node %d (type: %d).\n",
1036  inode, from_type, to_node, to_type);
1037  exit(1);
1038  break;
1039  }
1040  break;
1041 
1042  case CHANY: /* from_type */
1043  switch (to_type) {
1044  case IPIN:
1046  break;
1047  }
1048 
1049  if (show_defects) {
1050  if (defective)
1051  setcolor(RED);
1052  else
1053  setcolor(BLACK);
1054  } else
1055  setcolor(BLUE);
1056  draw_pin_to_chan_edge(to_node, inode);
1057  break;
1058 
1059  case CHANX:
1060  if (show_defects) {
1061  if (defective)
1062  setcolor(RED);
1063  else
1064  setcolor(BLACK);
1065  } else
1067  switch_type = rr_node[inode].switches[iedge];
1068  draw_chanx_to_chany_edge(to_node, to_ptc_num, inode,
1069  from_ptc_num, FROM_Y_TO_X, switch_type);
1070  break;
1071 
1072  case CHANY:
1073  if (show_defects) {
1074  if (defective)
1075  setcolor(RED);
1076  else
1077  setcolor(BLACK);
1078  } else
1080  switch_type = rr_node[inode].switches[iedge];
1081  draw_chany_to_chany_edge(inode, from_ptc_num, to_node,
1082  to_ptc_num, switch_type);
1083  break;
1084 
1085  default:
1086  vpr_printf(TIO_MESSAGE_ERROR, "in draw_rr_edges: node %d (type: %d) connects to node %d (type: %d).\n",
1087  inode, from_type, to_node, to_type);
1088  exit(1);
1089  break;
1090  }
1091  break;
1092 
1093  default: /* from_type */
1094  vpr_printf(TIO_MESSAGE_ERROR, "draw_rr_edges called with node %d of type %d.\n",
1095  inode, from_type);
1096  exit(1);
1097  break;
1098  }
1099  } /* End of for each edge loop */
1100 }
1101 
1102 static void draw_x(float x, float y, float size) {
1103 
1104  /* Draws an X centered at (x,y). The width and height of the X are each *
1105  * 2 * size. */
1106 
1107  drawline(x - size, y + size, x + size, y - size);
1108  drawline(x - size, y - size, x + size, y + size);
1109 }
1110 
1111 /* UDSD Modifications by WMF: Thank God Andy fixed this. */
1112 static void draw_chanx_to_chany_edge(int chanx_node, int chanx_track,
1113  int chany_node, int chany_track, enum e_edge_dir edge_dir,
1114  short switch_type) {
1115 
1116  /* Draws an edge (SBOX connection) between an x-directed channel and a *
1117  * y-directed channel. */
1118 
1119  float x1, y1, x2, y2;
1120  int chanx_y, chany_x, chanx_xlow, chany_ylow;
1121 
1122  chanx_y = rr_node[chanx_node].ylow;
1123  chanx_xlow = rr_node[chanx_node].xlow;
1124  chany_x = rr_node[chany_node].xlow;
1125  chany_ylow = rr_node[chany_node].ylow;
1126 
1127  /* (x1,y1): point on CHANX segment, (x2,y2): point on CHANY segment. */
1128 
1129  y1 = tile_y[chanx_y] + tile_width + 1. + chanx_track;
1130  x2 = tile_x[chany_x] + tile_width + 1. + chany_track;
1131 
1132  if (chanx_xlow <= chany_x) { /* Can draw connection going right */
1133  x1 = tile_x[chany_x] + tile_width;
1134  /* UDSD by AY Start */
1135  if (rr_node[chanx_node].direction != BI_DIRECTION) {
1136  if (edge_dir == FROM_X_TO_Y) {
1137  if ((chanx_track % 2) == 1) { /* UDSD Modifications by WMF: If dec wire, then going left */
1138  x1 = tile_x[chany_x + 1];
1139  }
1140  }
1141  }
1142  /* UDSD by AY End */
1143  } else { /* Must draw connection going left. */
1144  x1 = tile_x[chanx_xlow];
1145  }
1146 
1147  if (chany_ylow <= chanx_y) { /* Can draw connection going up. */
1148  y2 = tile_y[chanx_y] + tile_width;
1149  /* UDSD by AY Start */
1150  if (rr_node[chany_node].direction != BI_DIRECTION) {
1151  if (edge_dir == FROM_Y_TO_X) {
1152  if ((chany_track % 2) == 1) { /* UDSD Modifications by WMF: If dec wire, then going down */
1153  y2 = tile_y[chanx_y + 1];
1154  }
1155  }
1156  }
1157  /* UDSD by AY End */
1158  } else { /* Must draw connection going down. */
1159  y2 = tile_y[chany_ylow];
1160  }
1161 
1162  drawline(x1, y1, x2, y2);
1163 
1164  if (draw_rr_toggle != DRAW_ALL_RR)
1165  return;
1166 
1167  if (edge_dir == FROM_X_TO_Y)
1168  draw_rr_switch(x1, y1, x2, y2, switch_inf[switch_type].buffered);
1169  else
1170  draw_rr_switch(x2, y2, x1, y1, switch_inf[switch_type].buffered);
1171 }
1172 
1173 static void draw_chanx_to_chanx_edge(int from_node, int from_track, int to_node,
1174  int to_track, short switch_type) {
1175 
1176  /* Draws a connection between two x-channel segments. Passing in the track *
1177  * numbers allows this routine to be used for both rr_graph and routing *
1178  * drawing. */
1179 
1180  float x1, x2, y1, y2;
1181  int from_y, to_y, from_xlow, to_xlow, from_xhigh, to_xhigh;
1182 
1183  from_y = rr_node[from_node].ylow;
1184  from_xlow = rr_node[from_node].xlow;
1185  from_xhigh = rr_node[from_node].xhigh;
1186  to_y = rr_node[to_node].ylow;
1187  to_xlow = rr_node[to_node].xlow;
1188  to_xhigh = rr_node[to_node].xhigh;
1189 
1190  /* (x1, y1) point on from_node, (x2, y2) point on to_node. */
1191 
1192  y1 = tile_y[from_y] + tile_width + 1 + from_track;
1193  y2 = tile_y[to_y] + tile_width + 1 + to_track;
1194 
1195  if (to_xhigh < from_xlow) { /* From right to left */
1196  /* UDSD Note by WMF: could never happen for INC wires, unless U-turn. For DEC
1197  * wires this handles well */
1198  x1 = tile_x[from_xlow];
1199  x2 = tile_x[to_xhigh] + tile_width;
1200  } else if (to_xlow > from_xhigh) { /* From left to right */
1201  /* UDSD Note by WMF: could never happen for DEC wires, unless U-turn. For INC
1202  * wires this handles well */
1203  x1 = tile_x[from_xhigh] + tile_width;
1204  x2 = tile_x[to_xlow];
1205  }
1206 
1207  /* Segments overlap in the channel. Figure out best way to draw. Have to *
1208  * make sure the drawing is symmetric in the from rr and to rr so the edges *
1209  * will be drawn on top of each other for bidirectional connections. */
1210 
1211  /* UDSD Modification by WMF Begin */
1212  else {
1213  if (rr_node[to_node].direction != BI_DIRECTION) {
1214  /* must connect to to_node's wire beginning at x2 */
1215  if (to_track % 2 == 0) { /* INC wire starts at leftmost edge */
1216  assert(from_xlow < to_xlow);
1217  x2 = tile_x[to_xlow];
1218  /* since no U-turns from_track must be INC as well */
1219  x1 = tile_x[to_xlow - 1] + tile_width;
1220  } else { /* DEC wire starts at rightmost edge */
1221  assert(from_xhigh > to_xhigh);
1222  x2 = tile_x[to_xhigh] + tile_width;
1223  x1 = tile_x[to_xhigh + 1];
1224  }
1225  } else {
1226  if (to_xlow < from_xlow) { /* Draw from left edge of one to other */
1227  x1 = tile_x[from_xlow];
1228  x2 = tile_x[from_xlow - 1] + tile_width;
1229  } else if (from_xlow < to_xlow) {
1230  x1 = tile_x[to_xlow - 1] + tile_width;
1231  x2 = tile_x[to_xlow];
1232  } /* The following then is executed when from_xlow == to_xlow */
1233  else if (to_xhigh > from_xhigh) { /* Draw from right edge of one to other */
1234  x1 = tile_x[from_xhigh] + tile_width;
1235  x2 = tile_x[from_xhigh + 1];
1236  } else if (from_xhigh > to_xhigh) {
1237  x1 = tile_x[to_xhigh + 1];
1238  x2 = tile_x[to_xhigh] + tile_width;
1239  } else { /* Complete overlap: start and end both align. Draw outside the sbox */
1240  x1 = tile_x[from_xlow];
1241  x2 = tile_x[from_xlow] + tile_width;
1242  }
1243  }
1244  }
1245  /* UDSD Modification by WMF End */
1246  drawline(x1, y1, x2, y2);
1247 
1248  if (draw_rr_toggle == DRAW_ALL_RR)
1249  draw_rr_switch(x1, y1, x2, y2, switch_inf[switch_type].buffered);
1250 }
1251 
1252 static void draw_chany_to_chany_edge(int from_node, int from_track, int to_node,
1253  int to_track, short switch_type) {
1254 
1255  /* Draws a connection between two y-channel segments. Passing in the track *
1256  * numbers allows this routine to be used for both rr_graph and routing *
1257  * drawing. */
1258 
1259  float x1, x2, y1, y2;
1260  int from_x, to_x, from_ylow, to_ylow, from_yhigh, to_yhigh;
1261 
1262  from_x = rr_node[from_node].xlow;
1263  from_ylow = rr_node[from_node].ylow;
1264  from_yhigh = rr_node[from_node].yhigh;
1265  to_x = rr_node[to_node].xlow;
1266  to_ylow = rr_node[to_node].ylow;
1267  to_yhigh = rr_node[to_node].yhigh;
1268 
1269  /* (x1, y1) point on from_node, (x2, y2) point on to_node. */
1270 
1271  x1 = tile_x[from_x] + tile_width + 1 + from_track;
1272  x2 = tile_x[to_x] + tile_width + 1 + to_track;
1273 
1274  if (to_yhigh < from_ylow) { /* From upper to lower */
1275  y1 = tile_y[from_ylow];
1276  y2 = tile_y[to_yhigh] + tile_width;
1277  } else if (to_ylow > from_yhigh) { /* From lower to upper */
1278  y1 = tile_y[from_yhigh] + tile_width;
1279  y2 = tile_y[to_ylow];
1280  }
1281 
1282  /* Segments overlap in the channel. Figure out best way to draw. Have to *
1283  * make sure the drawing is symmetric in the from rr and to rr so the edges *
1284  * will be drawn on top of each other for bidirectional connections. */
1285 
1286  /* UDSD Modification by WMF Begin */
1287  else {
1288  if (rr_node[to_node].direction != BI_DIRECTION) {
1289  if (to_track % 2 == 0) { /* INC wire starts at bottom edge */
1290  assert(from_ylow < to_ylow);
1291  y2 = tile_y[to_ylow];
1292  /* since no U-turns from_track must be INC as well */
1293  y1 = tile_y[to_ylow - 1] + tile_width;
1294  } else { /* DEC wire starts at top edge */
1295  if (!(from_yhigh > to_yhigh)) {
1296  vpr_printf(TIO_MESSAGE_INFO, "from_yhigh (%d) !> to_yhigh (%d).\n",
1297  from_yhigh, to_yhigh);
1298  vpr_printf(TIO_MESSAGE_INFO, "from is (%d, %d) to (%d, %d) track %d.\n",
1299  rr_node[from_node].xhigh, rr_node[from_node].yhigh,
1300  rr_node[from_node].xlow, rr_node[from_node].ylow,
1301  rr_node[from_node].ptc_num);
1302  vpr_printf(TIO_MESSAGE_INFO, "to is (%d, %d) to (%d, %d) track %d.\n",
1303  rr_node[to_node].xhigh, rr_node[to_node].yhigh,
1304  rr_node[to_node].xlow, rr_node[to_node].ylow,
1305  rr_node[to_node].ptc_num);
1306  exit(1);
1307  }
1308  y2 = tile_y[to_yhigh] + tile_width;
1309  y1 = tile_y[to_yhigh + 1];
1310  }
1311  } else {
1312  if (to_ylow < from_ylow) { /* Draw from bottom edge of one to other. */
1313  y1 = tile_y[from_ylow];
1314  y2 = tile_y[from_ylow - 1] + tile_width;
1315  } else if (from_ylow < to_ylow) {
1316  y1 = tile_y[to_ylow - 1] + tile_width;
1317  y2 = tile_y[to_ylow];
1318  } else if (to_yhigh > from_yhigh) { /* Draw from top edge of one to other. */
1319  y1 = tile_y[from_yhigh] + tile_width;
1320  y2 = tile_y[from_yhigh + 1];
1321  } else if (from_yhigh > to_yhigh) {
1322  y1 = tile_y[to_yhigh + 1];
1323  y2 = tile_y[to_yhigh] + tile_width;
1324  } else { /* Complete overlap: start and end both align. Draw outside the sbox */
1325  y1 = tile_y[from_ylow];
1326  y2 = tile_y[from_ylow] + tile_width;
1327  }
1328  }
1329  }
1330  /* UDSD Modification by WMF End */
1331  drawline(x1, y1, x2, y2);
1332 
1333  if (draw_rr_toggle == DRAW_ALL_RR)
1334  draw_rr_switch(x1, y1, x2, y2, switch_inf[switch_type].buffered);
1335 }
1336 
1337 static void draw_rr_switch(float from_x, float from_y, float to_x, float to_y,
1338  boolean buffered) {
1339 
1340  /* Draws a buffer (triangle) or pass transistor (circle) on the edge *
1341  * connecting from to to, depending on the status of buffered. The drawing *
1342  * is closest to the from_node, since it reflects the switch type of from. */
1343 
1344  const float switch_rad = 0.15;
1345  float magnitude, xcen, ycen, xdelta, ydelta, xbaseline, ybaseline;
1346  float xunit, yunit;
1347  t_point poly[3];
1348 
1349  xcen = from_x + (to_x - from_x) / 10.;
1350  ycen = from_y + (to_y - from_y) / 10.;
1351 
1352  if (!buffered) { /* Draw a circle for a pass transistor */
1353  drawarc(xcen, ycen, switch_rad, 0., 360.);
1354  } else { /* Buffer */
1355  xdelta = to_x - from_x;
1356  ydelta = to_y - from_y;
1357  magnitude = sqrt(xdelta * xdelta + ydelta * ydelta);
1358  xunit = xdelta / magnitude;
1359  yunit = ydelta / magnitude;
1360  poly[0].x = xcen + xunit * switch_rad;
1361  poly[0].y = ycen + yunit * switch_rad;
1362  xbaseline = xcen - xunit * switch_rad;
1363  ybaseline = ycen - yunit * switch_rad;
1364 
1365  /* Recall: perpendicular vector to the unit vector along the switch (xv, yv) *
1366  * is (yv, -xv). */
1367 
1368  poly[1].x = xbaseline + yunit * switch_rad;
1369  poly[1].y = ybaseline - xunit * switch_rad;
1370  poly[2].x = xbaseline - yunit * switch_rad;
1371  poly[2].y = ybaseline + xunit * switch_rad;
1372  fillpoly(poly, 3);
1373  }
1374 }
1375 
1376 static void draw_rr_pin(int inode, enum color_types color) {
1377 
1378  /* Draws an IPIN or OPIN rr_node. Note that the pin can appear on more *
1379  * than one side of a clb. Also note that this routine can change the *
1380  * current color to BLACK. */
1381 
1382  int ipin, i, j, iside, ioff;
1383  float xcen, ycen;
1384  char str[BUFSIZE];
1385  t_type_ptr type;
1386 
1387  i = rr_node[inode].xlow;
1388  j = rr_node[inode].ylow;
1389  ipin = rr_node[inode].ptc_num;
1390  type = grid[i][j].type;
1391  ioff = grid[i][j].offset;
1392 
1393  setcolor(color);
1394  /* TODO: This is where we can hide fringe physical pins and also identify globals (hide, color, show) */
1395  for (iside = 0; iside < 4; iside++) {
1396  if (type->pinloc[grid[i][j].offset][iside][ipin]) { /* Pin exists on this side. */
1397  get_rr_pin_draw_coords(inode, iside, ioff, &xcen, &ycen);
1398  fillrect(xcen - pin_size, ycen - pin_size, xcen + pin_size,
1399  ycen + pin_size);
1400  sprintf(str, "%d", ipin);
1401  setcolor(BLACK);
1402  drawtext(xcen, ycen, str, 2 * pin_size);
1403  setcolor(color);
1404  }
1405  }
1406 }
1407 
1408 static void get_rr_pin_draw_coords(int inode, int iside, int ioff, float *xcen,
1409  float *ycen) {
1410 
1411  /* Returns the coordinates at which the center of this pin should be drawn. *
1412  * inode gives the node number, and iside gives the side of the clb or pad *
1413  * the physical pin is on. */
1414 
1415  int i, j, k, ipin, pins_per_sub_tile;
1416  float offset, xc, yc, step;
1417  t_type_ptr type;
1418 
1419  i = rr_node[inode].xlow;
1420  j = rr_node[inode].ylow + ioff; /* Need correct tile of block */
1421 
1422  xc = tile_x[i];
1423  yc = tile_y[j];
1424 
1425  ipin = rr_node[inode].ptc_num;
1426  type = grid[i][j].type;
1427  pins_per_sub_tile = grid[i][j].type->num_pins / grid[i][j].type->capacity;
1428  k = ipin / pins_per_sub_tile;
1429 
1430  /* Since pins numbers go across all sub_tiles in a block in order
1431  * we can treat as a block box for this step */
1432 
1433  /* For each sub_tile we need and extra padding space */
1434  step = (float) (tile_width) / (float) (type->num_pins + type->capacity);
1435  offset = (ipin + k + 1) * step;
1436 
1437  switch (iside) {
1438  case LEFT:
1439  yc += offset;
1440  break;
1441 
1442  case RIGHT:
1443  xc += tile_width;
1444  yc += offset;
1445  break;
1446 
1447  case BOTTOM:
1448  xc += offset;
1449  break;
1450 
1451  case TOP:
1452  xc += offset;
1453  yc += tile_width;
1454  break;
1455 
1456  default:
1457  vpr_printf(TIO_MESSAGE_ERROR, "in get_rr_pin_draw_coords: Unexpected iside %d.\n", iside);
1458  exit(1);
1459  break;
1460  }
1461 
1462  *xcen = xc;
1463  *ycen = yc;
1464 }
1465 
1466 static void drawroute(enum e_draw_net_type draw_net_type) {
1467 
1468  /* Draws the nets in the positions fixed by the router. If draw_net_type is *
1469  * ALL_NETS, draw all the nets. If it is HIGHLIGHTED, draw only the nets *
1470  * that are not coloured black (useful for drawing over the rr_graph). */
1471 
1472  /* Next free track in each channel segment if routing is GLOBAL */
1473 
1474  static int **chanx_track = NULL; /* [1..nx][0..ny] */
1475  static int **chany_track = NULL; /* [0..nx][1..ny] */
1476 
1477  int inet, i, j, inode, prev_node, prev_track, itrack;
1478  short switch_type;
1479  struct s_trace *tptr;
1480  t_rr_type rr_type, prev_type;
1481 
1482  if (draw_route_type == GLOBAL) {
1483  /* Allocate some temporary storage if it's not already available. */
1484  if (chanx_track == NULL) {
1485  chanx_track = (int **) alloc_matrix(1, nx, 0, ny, sizeof(int));
1486  }
1487 
1488  if (chany_track == NULL) {
1489  chany_track = (int **) alloc_matrix(0, nx, 1, ny, sizeof(int));
1490  }
1491 
1492  for (i = 1; i <= nx; i++)
1493  for (j = 0; j <= ny; j++)
1494  chanx_track[i][j] = (-1);
1495 
1496  for (i = 0; i <= nx; i++)
1497  for (j = 1; j <= ny; j++)
1498  chany_track[i][j] = (-1);
1499  }
1500 
1502 
1503  /* Now draw each net, one by one. */
1504 
1505  for (inet = 0; inet < num_nets; inet++) {
1506  if (clb_net[inet].is_global) /* Don't draw global nets. */
1507  continue;
1508 
1509  if (trace_head[inet] == NULL) /* No routing. Skip. (Allows me to draw */
1510  continue; /* partially complete routes). */
1511 
1512  if (draw_net_type == HIGHLIGHTED && net_color[inet] == BLACK)
1513  continue;
1514 
1515  setcolor(net_color[inet]);
1516  tptr = trace_head[inet]; /* SOURCE to start */
1517  inode = tptr->index;
1518  rr_type = rr_node[inode].type;
1519 
1520  for (;;) {
1521  prev_node = inode;
1522  prev_type = rr_type;
1523  switch_type = tptr->iswitch;
1524  tptr = tptr->next;
1525  inode = tptr->index;
1526  rr_type = rr_node[inode].type;
1527 
1528  switch (rr_type) {
1529 
1530  case OPIN:
1531  draw_rr_pin(inode, net_color[inet]);
1532  break;
1533 
1534  case IPIN:
1535  draw_rr_pin(inode, net_color[inet]);
1536  if(rr_node[prev_node].type == OPIN) {
1537  draw_pin_to_pin(prev_node, inode);
1538  } else {
1539  prev_track = get_track_num(prev_node, chanx_track, chany_track);
1540  draw_pin_to_chan_edge(inode, prev_node);
1541  }
1542  break;
1543 
1544  case CHANX:
1545  if (draw_route_type == GLOBAL)
1546  chanx_track[rr_node[inode].xlow][rr_node[inode].ylow]++;
1547 
1548  itrack = get_track_num(inode, chanx_track, chany_track);
1549  draw_rr_chanx(inode, itrack);
1550 
1551  switch (prev_type) {
1552 
1553  case CHANX:
1554  prev_track = get_track_num(prev_node, chanx_track,
1555  chany_track);
1556  draw_chanx_to_chanx_edge(prev_node, prev_track, inode,
1557  itrack, switch_type);
1558  break;
1559 
1560  case CHANY:
1561  prev_track = get_track_num(prev_node, chanx_track,
1562  chany_track);
1563  draw_chanx_to_chany_edge(inode, itrack, prev_node,
1564  prev_track, FROM_Y_TO_X, switch_type);
1565  break;
1566 
1567  case OPIN:
1568  draw_pin_to_chan_edge(prev_node, inode);
1569  break;
1570 
1571  default:
1572  vpr_printf(TIO_MESSAGE_ERROR, "in drawroute: Unexpected connection from an rr_node of type %d to one of type %d.\n",
1573  prev_type, rr_type);
1574  exit(1);
1575  }
1576 
1577  break;
1578 
1579  case CHANY:
1580  if (draw_route_type == GLOBAL)
1581  chany_track[rr_node[inode].xlow][rr_node[inode].ylow]++;
1582 
1583  itrack = get_track_num(inode, chanx_track, chany_track);
1584  draw_rr_chany(inode, itrack);
1585 
1586  switch (prev_type) {
1587 
1588  case CHANX:
1589  prev_track = get_track_num(prev_node, chanx_track,
1590  chany_track);
1591  draw_chanx_to_chany_edge(prev_node, prev_track, inode,
1592  itrack, FROM_X_TO_Y, switch_type);
1593  break;
1594 
1595  case CHANY:
1596  prev_track = get_track_num(prev_node, chanx_track,
1597  chany_track);
1598  draw_chany_to_chany_edge(prev_node, prev_track, inode,
1599  itrack, switch_type);
1600  break;
1601 
1602  case OPIN:
1603  draw_pin_to_chan_edge(prev_node, inode);
1604 
1605  break;
1606 
1607  default:
1608  vpr_printf(TIO_MESSAGE_ERROR, "in drawroute: Unexpected connection from an rr_node of type %d to one of type %d.\n",
1609  prev_type, rr_type);
1610  exit(1);
1611  }
1612 
1613  break;
1614 
1615  default:
1616  break;
1617 
1618  }
1619 
1620  if (rr_type == SINK) { /* Skip the next segment */
1621  tptr = tptr->next;
1622  if (tptr == NULL)
1623  break;
1624  inode = tptr->index;
1625  rr_type = rr_node[inode].type;
1626  }
1627 
1628  } /* End loop over traceback. */
1629  } /* End for (each net) */
1630 }
1631 
1632 static int get_track_num(int inode, int **chanx_track, int **chany_track) {
1633 
1634  /* Returns the track number of this routing resource node. */
1635 
1636  int i, j;
1637  t_rr_type rr_type;
1638 
1639  if (draw_route_type == DETAILED)
1640  return (rr_node[inode].ptc_num);
1641 
1642  /* GLOBAL route stuff below. */
1643 
1644  rr_type = rr_node[inode].type;
1645  i = rr_node[inode].xlow; /* NB: Global rr graphs must have only unit */
1646  j = rr_node[inode].ylow; /* length channel segments. */
1647 
1648  switch (rr_type) {
1649  case CHANX:
1650  return (chanx_track[i][j]);
1651 
1652  case CHANY:
1653  return (chany_track[i][j]);
1654 
1655  default:
1656  vpr_printf(TIO_MESSAGE_ERROR, "in get_track_num: Unexpected node type %d for node %d.\n", rr_type, inode);
1657  exit(1);
1658  }
1659 }
1660 
1661 static void highlight_nets(char *message) {
1662  int inet;
1663  struct s_trace *tptr;
1664 
1665  for (inet = 0; inet < num_nets; inet++) {
1666  for (tptr = trace_head[inet]; tptr != NULL; tptr = tptr->next) {
1667  if (rr_node_color[tptr->index] != BLACK) {
1668  net_color[inet] = rr_node_color[tptr->index];
1669  sprintf(message, "%s || Net:%d %d", message, inet,
1670  trace_head[inet]->index);
1671  break;
1672  }
1673  }
1674  }
1675  update_message(message);
1676 }
1677 
1678 static void highlight_rr_nodes(float x, float y) {
1679  int inode;
1680  int hit = 0;
1681  char message[250] = "";
1682  int edge;
1683 
1684  if (draw_rr_toggle == DRAW_NO_RR && !show_nets) {
1686  drawscreen();
1687  return;
1688  }
1689 
1690  for (inode = 0; inode < num_rr_nodes; inode++) {
1691  if (x >= x_rr_node_left[inode] && x <= x_rr_node_right[inode]
1692  && y >= y_rr_node_bottom[inode] && y <= y_rr_node_top[inode]) {
1693  t_rr_type rr_type = rr_node[inode].type;
1694  int xlow = rr_node[inode].xlow;
1695  int xhigh = rr_node[inode].xhigh;
1696  int ylow = rr_node[inode].ylow;
1697  int yhigh = rr_node[inode].yhigh;
1698  int ptc_num = rr_node[inode].ptc_num;
1699  rr_node_color[inode] = MAGENTA;
1700  sprintf(message, "%s%s %d: %s (%d,%d) -> (%d,%d) track: %d",
1701  message, (hit ? " | " : ""), inode, name_type[rr_type],
1702  xlow, ylow, xhigh, yhigh, ptc_num);
1703 
1704 #ifdef DEBUG
1705  print_rr_node(stdout, rr_node, inode);
1706 #endif
1707  for (edge = 0; edge < rr_node[inode].num_edges; edge++) {
1708  if (rr_node_color[rr_node[inode].edges[edge]] == BLACK
1709  && rr_node[rr_node[inode].edges[edge]].capacity
1710  > rr_node[rr_node[inode].edges[edge]].occ)
1711  rr_node_color[rr_node[inode].edges[edge]] = GREEN;
1712  else if (rr_node_color[rr_node[inode].edges[edge]] == BLACK
1713  && rr_node[rr_node[inode].edges[edge]].capacity
1714  == rr_node[rr_node[inode].edges[edge]].occ)
1715  rr_node_color[rr_node[inode].edges[edge]] = BLUE;
1716 
1717  }
1718  hit = 1;
1719  }
1720  }
1721 
1722  if (!hit) {
1724  drawscreen();
1725  return;
1726  }
1727 
1728  if (show_nets) {
1729  highlight_nets(message);
1730  } else
1731  update_message(message);
1732  drawscreen();
1733 }
1734 
1735 static void highlight_blocks(float x, float y) {
1736 
1737  /* This routine is called when the user clicks in the graphics area. *
1738  * It determines if a clb was clicked on. If one was, it is *
1739  * highlighted in green, it's fanin nets and clbs are highlighted in *
1740  * blue and it's fanout is highlighted in red. If no clb was *
1741  * clicked on (user clicked on white space) any old highlighting is *
1742  * removed. Note that even though global nets are not drawn, their *
1743  * fanins and fanouts are highlighted when you click on a block *
1744  * attached to them. */
1745 
1746  int i, j, k, hit, bnum, ipin, netnum, fanblk;
1747  int iclass;
1748  float io_step;
1749  t_type_ptr type;
1750  char msg[BUFSIZE];
1751 
1752  deselect_all();
1753 
1754  hit = i = j = k = 0;
1755 
1756  for (i = 0; i <= (nx + 1) && !hit; i++) {
1757  if (x <= tile_x[i] + tile_width) {
1758  if (x >= tile_x[i]) {
1759  for (j = 0; j <= (ny + 1) && !hit; j++) {
1760  if (grid[i][j].offset != 0)
1761  continue;
1762  type = grid[i][j].type;
1763  if (y <= tile_y[j + type->height - 1] + tile_width) {
1764  if (y >= tile_y[j])
1765  hit = 1;
1766  }
1767  }
1768 
1769  }
1770  }
1771  }
1772  i--;
1773  j--;
1774 
1775  if (!hit) {
1776  highlight_rr_nodes(x, y);
1777  /* update_message(default_message);
1778  drawscreen(); */
1779  return;
1780  }
1781  type = grid[i][j].type;
1782  hit = 0;
1783 
1784  if (EMPTY_TYPE == type) {
1786  drawscreen();
1787  return;
1788  }
1789 
1790  /* The user selected the clb at location (i,j). */
1791  io_step = tile_width / type->capacity;
1792 
1793  if ((i < 1) || (i > nx)) /* Vertical columns of IOs */
1794  k = (int) ((y - tile_y[j]) / io_step);
1795  else
1796  k = (int) ((x - tile_x[i]) / io_step);
1797 
1798  assert(k < type->capacity);
1799  if (grid[i][j].blocks[k] == EMPTY) {
1801  drawscreen();
1802  return;
1803  }
1804  bnum = grid[i][j].blocks[k];
1805 
1806  /* Highlight fanin and fanout. */
1807 
1808  for (k = 0; k < type->num_pins; k++) { /* Each pin on a CLB */
1809  netnum = block[bnum].nets[k];
1810 
1811  if (netnum == OPEN)
1812  continue;
1813 
1814  iclass = type->pin_class[k];
1815 
1816  if (type->class_inf[iclass].type == DRIVER) { /* Fanout */
1817  net_color[netnum] = RED;
1818  for (ipin = 1; ipin <= clb_net[netnum].num_sinks; ipin++) {
1819  fanblk = clb_net[netnum].node_block[ipin];
1820  block_color[fanblk] = RED;
1821  }
1822  } else { /* This net is fanin to the block. */
1823  net_color[netnum] = BLUE;
1824  fanblk = clb_net[netnum].node_block[0]; /* DRIVER to net */
1825  block_color[fanblk] = BLUE;
1826  }
1827  }
1828 
1829  block_color[bnum] = GREEN; /* Selected block. */
1830 
1831  sprintf(msg, "Block %d (%s) at (%d, %d) selected.", bnum, block[bnum].name,
1832  i, j);
1833  update_message(msg);
1834  drawscreen(); /* Need to erase screen. */
1835 }
1836 
1837 static void deselect_all(void) {
1838  /* Sets the color of all clbs and nets to the default. */
1839 
1840  int i;
1841 
1842  /* Create some colour highlighting */
1843  for (i = 0; i < num_blocks; i++) {
1844  if (block[i].type->index < 3) {
1845  block_color[i] = LIGHTGREY;
1846  } else if (block[i].type->index < 3 + MAX_BLOCK_COLOURS) {
1847  block_color[i] = (enum color_types) (BISQUE + MAX_BLOCK_COLOURS + block[i].type->index
1848  - 3);
1849  } else {
1850  block_color[i] = (enum color_types) (BISQUE + 2 * MAX_BLOCK_COLOURS - 1);
1851  }
1852  }
1853 
1854  for (i = 0; i < num_nets; i++)
1855  net_color[i] = BLACK;
1856 
1857  for (i = 0; i < num_rr_nodes; i++)
1858  rr_node_color[i] = BLACK;
1859 }
1860 
1861 /* UDSD by AY Start */
1862 static void draw_triangle_along_line(float xend, float yend, float x1, float x2,
1863  float y1, float y2) {
1864  float switch_rad = 0.15;
1865  float xdelta, ydelta;
1866  float magnitude;
1867  float xunit, yunit;
1868  float xbaseline, ybaseline;
1869  t_point poly[3];
1870 
1871  xdelta = x2 - x1;
1872  ydelta = y2 - y1;
1873  magnitude = sqrt(xdelta * xdelta + ydelta * ydelta);
1874  xunit = xdelta / magnitude;
1875  yunit = ydelta / magnitude;
1876 
1877  poly[0].x = xend + xunit * switch_rad;
1878  poly[0].y = yend + yunit * switch_rad;
1879  xbaseline = xend - xunit * switch_rad;
1880  ybaseline = yend - yunit * switch_rad;
1881  poly[1].x = xbaseline + yunit * switch_rad;
1882  poly[1].y = ybaseline - xunit * switch_rad;
1883  poly[2].x = xbaseline - yunit * switch_rad;
1884  poly[2].y = ybaseline + xunit * switch_rad;
1885 
1886  fillpoly(poly, 3);
1887 }
1888 
1889 static void draw_pin_to_chan_edge(int pin_node, int chan_node) {
1890 
1891  /* This routine draws an edge from the pin_node to the chan_node (CHANX or *
1892  * CHANY). The connection is made to the nearest end of the track instead *
1893  * of perpundicular to the track to symbolize a single-drive connection. *
1894  * If mark_conn is TRUE, draw a box where the pin connects to the track *
1895  * (useful for drawing the rr graph) */
1896 
1897  /* TODO: Fix this for global routing, currently for detailed only */
1898 
1899  t_rr_type chan_type;
1900  int grid_x, grid_y, pin_num, chan_xlow, chan_ylow, ioff, height;
1901  float x1, x2, y1, y2;
1902  int start, end, i;
1903  int itrack;
1904  float xend, yend;
1905  float draw_pin_off;
1906  enum e_direction direction;
1907  enum e_side iside;
1908  t_type_ptr type;
1909 
1910  direction = rr_node[chan_node].direction;
1911  grid_x = rr_node[pin_node].xlow;
1912  grid_y = rr_node[pin_node].ylow;
1913  pin_num = rr_node[pin_node].ptc_num;
1914  chan_type = rr_node[chan_node].type;
1915  itrack = rr_node[chan_node].ptc_num;
1916  type = grid[grid_x][grid_y].type;
1917 
1918  ioff = grid[grid_x][grid_y].offset;
1919  /* large block begins at primary tile (offset == 0) */
1920  grid_y = grid_y - ioff;
1921  height = grid[grid_x][grid_y].type->height;
1922  chan_ylow = rr_node[chan_node].ylow;
1923  chan_xlow = rr_node[chan_node].xlow;
1924  start = -1;
1925  end = -1;
1926 
1927  switch (chan_type) {
1928 
1929  case CHANX:
1930  start = rr_node[chan_node].xlow;
1931  end = rr_node[chan_node].xhigh;
1932  if (is_opin(pin_num, type)) {
1933  if (direction == INC_DIRECTION) {
1934  end = rr_node[chan_node].xlow;
1935  } else if (direction == DEC_DIRECTION) {
1936  start = rr_node[chan_node].xhigh;
1937  }
1938  }
1939 
1940  start = std::max(start, grid_x);
1941  end = std::min(end, grid_x); /* Width is 1 always */
1942  assert(end >= start);
1943  /* Make sure we are nearby */
1944 
1945  if ((grid_y + height - 1) == chan_ylow) {
1946  iside = TOP;
1947  ioff = height - 1;
1948  draw_pin_off = pin_size;
1949  } else {
1950  assert((grid_y - 1) == chan_ylow);
1951 
1952  iside = BOTTOM;
1953  ioff = 0;
1954  draw_pin_off = -pin_size;
1955  }
1956  assert(grid[grid_x][grid_y].type->pinloc[ioff][iside][pin_num]);
1957 
1958  get_rr_pin_draw_coords(pin_node, iside, ioff, &x1, &y1);
1959  y1 += draw_pin_off;
1960 
1961  y2 = tile_y[rr_node[chan_node].ylow] + tile_width + 1. + itrack;
1962  x2 = x1;
1963  if (is_opin(pin_num, type)) {
1964  if (direction == INC_DIRECTION) {
1965  x2 = tile_x[rr_node[chan_node].xlow];
1966  } else if (direction == DEC_DIRECTION) {
1967  x2 = tile_x[rr_node[chan_node].xhigh] + tile_width;
1968  }
1969  }
1970  break;
1971 
1972  case CHANY:
1973  start = rr_node[chan_node].ylow;
1974  end = rr_node[chan_node].yhigh;
1975  if (is_opin(pin_num, type)) {
1976  if (direction == INC_DIRECTION) {
1977  end = rr_node[chan_node].ylow;
1978  } else if (direction == DEC_DIRECTION) {
1979  start = rr_node[chan_node].yhigh;
1980  }
1981  }
1982 
1983  start = std::max(start, grid_y);
1984  end = std::min(end, (grid_y + height - 1)); /* Width is 1 always */
1985  assert(end >= start);
1986  /* Make sure we are nearby */
1987 
1988  if ((grid_x) == chan_xlow) {
1989  iside = RIGHT;
1990  draw_pin_off = pin_size;
1991  } else {
1992  assert((grid_x - 1) == chan_xlow);
1993  iside = LEFT;
1994  draw_pin_off = -pin_size;
1995  }
1996  for (i = start; i <= end; i++) {
1997  ioff = i - grid_y;
1998  assert(ioff >= 0 && ioff < type->height);
1999  /* Once we find the location, break out, this will leave ioff pointing
2000  * to the correct offset. If an offset is not found, the assertion after
2001  * this will fail. With the correct routing graph, the assertion will not
2002  * be triggered. This also takes care of connecting a wire once to multiple
2003  * physical pins on the same side. */
2004  if (grid[grid_x][grid_y].type->pinloc[ioff][iside][pin_num]) {
2005  break;
2006  }
2007  }
2008  assert(grid[grid_x][grid_y].type->pinloc[ioff][iside][pin_num]);
2009 
2010  get_rr_pin_draw_coords(pin_node, iside, ioff, &x1, &y1);
2011  x1 += draw_pin_off;
2012 
2013  x2 = tile_x[chan_xlow] + tile_width + 1 + itrack;
2014  y2 = y1;
2015  if (is_opin(pin_num, type)) {
2016  if (direction == INC_DIRECTION) {
2017  y2 = tile_y[rr_node[chan_node].ylow];
2018  } else if (direction == DEC_DIRECTION) {
2019  y2 = tile_y[rr_node[chan_node].yhigh] + tile_width;
2020  }
2021  }
2022  break;
2023 
2024  default:
2025  vpr_printf(TIO_MESSAGE_ERROR, "in draw_pin_to_chan_edge: Invalid channel node %d.\n", chan_node);
2026  exit(1);
2027  }
2028 
2029  drawline(x1, y1, x2, y2);
2030  if (direction == BI_DIRECTION || !is_opin(pin_num, type)) {
2031  draw_x(x2, y2, 0.7 * pin_size);
2032  } else {
2033  xend = x2 + (x1 - x2) / 10.;
2034  yend = y2 + (y1 - y2) / 10.;
2035  draw_triangle_along_line(xend, yend, x1, x2, y1, y2);
2036  }
2037 }
2038 
2039 static void draw_pin_to_pin(int opin_node, int ipin_node) {
2040 
2041  /* This routine draws an edge from the opin rr node to the ipin rr node */
2042  int opin_grid_x, opin_grid_y, opin_pin_num, opin;
2043  int ipin_grid_x, ipin_grid_y, ipin_pin_num, ipin;
2044  int ofs, pin_ofs;
2045  boolean found;
2046  float x1, x2, y1, y2;
2047  float xend, yend;
2048  enum e_side iside, pin_side;
2049  t_type_ptr type;
2050 
2051  assert(rr_node[opin_node].type == OPIN);
2052  assert(rr_node[ipin_node].type == IPIN);
2053  iside = (enum e_side)0;
2054  x1 = y1 = x2 = y2 = 0;
2055  pin_ofs = 0;
2056  pin_side = TOP;
2057 
2058  /* get opin coordinate */
2059  opin_grid_x = rr_node[opin_node].xlow;
2060  opin_grid_y = rr_node[opin_node].ylow;
2061  opin_grid_y = opin_grid_y - grid[opin_grid_x][opin_grid_y].offset;
2062  opin = rr_node[opin_node].ptc_num;
2063  opin_pin_num = rr_node[opin_node].ptc_num;
2064  type = grid[opin_grid_x][opin_grid_y].type;
2065 
2066  found = FALSE;
2067  for (ofs = 0; ofs < type->height && !found; ++ofs) {
2068  for (iside = (enum e_side)0; iside < 4 && !found; iside = (enum e_side)(iside + 1)) {
2069  /* Find first location of pin */
2070  if (1 == type->pinloc[ofs][iside][opin]) {
2071  pin_ofs = ofs;
2072  pin_side = iside;
2073  found = TRUE;
2074  }
2075  }
2076  }
2077  assert(found);
2078  get_rr_pin_draw_coords(opin_node, pin_side, pin_ofs, &x1, &y1);
2079 
2080 
2081  /* get ipin coordinate */
2082  ipin_grid_x = rr_node[ipin_node].xlow;
2083  ipin_grid_y = rr_node[ipin_node].ylow;
2084  ipin_grid_y = ipin_grid_y - grid[ipin_grid_x][ipin_grid_y].offset;
2085  ipin = rr_node[ipin_node].ptc_num;
2086  ipin_pin_num = rr_node[ipin_node].ptc_num;
2087  type = grid[ipin_grid_x][ipin_grid_y].type;
2088 
2089  found = FALSE;
2090  for (ofs = 0; ofs < type->height && !found; ++ofs) {
2091  for (iside = (enum e_side)0; iside < 4 && !found; iside = (enum e_side)(iside + 1)) {
2092  /* Find first location of pin */
2093  if (1 == type->pinloc[ofs][iside][ipin]) {
2094  pin_ofs = ofs;
2095  pin_side = iside;
2096  found = TRUE;
2097  }
2098  }
2099  }
2100  assert(found);
2101  get_rr_pin_draw_coords(ipin_node, pin_side, pin_ofs, &x2, &y2);
2102  drawline(x1, y1, x2, y2);
2103  xend = x2 + (x1 - x2) / 10.;
2104  yend = y2 + (y1 - y2) / 10.;
2105  draw_triangle_along_line(xend, yend, x1, x2, y1, y2);
2106 }
2107 
2108 /* UDSD by AY End */
t_type_ptr type
Definition: vpr_types.h:522
static void toggle_nets(void(*drawscreen)(void))
Definition: draw.c:250
static float * x_rr_node_right
Definition: draw.c:91
short xhigh
Definition: vpr_types.h:891
static void get_block_center(int bnum, float *x, float *y)
Definition: draw.c:624
short num_edges
Definition: vpr_types.h:901
void init_world(float x1, float y1, float x2, float y2)
Definition: graphics.c:2038
void update_screen(int priority, char *msg, enum pic_type pic_on_screen_val, boolean crit_path_button_enabled)
Definition: draw.c:156
int index
Definition: vpr_types.h:866
static float * y_rr_node_bottom
Definition: draw.c:93
int * edges
Definition: vpr_types.h:903
void ** alloc_matrix(int nrmin, int nrmax, int ncmin, int ncmax, size_t elsize)
Definition: util.c:551
static boolean show_congestion
Definition: draw.c:55
t_rr_node * rr_node
Definition: globals.c:70
boolean is_opin(int ipin, t_type_ptr type)
Definition: vpr_utils.c:148
void fillpoly(t_point *points, int npoints)
Definition: graphics.c:1881
static int gr_automode
Definition: draw.c:63
static void draw_rr(void)
Definition: draw.c:684
char * my_strncpy(char *dest, const char *src, size_t size)
Definition: util.c:35
short ptc_num
Definition: vpr_types.h:895
static void draw_rr_switch(float from_x, float from_y, float to_x, float to_y, boolean buffered)
Definition: draw.c:1337
t_type_ptr EMPTY_TYPE
Definition: globals.c:41
color_types
struct s_class * class_inf
short iswitch
Definition: vpr_types.h:867
void clearscreen(void)
Definition: graphics.c:1483
boolean
Definition: util.h:11
int data
Definition: util.h:40
short ylow
Definition: vpr_types.h:892
void drawrect(float x1, float y1, float x2, float y2)
Definition: graphics.c:1581
int x
Definition: vpr_types.h:563
int * chan_width_x
Definition: globals.c:56
static enum e_draw_rr_toggle draw_rr_toggle
Definition: draw.c:49
void get_tnode_block_and_output_net(int inode, int *iblk_ptr, int *inet_ptr)
Definition: path_delay.c:2611
static void highlight_rr_nodes(float x, float y)
Definition: draw.c:1678
e_side
static void draw_rr_chanx(int inode, int itrack)
Definition: draw.c:772
void destroy_button(const char *button_text)
Definition: graphics.c:954
enum e_direction direction
Definition: vpr_types.h:909
int num_nets
Definition: globals.c:27
static void get_rr_pin_draw_coords(int inode, int iside, int ioff, float *xcen, float *ycen)
Definition: draw.c:1408
int * node_block
Definition: vpr_types.h:507
int * chan_width_y
Definition: globals.c:57
static void draw_triangle_along_line(float xend, float yend, float x1, float x2, float y1, float y2)
Definition: draw.c:1862
t_linked_int * allocate_and_load_critical_path(void)
Definition: path_delay.c:2522
static int get_track_num(int inode, int **chanx_track, int **chany_track)
Definition: draw.c:1632
t_type_ptr type
Definition: vpr_types.h:561
static void drawnets(void)
Definition: draw.c:589
static enum e_route_type draw_route_type
Definition: draw.c:51
#define BUFSIZE
Definition: graphics.c:184
static float * tile_y
Definition: draw.c:68
int num_blocks
Definition: globals.c:30
static float pin_size
Definition: draw.c:76
static void toggle_rr(void(*drawscreen)(void))
Definition: draw.c:264
static const char * name_type[]
Definition: draw.c:87
Definition: util.h:12
Definition: draw.c:33
void drawline(float x1, float y1, float x2, float y2)
Definition: graphics.c:1539
e_edge_dir
Definition: draw.c:36
static void drawscreen(void)
Definition: draw.c:212
int y
Definition: vpr_types.h:564
static void highlight_crit_path(void(*drawscreen_ptr)(void))
Definition: draw.c:314
#define min(a, b)
Definition: graphics.c:174
static char default_message[BUFSIZE]
Definition: draw.c:61
void create_button(const char *prev_button_text, const char *button_text, void(*button_func)(void(*drawscreen)(void)))
Definition: graphics.c:881
void drawtext(float xc, float yc, const char *text, float boundx)
Definition: graphics.c:1952
static float line_fuz
Definition: draw.c:86
#define EMPTY
Definition: vpr_types.h:90
void fillrect(float x1, float y1, float x2, float y2)
Definition: graphics.c:1643
void init_draw_coords(float width_val)
Definition: draw.c:430
static void deselect_all(void)
Definition: draw.c:1837
static void draw_chany_to_chany_edge(int from_node, int from_track, int to_node, int to_track, short switch_type)
Definition: draw.c:1252
struct s_trace * next
Definition: vpr_types.h:870
static void * my_malloc(int ibytes)
Definition: graphics.c:499
static float tile_width
Definition: draw.c:76
static void draw_pin_to_chan_edge(int pin_node, int chan_node)
Definition: draw.c:1889
boolean * is_global
static void redraw_screen(void)
Definition: draw.c:222
e_draw_net_type
Definition: draw.c:32
#define max(a, b)
Definition: graphics.c:171
static void draw_rr_chany(int inode, int itrack)
Definition: draw.c:855
struct s_block * block
Definition: globals.c:31
void free_draw_structs(void)
Definition: draw.c:400
void setfontsize(int pointsize)
Definition: graphics.c:796
struct s_net * clb_net
Definition: globals.c:28
static enum color_types * net_color
Definition: draw.c:81
int num_rr_nodes
Definition: globals.c:69
int nx
Definition: globals.c:46
static void draw_chanx_to_chany_edge(int chanx_node, int chanx_track, int chany_node, int chany_track, enum e_edge_dir edge_dir, short switch_type)
Definition: draw.c:1112
pic_type
Definition: vpr_types.h:462
void drawarc(float xc, float yc, float rad, float startang, float angextent)
Definition: graphics.c:1787
void print_rr_node(FILE *fp, t_rr_node *L_rr_node, int inode)
Definition: rr_graph.c:1814
void free_int_list(t_linked_int **int_list_head_ptr)
Definition: util.c:341
static boolean show_defects
Definition: draw.c:57
struct s_trace ** trace_head
Definition: globals.c:64
e_direction
Definition: vpr_types.h:798
static void draw_x(float x, float y, float size)
Definition: draw.c:1102
static void toggle_congestion(void(*drawscreen)(void))
Definition: draw.c:287
struct s_switch_inf * switch_inf
Definition: globals.c:83
void setlinewidth(int linewidth)
Definition: graphics.c:743
int getcolor()
Definition: graphics.c:647
static enum color_types * rr_node_color
Definition: draw.c:94
static void toggle_defects(void(*drawscreen)(void))
Definition: draw.c:281
static void draw_pin_to_pin(int opin, int ipin)
Definition: draw.c:2039
static enum pic_type pic_on_screen
Definition: draw.c:66
void event_loop(void(*act_on_mousebutton)(float x, float y), void(*act_on_mousemove)(float x, float y), void(*act_on_keypress)(char key_pressed), void(*drawscreen)(void))
Definition: graphics.c:1352
static void draw_rr_pin(int inode, enum color_types color)
Definition: draw.c:1376
struct s_grid_tile ** grid
Definition: globals.c:59
int * blocks
Definition: vpr_types.h:525
short yhigh
Definition: vpr_types.h:893
enum e_rr_type t_rr_type
void setlinestyle(int linestyle)
Definition: graphics.c:697
int num_types
Definition: globals.c:37
short * switches
Definition: vpr_types.h:904
static void * my_realloc(void *memblk, int ibytes)
Definition: graphics.c:512
void set_graphics_state(boolean show_graphics_val, int gr_automode_val, enum e_route_type route_type)
Definition: draw.c:144
#define MAX_BLOCK_COLOURS
Definition: draw.c:21
static void drawplace(void)
Definition: draw.c:487
static boolean show_nets
Definition: draw.c:43
static float * tile_x
Definition: draw.c:68
static void draw_chanx_to_chanx_edge(int from_node, int from_track, int to_node, int to_track, short switch_type)
Definition: draw.c:1173
static void draw_rr_edges(int from_node)
Definition: draw.c:938
static float * x_rr_node_left
Definition: draw.c:90
short xlow
Definition: vpr_types.h:890
Definition: slre.c:50
int * nets
Definition: vpr_types.h:562
void alloc_draw_structs(void)
Definition: draw.c:376
struct s_linked_int * next
Definition: util.h:41
int z
Definition: vpr_types.h:565
static void drawroute(enum e_draw_net_type draw_net_type)
Definition: draw.c:1466
struct s_type_descriptor * type_descriptors
Definition: globals.c:38
enum e_pin_type type
void flushinput(void)
Definition: graphics.c:2027
static void highlight_nets(char *message)
Definition: draw.c:1661
e_route_type
Definition: vpr_types.h:682
void update_message(const char *msg)
Definition: graphics.c:2113
static int old_num_rr_nodes
Definition: draw.c:95
e_draw_rr_toggle
Definition: draw.c:23
int ny
Definition: globals.c:47
messagelogger vpr_printf
Definition: util.c:17
int num_sinks
Definition: vpr_types.h:506
static enum color_types * block_color
Definition: draw.c:81
static float * y_rr_node_top
Definition: draw.c:92
static void highlight_blocks(float x, float y)
Definition: draw.c:1735
t_rr_type type
Definition: vpr_types.h:902
Definition: util.h:12
static void draw_congestion(void)
Definition: draw.c:651
void setcolor(int cindex)
Definition: graphics.c:619
static boolean show_graphics
Definition: draw.c:59