00001 #include <stdio.h>
00002 #include <string.h>
00003 #include <math.h>
00004 #include "util.h"
00005 #include "vpr_types.h"
00006 #include "vpr_utils.h"
00007 #include "globals.h"
00008 #include "graphics.h"
00009 #include "path_delay.h"
00010 #include "draw.h"
00011 #include <assert.h>
00012
00013
00014 #define MAX_BLOCK_COLOURS 5
00015
00016 enum e_draw_rr_toggle
00017 {
00018 DRAW_NO_RR = 0,
00019 DRAW_ALL_RR,
00020 DRAW_ALL_BUT_BUFFERS_RR,
00021 DRAW_NODES_AND_SBOX_RR,
00022 DRAW_NODES_RR,
00023 DRAW_RR_TOGGLE_MAX
00024 };
00025
00026 enum e_draw_net_type
00027 { ALL_NETS, HIGHLIGHTED };
00028
00029 enum e_edge_dir
00030 { FROM_X_TO_Y, FROM_Y_TO_X };
00031
00032
00033
00034
00035 static boolean show_nets = FALSE;
00036
00037
00038
00039
00040
00041 static enum e_draw_rr_toggle draw_rr_toggle = DRAW_NO_RR;
00042
00043 static enum e_route_type draw_route_type;
00044
00045
00046
00047 static boolean show_congestion = FALSE;
00048
00049 static boolean show_graphics;
00050
00051 static char default_message[BUFSIZE];
00052
00053 static int gr_automode;
00054
00055
00056 static enum pic_type pic_on_screen = NO_PICTURE;
00057
00058 static float *tile_x, *tile_y;
00059
00060
00061
00062
00063
00064
00065
00066
00067 static float tile_width, pin_size;
00068
00069
00070
00071
00072 static enum color_types *net_color, *block_color;
00073
00074
00075
00076
00077
00078
00079
00080 static void toggle_nets(void (*drawscreen) (void));
00081 static void toggle_rr(void (*drawscreen) (void));
00082 static void toggle_congestion(void (*drawscreen) (void));
00083 static void highlight_crit_path(void (*drawscreen_ptr) (void));
00084
00085 static void drawscreen(void);
00086 static void redraw_screen(void);
00087 static void drawplace(void);
00088 static void drawnets(void);
00089 static void drawroute(enum e_draw_net_type draw_net_type);
00090 static void draw_congestion(void);
00091
00092 static void highlight_blocks(float x,
00093 float y);
00094 static void get_block_center(int bnum,
00095 float *x,
00096 float *y);
00097 static void deselect_all(void);
00098
00099 static void draw_rr(void);
00100 static void draw_rr_edges(int from_node);
00101 static void draw_rr_pin(int inode,
00102 enum color_types color);
00103 static void draw_rr_chanx(int inode,
00104 int itrack);
00105 static void draw_rr_chany(int inode,
00106 int itrack);
00107 static void get_rr_pin_draw_coords(int inode,
00108 int iside,
00109 int ioff,
00110 float *xcen,
00111 float *ycen);
00112 static void draw_pin_to_chan_edge(int pin_node,
00113 int chan_node);
00114 static void draw_x(float x,
00115 float y,
00116 float size);
00117 static void draw_chany_to_chany_edge(int from_node,
00118 int from_track,
00119 int to_node,
00120 int to_track,
00121 short switch_type);
00122 static void draw_chanx_to_chanx_edge(int from_node,
00123 int from_track,
00124 int to_node,
00125 int to_track,
00126 short switch_type);
00127 static void draw_chanx_to_chany_edge(int chanx_node,
00128 int chanx_track,
00129 int chany_node,
00130 int chany_track,
00131 enum e_edge_dir edge_dir,
00132 short switch_type);
00133 static int get_track_num(int inode,
00134 int **chanx_track,
00135 int **chany_track);
00136 static void draw_rr_switch(float from_x,
00137 float from_y,
00138 float to_x,
00139 float to_y,
00140 boolean buffered);
00141 static void draw_triangle_along_line(float xend,
00142 float yend,
00143
00144 float x1,
00145 float x2,
00146
00147 float y1,
00148 float y2);
00149
00150
00151
00152
00153
00154 void
00155 set_graphics_state(boolean show_graphics_val,
00156 int gr_automode_val,
00157 enum e_route_type route_type)
00158 {
00159
00160
00161
00162
00163
00164 show_graphics = show_graphics_val;
00165 gr_automode = gr_automode_val;
00166 draw_route_type = route_type;
00167 }
00168
00169
00170 void
00171 update_screen(int priority,
00172 char *msg,
00173 enum pic_type pic_on_screen_val,
00174 boolean crit_path_button_enabled)
00175 {
00176
00177
00178
00179
00180
00181 if(!show_graphics)
00182 return;
00183
00184
00185
00186
00187
00188 if(pic_on_screen != pic_on_screen_val)
00189 {
00190 if(pic_on_screen_val == PLACEMENT && pic_on_screen == NO_PICTURE)
00191 {
00192 create_button("Window", "Toggle Nets", toggle_nets);
00193 }
00194 else if(pic_on_screen_val == ROUTING
00195 && pic_on_screen == PLACEMENT)
00196 {
00197 create_button("Toggle Nets", "Toggle RR", toggle_rr);
00198 create_button("Toggle RR", "Congestion",
00199 toggle_congestion);
00200
00201 if(crit_path_button_enabled)
00202 {
00203 create_button("Congestion", "Crit. Path",
00204 highlight_crit_path);
00205 }
00206 }
00207 else if(pic_on_screen_val == PLACEMENT
00208 && pic_on_screen == ROUTING)
00209 {
00210 destroy_button("Toggle RR");
00211 destroy_button("Congestion");
00212
00213 if(crit_path_button_enabled)
00214 {
00215 destroy_button("Crit. Path");
00216 }
00217 }
00218 else if(pic_on_screen_val == ROUTING
00219 && pic_on_screen == NO_PICTURE)
00220 {
00221 create_button("Window", "Toggle Nets", toggle_nets);
00222 create_button("Toggle Nets", "Toggle RR", toggle_rr);
00223 create_button("Toggle RR", "Congestion",
00224 toggle_congestion);
00225
00226 if(crit_path_button_enabled)
00227 {
00228 create_button("Congestion", "Crit. Path",
00229 highlight_crit_path);
00230 }
00231 }
00232 }
00233
00234
00235 my_strncpy(default_message, msg, BUFSIZE);
00236
00237 pic_on_screen = pic_on_screen_val;
00238 update_message(msg);
00239 drawscreen();
00240 if(priority >= gr_automode)
00241 {
00242 event_loop(highlight_blocks, drawscreen);
00243 }
00244 else
00245 {
00246 flushinput();
00247 }
00248 }
00249
00250
00251 static void
00252 drawscreen()
00253 {
00254
00255
00256
00257
00258
00259 clearscreen();
00260 redraw_screen();
00261 }
00262
00263
00264 static void
00265 redraw_screen()
00266 {
00267
00268
00269
00270
00271
00272
00273 setfontsize(20);
00274 if(pic_on_screen == PLACEMENT)
00275 {
00276 drawplace();
00277 if(show_nets)
00278 {
00279 drawnets();
00280 }
00281 }
00282 else
00283 {
00284 drawplace();
00285
00286 if(show_nets)
00287 {
00288 drawroute(ALL_NETS);
00289 }
00290 else
00291 {
00292 draw_rr();
00293 }
00294
00295 if(show_congestion)
00296 {
00297 draw_congestion();
00298 }
00299 }
00300 }
00301
00302
00303 static void
00304 toggle_nets(void (*drawscreen_ptr) (void))
00305 {
00306
00307
00308
00309
00310
00311 show_nets = !show_nets;
00312 draw_rr_toggle = DRAW_NO_RR;
00313 show_congestion = FALSE;
00314
00315 update_message(default_message);
00316 drawscreen_ptr();
00317 }
00318
00319
00320 static void
00321 toggle_rr(void (*drawscreen_ptr) (void))
00322 {
00323
00324
00325
00326
00327
00328
00329
00330
00331 draw_rr_toggle = (draw_rr_toggle + 1) % (DRAW_RR_TOGGLE_MAX);
00332 show_nets = FALSE;
00333 show_congestion = FALSE;
00334
00335 update_message(default_message);
00336 drawscreen_ptr();
00337 }
00338
00339
00340 static void
00341 toggle_congestion(void (*drawscreen_ptr) (void))
00342 {
00343
00344
00345 char msg[BUFSIZE];
00346 int inode, num_congested;
00347
00348 show_nets = FALSE;
00349 draw_rr_toggle = DRAW_NO_RR;
00350 show_congestion = !show_congestion;
00351
00352 if(!show_congestion)
00353 {
00354 update_message(default_message);
00355 }
00356 else
00357 {
00358 num_congested = 0;
00359 for(inode = 0; inode < num_rr_nodes; inode++)
00360 {
00361 if(rr_node[inode].occ > rr_node[inode].capacity)
00362 {
00363 num_congested++;
00364 }
00365 }
00366
00367 sprintf(msg, "%d routing resources are overused.", num_congested);
00368 update_message(msg);
00369 }
00370
00371 drawscreen_ptr();
00372 }
00373
00374
00375 static void
00376 highlight_crit_path(void (*drawscreen_ptr) (void))
00377 {
00378
00379
00380
00381 t_linked_int *critical_path_head, *critical_path_node;
00382 int inode, iblk, inet, num_nets_seen;
00383 static int nets_to_highlight = 1;
00384 char msg[BUFSIZE];
00385
00386 if(nets_to_highlight == 0)
00387 {
00388 nets_to_highlight = 1;
00389 deselect_all();
00390 update_message(default_message);
00391 drawscreen_ptr();
00392 return;
00393 }
00394
00395 critical_path_head = allocate_and_load_critical_path();
00396 critical_path_node = critical_path_head;
00397 num_nets_seen = 0;
00398
00399 while(critical_path_node != NULL)
00400 {
00401 inode = critical_path_node->data;
00402 get_tnode_block_and_output_net(inode, &iblk, &inet);
00403
00404 if(num_nets_seen == nets_to_highlight)
00405 {
00406 block_color[iblk] = MAGENTA;
00407 }
00408 else if(num_nets_seen == nets_to_highlight - 1)
00409 {
00410 block_color[iblk] = YELLOW;
00411 }
00412 else if(num_nets_seen < nets_to_highlight)
00413 {
00414 block_color[iblk] = DARKGREEN;
00415 }
00416
00417 if(inet != OPEN)
00418 {
00419 num_nets_seen++;
00420
00421 if(num_nets_seen < nets_to_highlight)
00422 {
00423 net_color[inet] = DARKGREEN;
00424 }
00425 else if(num_nets_seen == nets_to_highlight)
00426 {
00427 net_color[inet] = CYAN;
00428 }
00429 }
00430
00431 critical_path_node = critical_path_node->next;
00432 }
00433
00434 if(nets_to_highlight == num_nets_seen)
00435 {
00436 nets_to_highlight = 0;
00437 sprintf(msg, "All %d nets on the critical path highlighted.",
00438 num_nets_seen);
00439 }
00440 else
00441 {
00442 sprintf(msg, "First %d nets on the critical path highlighted.",
00443 nets_to_highlight);
00444 nets_to_highlight++;
00445 }
00446
00447 free_int_list(&critical_path_head);
00448
00449 update_message(msg);
00450 drawscreen_ptr();
00451 }
00452
00453
00454 void
00455 alloc_draw_structs(void)
00456 {
00457
00458
00459
00460
00461 tile_x = (float *)my_malloc((nx + 2) * sizeof(float));
00462 tile_y = (float *)my_malloc((ny + 2) * sizeof(float));
00463
00464 net_color = (enum color_types *)
00465 my_malloc(num_nets * sizeof(enum color_types));
00466
00467 block_color = (enum color_types *)
00468 my_malloc(num_blocks * sizeof(enum color_types));
00469
00470 deselect_all();
00471 }
00472
00473
00474 void
00475 init_draw_coords(float width_val)
00476 {
00477
00478
00479
00480
00481
00482 int i;
00483 int j;
00484
00485 if(!show_graphics)
00486 return;
00487
00488 tile_width = width_val;
00489 pin_size = 0.3;
00490 for(i = 0; i < num_types; ++i)
00491 {
00492 pin_size =
00493 min(pin_size,
00494 (tile_width / (4.0 * type_descriptors[i].num_pins)));
00495 }
00496
00497 j = 0;
00498 for(i = 0; i < (nx + 1); i++)
00499 {
00500 tile_x[i] = (i * tile_width) + j;
00501 j += chan_width_y[i] + 1;
00502 }
00503 tile_x[nx + 1] = ((nx + 1) * tile_width) + j;
00504
00505 j = 0;
00506 for(i = 0; i < (ny + 1); ++i)
00507 {
00508 tile_y[i] = (i * tile_width) + j;
00509 j += chan_width_x[i] + 1;
00510 }
00511 tile_y[ny + 1] = ((ny + 1) * tile_width) + j;
00512
00513 init_world(0.0,
00514 tile_y[ny + 1] + tile_width, tile_x[nx + 1] + tile_width, 0.0);
00515 }
00516
00517
00518 static void
00519 drawplace(void)
00520 {
00521
00522
00523
00524
00525 float sub_tile_step;
00526 float x1, y1, x2, y2;
00527 int i, j, k, bnum;
00528 int num_sub_tiles;
00529 int height;
00530
00531 setlinewidth(0);
00532
00533 for(i = 0; i <= (nx + 1); i++)
00534 {
00535 for(j = 0; j <= (ny + 1); j++)
00536 {
00537
00538 if(grid[i][j].offset > 0)
00539 continue;
00540
00541
00542 if(((i < 1) || (i > nx)) && ((j < 1) || (j > ny)))
00543 continue;
00544
00545 num_sub_tiles = grid[i][j].type->capacity;
00546 sub_tile_step = tile_width / num_sub_tiles;
00547 height = grid[i][j].type->height;
00548
00549 if(num_sub_tiles < 1)
00550 {
00551 setcolor(BLACK);
00552 setlinestyle(DASHED);
00553 drawrect(tile_x[i], tile_y[j],
00554 tile_x[i] + tile_width,
00555 tile_y[j] + tile_width);
00556 draw_x(tile_x[i] + (tile_width / 2),
00557 tile_y[j] + (tile_width / 2),
00558 (tile_width / 2));
00559 }
00560
00561 for(k = 0; k < num_sub_tiles; ++k)
00562 {
00563
00564 assert(height == 1 || num_sub_tiles == 1);
00565
00566 if((i < 1) || (i > nx))
00567 {
00568 x1 = tile_x[i];
00569 y1 = tile_y[j] + (k * sub_tile_step);
00570 x2 = x1 + tile_width;
00571 y2 = y1 + sub_tile_step;
00572 }
00573 else if((j < 1) || (j > ny))
00574 {
00575 x1 = tile_x[i] + (k * sub_tile_step);
00576 y1 = tile_y[j];
00577 x2 = x1 + sub_tile_step;
00578 y2 = y1 + tile_width;
00579 }
00580 else
00581 {
00582 assert(num_sub_tiles <= 1);
00583
00584 x1 = tile_x[i];
00585 y1 = tile_y[j];
00586 x2 = x1 + tile_width;
00587 y2 = tile_y[j + height - 1] + tile_width;
00588 }
00589
00590
00591 bnum = grid[i][j].blocks[k];
00592
00593
00594
00595 if(bnum != EMPTY)
00596 {
00597 setcolor(block_color[bnum]);
00598 fillrect(x1, y1, x2, y2);
00599 } else {
00600
00601 if(grid[i][j].type->index < 3) {
00602 setcolor(WHITE);
00603 } else if(grid[i][j].type->index < 3 + MAX_BLOCK_COLOURS) {
00604 setcolor(BISQUE + grid[i][j].type->index - 3);
00605 } else {
00606 setcolor(BISQUE + MAX_BLOCK_COLOURS - 1);
00607 }
00608 fillrect(x1, y1, x2, y2);
00609 }
00610
00611 setcolor(BLACK);
00612
00613 setlinestyle((EMPTY == bnum) ? DASHED : SOLID);
00614 drawrect(x1, y1, x2, y2);
00615
00616
00617 if(bnum != EMPTY)
00618 {
00619 drawtext((x1 + x2) / 2.0, (y1 + y2) / 2.0,
00620 block[bnum].name, tile_width);
00621 }
00622
00623
00624 if(grid[i][j].offset == 0) {
00625 if(i > 0 && i <= nx && j > 0 && j <= ny) {
00626 drawtext((x1 + x2) / 2.0, y1 + (tile_width / 4.0),
00627 grid[i][j].type->name, tile_width);
00628 }
00629 }
00630 }
00631 }
00632 }
00633 }
00634
00635
00636 static void
00637 drawnets(void)
00638 {
00639
00640
00641
00642
00643
00644 int inet, ipin, b1, b2;
00645 float x1, y1, x2, y2;
00646
00647 setlinestyle(SOLID);
00648 setlinewidth(0);
00649
00650
00651
00652
00653 for(inet = 0; inet < num_nets; inet++)
00654 {
00655 if(net[inet].is_global)
00656 continue;
00657
00658 setcolor(net_color[inet]);
00659 b1 = net[inet].node_block[0];
00660 get_block_center(b1, &x1, &y1);
00661
00662 for(ipin = 1; ipin < (net[inet].num_sinks + 1); ipin++)
00663 {
00664 b2 = net[inet].node_block[ipin];
00665 get_block_center(b2, &x2, &y2);
00666 drawline(x1, y1, x2, y2);
00667
00668
00669
00670
00671 }
00672 }
00673 }
00674
00675
00676 static void
00677 get_block_center(int bnum,
00678 float *x,
00679 float *y)
00680 {
00681
00682
00683
00684
00685 int i, j, k;
00686 float sub_tile_step;
00687
00688 i = block[bnum].x;
00689 j = block[bnum].y;
00690 k = block[bnum].z;
00691
00692 sub_tile_step = tile_width / block[bnum].type->capacity;
00693
00694 if((i < 1) || (i > nx))
00695 {
00696 *x = tile_x[i] + (sub_tile_step * (k + 0.5));
00697 }
00698 else
00699 {
00700 *x = tile_x[i] + (tile_width / 2.0);
00701 }
00702
00703 if((j < 1) || (j > ny))
00704 {
00705 *y = tile_y[j] + (sub_tile_step * (k + 0.5));
00706 }
00707 else
00708 {
00709 *y = tile_y[j] + (tile_width / 2.0);
00710 }
00711 }
00712
00713
00714 static void
00715 draw_congestion(void)
00716 {
00717
00718
00719
00720 int inode, itrack;
00721
00722 setcolor(RED);
00723 setlinewidth(2);
00724
00725 for(inode = 0; inode < num_rr_nodes; inode++)
00726 {
00727 if(rr_node[inode].occ > rr_node[inode].capacity)
00728 {
00729 switch (rr_node[inode].type)
00730 {
00731 case CHANX:
00732 itrack = rr_node[inode].ptc_num;
00733 draw_rr_chanx(inode, itrack);
00734 break;
00735
00736 case CHANY:
00737 itrack = rr_node[inode].ptc_num;
00738 draw_rr_chany(inode, itrack);
00739 break;
00740
00741 case IPIN:
00742 case OPIN:
00743 draw_rr_pin(inode, RED);
00744 break;
00745 }
00746 }
00747 }
00748 }
00749
00750
00751 void
00752 draw_rr(void)
00753 {
00754
00755
00756
00757
00758 int inode, itrack;
00759
00760 if(draw_rr_toggle == DRAW_NO_RR)
00761 {
00762 setlinewidth(3);
00763 drawroute(HIGHLIGHTED);
00764 setlinewidth(0);
00765 return;
00766 }
00767
00768 setlinestyle(SOLID);
00769 setlinewidth(0);
00770
00771 for(inode = 0; inode < num_rr_nodes; inode++)
00772 {
00773 switch (rr_node[inode].type)
00774 {
00775
00776 case SOURCE:
00777 case SINK:
00778 break;
00779
00780 case CHANX:
00781 setcolor(BLACK);
00782 itrack = rr_node[inode].ptc_num;
00783 draw_rr_chanx(inode, itrack);
00784 draw_rr_edges(inode);
00785 break;
00786
00787 case CHANY:
00788 setcolor(BLACK);
00789 itrack = rr_node[inode].ptc_num;
00790 draw_rr_chany(inode, itrack);
00791 draw_rr_edges(inode);
00792 break;
00793
00794 case IPIN:
00795 draw_rr_pin(inode, BLUE);
00796 break;
00797
00798 case OPIN:
00799 draw_rr_pin(inode, RED);
00800 setcolor(RED);
00801 draw_rr_edges(inode);
00802 break;
00803
00804 default:
00805 printf
00806 ("Error in draw_rr: Unexpected rr_node type: %d.\n",
00807 rr_node[inode].type);
00808 exit(1);
00809 }
00810 }
00811
00812 setlinewidth(3);
00813 drawroute(HIGHLIGHTED);
00814 setlinewidth(0);
00815 }
00816
00817
00818 static void
00819 draw_rr_chanx(int inode,
00820 int itrack)
00821 {
00822
00823
00824
00825 enum
00826 { BUFFSIZE = 80 };
00827 float x1, x2, y;
00828 float y1, y2;
00829 int k;
00830 char str[BUFFSIZE];
00831
00832
00833
00834 x1 = tile_x[rr_node[inode].xlow];
00835 x2 = tile_y[rr_node[inode].xhigh] + tile_width;
00836 y = tile_y[rr_node[inode].ylow] + tile_width + 1.0 + itrack;
00837 drawline(x1, y, x2, y);
00838
00839
00840 y1 = y - 0.25;
00841 y2 = y + 0.25;
00842
00843 if(rr_node[inode].direction == INC_DIRECTION)
00844 {
00845 setlinewidth(2);
00846 setcolor(YELLOW);
00847 drawline(x1, y1, x1, y2);
00848
00849
00850 setcolor(BLACK);
00851 sprintf(str, "%d", rr_node[inode].fan_in);
00852 drawtext(x1, y, str, 5);
00853
00854 setcolor(BLACK);
00855 setlinewidth(0);
00856 draw_triangle_along_line(x2 - 0.15, y, x1, x2, y, y);
00857
00858 setcolor(LIGHTGREY);
00859
00860 for(k = rr_node[inode].xlow; k < rr_node[inode].xhigh; k++)
00861 {
00862 x2 = tile_x[k] + tile_width;
00863 draw_triangle_along_line(x2 - 0.15, y, x1, x2, y, y);
00864 x2 = tile_x[k + 1];
00865 draw_triangle_along_line(x2 + 0.15, y, x1, x2, y, y);
00866 }
00867 setcolor(BLACK);
00868 }
00869 else if(rr_node[inode].direction == DEC_DIRECTION)
00870 {
00871 setlinewidth(2);
00872 setcolor(YELLOW);
00873 drawline(x2, y1, x2, y2);
00874
00875
00876 setcolor(BLACK);
00877 sprintf(str, "%d", rr_node[inode].fan_in);
00878 drawtext(x2, y, str, 5);
00879
00880 setlinewidth(0);
00881 draw_triangle_along_line(x1 + 0.15, y, x2, x1, y, y);
00882 setcolor(LIGHTGREY);
00883 for(k = rr_node[inode].xhigh; k > rr_node[inode].xlow; k--)
00884 {
00885 x1 = tile_x[k];
00886 draw_triangle_along_line(x1 + 0.15, y, x2, x1, y, y);
00887 x1 = tile_x[k - 1] + tile_width;
00888 draw_triangle_along_line(x1 - 0.15, y, x2, x1, y, y);
00889 }
00890 setcolor(BLACK);
00891 }
00892
00893 }
00894
00895
00896 static void
00897 draw_rr_chany(int inode,
00898 int itrack)
00899 {
00900
00901
00902 enum
00903 { BUFFSIZE = 80 };
00904 float x, y1, y2;
00905 float x1, x2;
00906 int k;
00907 char str[BUFFSIZE];
00908
00909
00910
00911 x = tile_x[rr_node[inode].xlow] + tile_width + 1. + itrack;
00912 y1 = tile_y[rr_node[inode].ylow];
00913 y2 = tile_y[rr_node[inode].yhigh] + tile_width;
00914 drawline(x, y1, x, y2);
00915
00916
00917 x1 = x - 0.25;
00918 x2 = x + 0.25;
00919 if(rr_node[inode].direction == INC_DIRECTION)
00920 {
00921 setlinewidth(2);
00922 setcolor(YELLOW);
00923 drawline(x1, y1, x2, y1);
00924
00925
00926 setcolor(BLACK);
00927 sprintf(str, "%d", rr_node[inode].fan_in);
00928 drawtext(x, y1, str, 5);
00929 setcolor(BLACK);
00930
00931
00932 setlinewidth(0);
00933 draw_triangle_along_line(x, y2 - 0.15, x, x, y1, y2);
00934 setcolor(LIGHTGREY);
00935 for(k = rr_node[inode].ylow; k < rr_node[inode].yhigh; k++)
00936 {
00937 y2 = tile_y[k] + tile_width;
00938 draw_triangle_along_line(x, y2 - 0.15, x, x, y1, y2);
00939 y2 = tile_y[k + 1];
00940 draw_triangle_along_line(x, y2 + 0.15, x, x, y1, y2);
00941 }
00942 setcolor(BLACK);
00943 }
00944 else if(rr_node[inode].direction == DEC_DIRECTION)
00945 {
00946 setlinewidth(2);
00947 setcolor(YELLOW);
00948 drawline(x1, y2, x2, y2);
00949
00950
00951 setcolor(BLACK);
00952 sprintf(str, "%d", rr_node[inode].fan_in);
00953 drawtext(x, y2, str, 5);
00954 setcolor(BLACK);
00955
00956
00957 setlinewidth(0);
00958 draw_triangle_along_line(x, y1 + 0.15, x, x, y2, y1);
00959 setcolor(LIGHTGREY);
00960 for(k = rr_node[inode].yhigh; k > rr_node[inode].ylow; k--)
00961 {
00962 y1 = tile_y[k];
00963 draw_triangle_along_line(x, y1 + 0.15, x, x, y2, y1);
00964 y1 = tile_y[k - 1] + tile_width;
00965 draw_triangle_along_line(x, y1 - 0.15, x, x, y2, y1);
00966 }
00967 setcolor(BLACK);
00968 }
00969
00970 }
00971
00972
00973 static void
00974 draw_rr_edges(int inode)
00975 {
00976
00977
00978
00979
00980 t_rr_type from_type, to_type;
00981 int iedge, to_node, from_ptc_num, to_ptc_num;
00982 short switch_type;
00983
00984 from_type = rr_node[inode].type;
00985
00986 if((draw_rr_toggle == DRAW_NODES_RR) ||
00987 (draw_rr_toggle == DRAW_NODES_AND_SBOX_RR && from_type == OPIN))
00988 {
00989 return;
00990 }
00991
00992 from_ptc_num = rr_node[inode].ptc_num;
00993
00994 for(iedge = 0; iedge < rr_node[inode].num_edges; iedge++)
00995 {
00996 to_node = rr_node[inode].edges[iedge];
00997 to_type = rr_node[to_node].type;
00998 to_ptc_num = rr_node[to_node].ptc_num;
00999
01000 switch (from_type)
01001 {
01002
01003 case OPIN:
01004 switch (to_type)
01005 {
01006 case CHANX:
01007 case CHANY:
01008 setcolor(RED);
01009 draw_pin_to_chan_edge(inode, to_node);
01010 break;
01011
01012 default:
01013 printf
01014 ("Error in draw_rr_edges: node %d (type: %d) connects to \n"
01015 "node %d (type: %d).\n", inode, from_type,
01016 to_node, to_type);
01017 exit(1);
01018 break;
01019 }
01020 break;
01021
01022 case CHANX:
01023 switch (to_type)
01024 {
01025 case IPIN:
01026 if(draw_rr_toggle == DRAW_NODES_AND_SBOX_RR)
01027 {
01028 break;
01029 }
01030
01031 setcolor(BLUE);
01032 draw_pin_to_chan_edge(to_node, inode);
01033 break;
01034
01035 case CHANX:
01036 setcolor(DARKGREEN);
01037 switch_type = rr_node[inode].switches[iedge];
01038 draw_chanx_to_chanx_edge(inode, from_ptc_num,
01039 to_node, to_ptc_num,
01040 switch_type);
01041 break;
01042
01043 case CHANY:
01044 setcolor(DARKGREEN);
01045 switch_type = rr_node[inode].switches[iedge];
01046 draw_chanx_to_chany_edge(inode, from_ptc_num,
01047 to_node, to_ptc_num,
01048 FROM_X_TO_Y,
01049 switch_type);
01050 break;
01051
01052 default:
01053 printf
01054 ("Error in draw_rr_edges: node %d (type: %d) connects to \n"
01055 "node %d (type: %d).\n", inode, from_type,
01056 to_node, to_type);
01057 exit(1);
01058 break;
01059 }
01060 break;
01061
01062
01063 case CHANY:
01064 switch (to_type)
01065 {
01066 case IPIN:
01067 if(draw_rr_toggle == DRAW_NODES_AND_SBOX_RR)
01068 {
01069 break;
01070 }
01071
01072 setcolor(BLUE);
01073 draw_pin_to_chan_edge(to_node, inode);
01074 break;
01075
01076 case CHANX:
01077 setcolor(DARKGREEN);
01078 switch_type = rr_node[inode].switches[iedge];
01079 draw_chanx_to_chany_edge(to_node, to_ptc_num,
01080 inode, from_ptc_num,
01081 FROM_Y_TO_X,
01082 switch_type);
01083 break;
01084
01085 case CHANY:
01086 setcolor(DARKGREEN);
01087 switch_type = rr_node[inode].switches[iedge];
01088 draw_chany_to_chany_edge(inode, from_ptc_num,
01089 to_node, to_ptc_num,
01090 switch_type);
01091 break;
01092
01093 default:
01094 printf
01095 ("Error in draw_rr_edges: node %d (type: %d) connects to \n"
01096 "node %d (type: %d).\n", inode, from_type,
01097 to_node, to_type);
01098 exit(1);
01099 break;
01100 }
01101 break;
01102
01103 default:
01104 printf
01105 ("Error: draw_rr_edges called with node %d of type %d.\n",
01106 inode, from_type);
01107 exit(1);
01108 break;
01109 }
01110 }
01111 }
01112
01113 static void
01114 draw_x(float x,
01115 float y,
01116 float size)
01117 {
01118
01119
01120
01121
01122 drawline(x - size, y + size, x + size, y - size);
01123 drawline(x - size, y - size, x + size, y + size);
01124 }
01125
01126
01127
01128 static void
01129 draw_chanx_to_chany_edge(int chanx_node,
01130 int chanx_track,
01131 int chany_node,
01132 int chany_track,
01133 enum e_edge_dir edge_dir,
01134 short switch_type)
01135 {
01136
01137
01138
01139
01140 float x1, y1, x2, y2;
01141 int chanx_y, chany_x, chanx_xlow, chany_ylow;
01142
01143 chanx_y = rr_node[chanx_node].ylow;
01144 chanx_xlow = rr_node[chanx_node].xlow;
01145 chany_x = rr_node[chany_node].xlow;
01146 chany_ylow = rr_node[chany_node].ylow;
01147
01148
01149
01150 y1 = tile_y[chanx_y] + tile_width + 1. + chanx_track;
01151 x2 = tile_x[chany_x] + tile_width + 1. + chany_track;
01152
01153 if(chanx_xlow <= chany_x)
01154 {
01155 x1 = tile_x[chany_x] + tile_width;
01156
01157 if(rr_node[chanx_node].direction != BI_DIRECTION)
01158 {
01159 if(edge_dir == FROM_X_TO_Y)
01160 {
01161 if((chanx_track % 2) == 1)
01162 {
01163 x1 = tile_x[chany_x + 1];
01164 }
01165 }
01166 }
01167
01168 }
01169 else
01170 {
01171 x1 = tile_x[chanx_xlow];
01172 }
01173
01174 if(chany_ylow <= chanx_y)
01175 {
01176 y2 = tile_y[chanx_y] + tile_width;
01177
01178 if(rr_node[chany_node].direction != BI_DIRECTION)
01179 {
01180 if(edge_dir == FROM_Y_TO_X)
01181 {
01182 if((chany_track % 2) == 1)
01183 {
01184 y2 = tile_y[chanx_y + 1];
01185 }
01186 }
01187 }
01188
01189 }
01190 else
01191 {
01192 y2 = tile_y[chany_ylow];
01193 }
01194
01195 drawline(x1, y1, x2, y2);
01196
01197 if(draw_rr_toggle != DRAW_ALL_RR)
01198 return;
01199
01200 if(edge_dir == FROM_X_TO_Y)
01201 draw_rr_switch(x1, y1, x2, y2, switch_inf[switch_type].buffered);
01202 else
01203 draw_rr_switch(x2, y2, x1, y1, switch_inf[switch_type].buffered);
01204 }
01205
01206
01207 static void
01208 draw_chanx_to_chanx_edge(int from_node,
01209 int from_track,
01210 int to_node,
01211 int to_track,
01212 short switch_type)
01213 {
01214
01215
01216
01217
01218
01219 float x1, x2, y1, y2;
01220 int from_y, to_y, from_xlow, to_xlow, from_xhigh, to_xhigh;
01221
01222 from_y = rr_node[from_node].ylow;
01223 from_xlow = rr_node[from_node].xlow;
01224 from_xhigh = rr_node[from_node].xhigh;
01225 to_y = rr_node[to_node].ylow;
01226 to_xlow = rr_node[to_node].xlow;
01227 to_xhigh = rr_node[to_node].xhigh;
01228
01229
01230
01231 y1 = tile_y[from_y] + tile_width + 1 + from_track;
01232 y2 = tile_y[to_y] + tile_width + 1 + to_track;
01233
01234
01235 if(to_xhigh < from_xlow)
01236 {
01237
01238
01239 x1 = tile_x[from_xlow];
01240 x2 = tile_x[to_xhigh] + tile_width;
01241 }
01242 else if(to_xlow > from_xhigh)
01243 {
01244
01245
01246 x1 = tile_x[from_xhigh] + tile_width;
01247 x2 = tile_x[to_xlow];
01248 }
01249
01250
01251
01252
01253
01254
01255 else
01256 {
01257 if(rr_node[to_node].direction != BI_DIRECTION)
01258 {
01259
01260 if(to_track % 2 == 0)
01261 {
01262 assert(from_xlow < to_xlow);
01263 x2 = tile_x[to_xlow];
01264
01265 x1 = tile_x[to_xlow - 1] + tile_width;
01266 }
01267 else
01268 {
01269 assert(from_xhigh > to_xhigh);
01270 x2 = tile_x[to_xhigh] + tile_width;
01271 x1 = tile_x[to_xhigh + 1];
01272 }
01273 }
01274 else
01275 {
01276 if(to_xlow < from_xlow)
01277 {
01278 x1 = tile_x[from_xlow];
01279 x2 = tile_x[from_xlow - 1] + tile_width;
01280 }
01281 else if(from_xlow < to_xlow)
01282 {
01283 x1 = tile_x[to_xlow - 1] + tile_width;
01284 x2 = tile_x[to_xlow];
01285 }
01286 else if(to_xhigh > from_xhigh)
01287 {
01288 x1 = tile_x[from_xhigh] + tile_width;
01289 x2 = tile_x[from_xhigh + 1];
01290 }
01291 else if(from_xhigh > to_xhigh)
01292 {
01293 x1 = tile_x[to_xhigh + 1];
01294 x2 = tile_x[to_xhigh] + tile_width;
01295 }
01296 else
01297 {
01298 x1 = tile_x[from_xlow];
01299 x2 = tile_x[from_xlow] + tile_width;
01300 }
01301 }
01302 }
01303
01304 drawline(x1, y1, x2, y2);
01305
01306 if(draw_rr_toggle == DRAW_ALL_RR)
01307 draw_rr_switch(x1, y1, x2, y2, switch_inf[switch_type].buffered);
01308 }
01309
01310
01311 static void
01312 draw_chany_to_chany_edge(int from_node,
01313 int from_track,
01314 int to_node,
01315 int to_track,
01316 short switch_type)
01317 {
01318
01319
01320
01321
01322
01323 float x1, x2, y1, y2;
01324 int from_x, to_x, from_ylow, to_ylow, from_yhigh, to_yhigh;
01325
01326 from_x = rr_node[from_node].xlow;
01327 from_ylow = rr_node[from_node].ylow;
01328 from_yhigh = rr_node[from_node].yhigh;
01329 to_x = rr_node[to_node].xlow;
01330 to_ylow = rr_node[to_node].ylow;
01331 to_yhigh = rr_node[to_node].yhigh;
01332
01333
01334
01335 x1 = tile_x[from_x] + tile_width + 1 + from_track;
01336 x2 = tile_x[to_x] + tile_width + 1 + to_track;
01337
01338 if(to_yhigh < from_ylow)
01339 {
01340 y1 = tile_y[from_ylow];
01341 y2 = tile_y[to_yhigh] + tile_width;
01342 }
01343 else if(to_ylow > from_yhigh)
01344 {
01345 y1 = tile_y[from_yhigh] + tile_width;
01346 y2 = tile_y[to_ylow];
01347 }
01348
01349
01350
01351
01352
01353
01354 else
01355 {
01356 if(rr_node[to_node].direction != BI_DIRECTION)
01357 {
01358 if(to_track % 2 == 0)
01359 {
01360 assert(from_ylow < to_ylow);
01361 y2 = tile_y[to_ylow];
01362
01363 y1 = tile_y[to_ylow - 1] + tile_width;
01364 }
01365 else
01366 {
01367 if(!(from_yhigh > to_yhigh))
01368 {
01369 printf
01370 ("from_yhigh (%d) !> to_yhigh (%d).\n",
01371 from_yhigh, to_yhigh);
01372 printf
01373 ("from is (%d, %d) to (%d, %d) track %d.\n",
01374 rr_node[from_node].xhigh,
01375 rr_node[from_node].yhigh,
01376 rr_node[from_node].xlow,
01377 rr_node[from_node].ylow,
01378 rr_node[from_node].ptc_num);
01379 printf
01380 ("to is (%d, %d) to (%d, %d) track %d.\n",
01381 rr_node[to_node].xhigh,
01382 rr_node[to_node].yhigh,
01383 rr_node[to_node].xlow,
01384 rr_node[to_node].ylow,
01385 rr_node[to_node].ptc_num);
01386 exit(1);
01387 }
01388 y2 = tile_y[to_yhigh] + tile_width;
01389 y1 = tile_y[to_yhigh + 1];
01390 }
01391 }
01392 else
01393 {
01394 if(to_ylow < from_ylow)
01395 {
01396 y1 = tile_y[from_ylow];
01397 y2 = tile_y[from_ylow - 1] + tile_width;
01398 }
01399 else if(from_ylow < to_ylow)
01400 {
01401 y1 = tile_y[to_ylow - 1] + tile_width;
01402 y2 = tile_y[to_ylow];
01403 }
01404 else if(to_yhigh > from_yhigh)
01405 {
01406 y1 = tile_y[from_yhigh] + tile_width;
01407 y2 = tile_y[from_yhigh + 1];
01408 }
01409 else if(from_yhigh > to_yhigh)
01410 {
01411 y1 = tile_y[to_yhigh + 1];
01412 y2 = tile_y[to_yhigh] + tile_width;
01413 }
01414 else
01415 {
01416 y1 = tile_y[from_ylow];
01417 y2 = tile_y[from_ylow] + tile_width;
01418 }
01419 }
01420 }
01421
01422 drawline(x1, y1, x2, y2);
01423
01424 if(draw_rr_toggle == DRAW_ALL_RR)
01425 draw_rr_switch(x1, y1, x2, y2, switch_inf[switch_type].buffered);
01426 }
01427
01428
01429 static void
01430 draw_rr_switch(float from_x,
01431 float from_y,
01432 float to_x,
01433 float to_y,
01434 boolean buffered)
01435 {
01436
01437
01438
01439
01440
01441 const float switch_rad = 0.15;
01442 float magnitude, xcen, ycen, xdelta, ydelta, xbaseline, ybaseline;
01443 float xunit, yunit;
01444 t_point poly[3];
01445
01446 xcen = from_x + (to_x - from_x) / 10.;
01447 ycen = from_y + (to_y - from_y) / 10.;
01448
01449 if(!buffered)
01450 {
01451 drawarc(xcen, ycen, switch_rad, 0., 360.);
01452 }
01453 else
01454 {
01455 xdelta = to_x - from_x;
01456 ydelta = to_y - from_y;
01457 magnitude = sqrt(xdelta * xdelta + ydelta * ydelta);
01458 xunit = xdelta / magnitude;
01459 yunit = ydelta / magnitude;
01460 poly[0].x = xcen + xunit * switch_rad;
01461 poly[0].y = ycen + yunit * switch_rad;
01462 xbaseline = xcen - xunit * switch_rad;
01463 ybaseline = ycen - yunit * switch_rad;
01464
01465
01466
01467
01468 poly[1].x = xbaseline + yunit * switch_rad;
01469 poly[1].y = ybaseline - xunit * switch_rad;
01470 poly[2].x = xbaseline - yunit * switch_rad;
01471 poly[2].y = ybaseline + xunit * switch_rad;
01472 fillpoly(poly, 3);
01473 }
01474 }
01475
01476
01477 static void
01478 draw_rr_pin(int inode,
01479 enum color_types color)
01480 {
01481
01482
01483
01484
01485
01486 int ipin, i, j, iside, iclass, ioff;
01487 float xcen, ycen;
01488 char str[BUFSIZE];
01489 t_type_ptr type;
01490
01491 i = rr_node[inode].xlow;
01492 j = rr_node[inode].ylow;
01493 ipin = rr_node[inode].ptc_num;
01494 type = grid[i][j].type;
01495 ioff = grid[i][j].offset;
01496
01497 setcolor(color);
01498 iclass = type->pin_class[ipin];
01499
01500 for(iside = 0; iside < 4; iside++)
01501 {
01502 if(type->pinloc[grid[i][j].offset][iside][ipin])
01503 {
01504 get_rr_pin_draw_coords(inode, iside, ioff, &xcen, &ycen);
01505 fillrect(xcen - pin_size, ycen - pin_size,
01506 xcen + pin_size, ycen + pin_size);
01507 sprintf(str, "%d", ipin);
01508 setcolor(BLACK);
01509 drawtext(xcen, ycen, str, 2 * pin_size);
01510 setcolor(color);
01511 }
01512 }
01513 }
01514
01515
01516 static void
01517 get_rr_pin_draw_coords(int inode,
01518 int iside,
01519 int ioff,
01520 float *xcen,
01521 float *ycen)
01522 {
01523
01524
01525
01526
01527
01528 int i, j, k, ipin, pins_per_sub_tile;
01529 float offset, xc, yc, step;
01530 t_type_ptr type;
01531
01532 i = rr_node[inode].xlow;
01533 j = rr_node[inode].ylow + ioff;
01534
01535 xc = tile_x[i];
01536 yc = tile_y[j];
01537
01538 ipin = rr_node[inode].ptc_num;
01539 type = grid[i][j].type;
01540 pins_per_sub_tile = grid[i][j].type->num_pins / grid[i][j].type->capacity;
01541 k = ipin / pins_per_sub_tile;
01542
01543
01544
01545
01546
01547 step = (float)(tile_width) / (float)(type->num_pins + type->capacity);
01548 offset = (ipin + k + 1) * step;
01549
01550 switch (iside)
01551 {
01552 case LEFT:
01553 yc += offset;
01554 break;
01555
01556 case RIGHT:
01557 xc += tile_width;
01558 yc += offset;
01559 break;
01560
01561 case BOTTOM:
01562 xc += offset;
01563 break;
01564
01565 case TOP:
01566 xc += offset;
01567 yc += tile_width;
01568 break;
01569
01570 default:
01571 printf("Error in get_rr_pin_draw_coords: Unexpected iside %d.\n",
01572 iside);
01573 exit(1);
01574 break;
01575 }
01576
01577 *xcen = xc;
01578 *ycen = yc;
01579 }
01580
01581
01582 static void
01583 drawroute(enum e_draw_net_type draw_net_type)
01584 {
01585
01586
01587
01588
01589
01590
01591
01592 static int **chanx_track = NULL;
01593 static int **chany_track = NULL;
01594
01595 int inet, i, j, inode, prev_node, prev_track, itrack;
01596 short switch_type;
01597 struct s_trace *tptr;
01598 t_rr_type rr_type, prev_type;
01599
01600
01601 if(draw_route_type == GLOBAL)
01602 {
01603
01604 if(chanx_track == NULL)
01605 {
01606 chanx_track =
01607 (int **)alloc_matrix(1, nx, 0, ny, sizeof(int));
01608 }
01609
01610 if(chany_track == NULL)
01611 {
01612 chany_track =
01613 (int **)alloc_matrix(0, nx, 1, ny, sizeof(int));
01614 }
01615
01616 for(i = 1; i <= nx; i++)
01617 for(j = 0; j <= ny; j++)
01618 chanx_track[i][j] = (-1);
01619
01620 for(i = 0; i <= nx; i++)
01621 for(j = 1; j <= ny; j++)
01622 chany_track[i][j] = (-1);
01623 }
01624
01625 setlinestyle(SOLID);
01626
01627
01628
01629 for(inet = 0; inet < num_nets; inet++)
01630 {
01631 if(net[inet].is_global)
01632 continue;
01633
01634 if(trace_head[inet] == NULL)
01635 continue;
01636
01637 if(draw_net_type == HIGHLIGHTED && net_color[inet] == BLACK)
01638 continue;
01639
01640 setcolor(net_color[inet]);
01641 tptr = trace_head[inet];
01642 inode = tptr->index;
01643 rr_type = rr_node[inode].type;
01644
01645
01646 for(;;)
01647 {
01648 prev_node = inode;
01649 prev_type = rr_type;
01650 switch_type = tptr->iswitch;
01651 tptr = tptr->next;
01652 inode = tptr->index;
01653 rr_type = rr_node[inode].type;
01654
01655 switch (rr_type)
01656 {
01657
01658 case OPIN:
01659 draw_rr_pin(inode, net_color[inet]);
01660 break;
01661
01662 case IPIN:
01663 draw_rr_pin(inode, net_color[inet]);
01664 prev_track =
01665 get_track_num(prev_node, chanx_track,
01666 chany_track);
01667 draw_pin_to_chan_edge(inode, prev_node);
01668 break;
01669
01670 case CHANX:
01671 if(draw_route_type == GLOBAL)
01672 chanx_track[rr_node[inode].
01673 xlow][rr_node[inode].ylow]++;
01674
01675 itrack =
01676 get_track_num(inode, chanx_track,
01677 chany_track);
01678 draw_rr_chanx(inode, itrack);
01679
01680 switch (prev_type)
01681 {
01682
01683 case CHANX:
01684 prev_track =
01685 get_track_num(prev_node, chanx_track,
01686 chany_track);
01687 draw_chanx_to_chanx_edge(prev_node,
01688 prev_track,
01689 inode, itrack,
01690 switch_type);
01691 break;
01692
01693 case CHANY:
01694 prev_track =
01695 get_track_num(prev_node, chanx_track,
01696 chany_track);
01697 draw_chanx_to_chany_edge(inode, itrack,
01698 prev_node,
01699 prev_track,
01700 FROM_Y_TO_X,
01701 switch_type);
01702 break;
01703
01704 case OPIN:
01705 draw_pin_to_chan_edge(prev_node, inode);
01706 break;
01707
01708 default:
01709 printf
01710 ("Error in drawroute: Unexpected connection from an \n"
01711 "rr_node of type %d to one of type %d.\n",
01712 prev_type, rr_type);
01713 exit(1);
01714 }
01715
01716 break;
01717
01718 case CHANY:
01719 if(draw_route_type == GLOBAL)
01720 chany_track[rr_node[inode].
01721 xlow][rr_node[inode].ylow]++;
01722
01723 itrack =
01724 get_track_num(inode, chanx_track,
01725 chany_track);
01726 draw_rr_chany(inode, itrack);
01727
01728 switch (prev_type)
01729 {
01730
01731 case CHANX:
01732 prev_track =
01733 get_track_num(prev_node, chanx_track,
01734 chany_track);
01735 draw_chanx_to_chany_edge(prev_node,
01736 prev_track,
01737 inode, itrack,
01738 FROM_X_TO_Y,
01739 switch_type);
01740 break;
01741
01742 case CHANY:
01743 prev_track =
01744 get_track_num(prev_node, chanx_track,
01745 chany_track);
01746 draw_chany_to_chany_edge(prev_node,
01747 prev_track,
01748 inode, itrack,
01749 switch_type);
01750 break;
01751
01752 case OPIN:
01753 draw_pin_to_chan_edge(prev_node, inode);
01754
01755 break;
01756
01757 default:
01758 printf
01759 ("Error in drawroute: Unexpected connection from an \n"
01760 "rr_node of type %d to one of type %d.\n",
01761 prev_type, rr_type);
01762 exit(1);
01763 }
01764
01765 break;
01766
01767 default:
01768 break;
01769
01770 }
01771
01772 if(rr_type == SINK)
01773 {
01774 tptr = tptr->next;
01775 if(tptr == NULL)
01776 break;
01777 inode = tptr->index;
01778 rr_type = rr_node[inode].type;
01779 }
01780
01781 }
01782 }
01783 }
01784
01785
01786 static int
01787 get_track_num(int inode,
01788 int **chanx_track,
01789 int **chany_track)
01790 {
01791
01792
01793
01794 int i, j;
01795 t_rr_type rr_type;
01796
01797 if(draw_route_type == DETAILED)
01798 return (rr_node[inode].ptc_num);
01799
01800
01801
01802 rr_type = rr_node[inode].type;
01803 i = rr_node[inode].xlow;
01804 j = rr_node[inode].ylow;
01805
01806 switch (rr_type)
01807 {
01808 case CHANX:
01809 return (chanx_track[i][j]);
01810
01811 case CHANY:
01812 return (chany_track[i][j]);
01813
01814 default:
01815 printf
01816 ("Error in get_track_num: unexpected node type %d for node %d."
01817 "\n", rr_type, inode);
01818 exit(1);
01819 }
01820 }
01821
01822
01823 static void
01824 highlight_blocks(float x,
01825 float y)
01826 {
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837 int i, j, k, hit, bnum, ipin, netnum, fanblk;
01838 int iclass;
01839 float io_step;
01840 t_type_ptr type;
01841 char msg[BUFSIZE];
01842
01843 deselect_all();
01844
01845 hit = 0;
01846 for(i = 0; i <= (nx + 1) && !hit; i++)
01847 {
01848 if(x <= tile_x[i] + tile_width)
01849 {
01850 if(x >= tile_x[i]){
01851 for(j = 0; j <= (ny + 1) && !hit; j++)
01852 {
01853 if(grid[i][j].offset != 0)
01854 continue;
01855 type = grid[i][j].type;
01856 if(y <= tile_y[j + type->height - 1] + tile_width)
01857 {
01858 if(y >= tile_y[j])
01859 hit = 1;
01860 }
01861 }
01862
01863 }
01864 }
01865 }
01866 i--;
01867 j--;
01868
01869 if(!hit)
01870 {
01871 update_message(default_message);
01872 drawscreen();
01873 return;
01874 }
01875 type = grid[i][j].type;
01876 hit = 0;
01877
01878 if(EMPTY_TYPE == type)
01879 {
01880 update_message(default_message);
01881 drawscreen();
01882 return;
01883 }
01884
01885
01886 io_step = tile_width / type->capacity;
01887
01888 if((i < 1) || (i > nx))
01889 k = (int)((y - tile_y[j]) / io_step);
01890 else
01891 k = (int)((x - tile_x[i]) / io_step);
01892
01893 assert(k < type->capacity);
01894 if(grid[i][j].blocks[k] == EMPTY)
01895 {
01896 update_message(default_message);
01897 drawscreen();
01898 return;
01899 }
01900 bnum = grid[i][j].blocks[k];
01901
01902
01903
01904 for(k = 0; k < type->num_pins; k++)
01905 {
01906 netnum = block[bnum].nets[k];
01907
01908 if(netnum == OPEN)
01909 continue;
01910
01911 iclass = type->pin_class[k];
01912
01913 if(type->class_inf[iclass].type == DRIVER)
01914 {
01915 net_color[netnum] = RED;
01916 for(ipin = 1; ipin <= net[netnum].num_sinks; ipin++)
01917 {
01918 fanblk = net[netnum].node_block[ipin];
01919 block_color[fanblk] = RED;
01920 }
01921 }
01922 else
01923 {
01924 net_color[netnum] = BLUE;
01925 fanblk = net[netnum].node_block[0];
01926 block_color[fanblk] = BLUE;
01927 }
01928 }
01929
01930 block_color[bnum] = GREEN;
01931
01932 sprintf(msg, "Block %d (%s) at (%d, %d) selected.", bnum,
01933 block[bnum].name, i, j);
01934 update_message(msg);
01935 drawscreen();
01936 }
01937
01938
01939 static void
01940 deselect_all(void)
01941 {
01942
01943
01944 int i;
01945
01946
01947 for(i = 0; i < num_blocks; i++) {
01948 if(block[i].type->index < 3) {
01949 block_color[i] = LIGHTGREY;
01950 } else if(block[i].type->index < 3 + MAX_BLOCK_COLOURS) {
01951 block_color[i] = BISQUE + MAX_BLOCK_COLOURS + block[i].type->index - 3;
01952 } else {
01953 block_color[i] = BISQUE + 2 * MAX_BLOCK_COLOURS - 1;
01954 }
01955 }
01956
01957 for(i = 0; i < num_nets; i++)
01958 net_color[i] = BLACK;
01959 }
01960
01961
01962
01963 static void
01964 draw_triangle_along_line(float xend,
01965 float yend,
01966 float x1,
01967 float x2,
01968 float y1,
01969 float y2)
01970 {
01971 float switch_rad = 0.15;
01972 float xdelta, ydelta;
01973 float magnitude;
01974 float xunit, yunit;
01975 float xbaseline, ybaseline;
01976 t_point poly[3];
01977
01978 xdelta = x2 - x1;
01979 ydelta = y2 - y1;
01980 magnitude = sqrt(xdelta * xdelta + ydelta * ydelta);
01981 xunit = xdelta / magnitude;
01982 yunit = ydelta / magnitude;
01983
01984 poly[0].x = xend + xunit * switch_rad;
01985 poly[0].y = yend + yunit * switch_rad;
01986 xbaseline = xend - xunit * switch_rad;
01987 ybaseline = yend - yunit * switch_rad;
01988 poly[1].x = xbaseline + yunit * switch_rad;
01989 poly[1].y = ybaseline - xunit * switch_rad;
01990 poly[2].x = xbaseline - yunit * switch_rad;
01991 poly[2].y = ybaseline + xunit * switch_rad;
01992
01993 fillpoly(poly, 3);
01994 }
01995
01996
01997 static void
01998 draw_pin_to_chan_edge(int pin_node,
01999 int chan_node)
02000 {
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010 t_rr_type chan_type;
02011 int grid_x, grid_y, pin_num, chan_xlow, chan_ylow, ioff, height;
02012 float x1, x2, y1, y2;
02013 int start, end, i;
02014 int itrack;
02015 float xend, yend;
02016 float draw_pin_off;
02017 enum e_direction direction;
02018 enum e_side iside;
02019 t_type_ptr type;
02020
02021 direction = rr_node[chan_node].direction;
02022 grid_x = rr_node[pin_node].xlow;
02023 grid_y = rr_node[pin_node].ylow;
02024 pin_num = rr_node[pin_node].ptc_num;
02025 chan_type = rr_node[chan_node].type;
02026 itrack = rr_node[chan_node].ptc_num;
02027 type = grid[grid_x][grid_y].type;
02028
02029 ioff = grid[grid_x][grid_y].offset;
02030
02031 grid_y = grid_y - ioff;
02032 height = grid[grid_x][grid_y].type->height;
02033 chan_ylow = rr_node[chan_node].ylow;
02034 chan_xlow = rr_node[chan_node].xlow;
02035 start = -1;
02036 end = -1;
02037
02038
02039 switch (chan_type)
02040 {
02041
02042 case CHANX:
02043 start = rr_node[chan_node].xlow;
02044 end = rr_node[chan_node].xhigh;
02045 if(is_opin(pin_num, type))
02046 {
02047 if(direction == INC_DIRECTION)
02048 {
02049 end = rr_node[chan_node].xlow;
02050 }
02051 else if(direction == DEC_DIRECTION)
02052 {
02053 start = rr_node[chan_node].xhigh;
02054 }
02055 }
02056
02057 start = max(start, grid_x);
02058 end = min(end, grid_x);
02059 assert(end >= start);
02060
02061 if((grid_y + height - 1) == chan_ylow)
02062 {
02063 iside = TOP;
02064 ioff = height - 1;
02065 draw_pin_off = pin_size;
02066 }
02067 else
02068 {
02069 assert((grid_y - 1) == chan_ylow);
02070
02071 iside = BOTTOM;
02072 ioff = 0;
02073 draw_pin_off = -pin_size;
02074 }
02075 assert(grid[grid_x][grid_y].type->pinloc[ioff][iside][pin_num]);
02076
02077 get_rr_pin_draw_coords(pin_node, iside, ioff, &x1, &y1);
02078 y1 += draw_pin_off;
02079
02080 y2 = tile_y[rr_node[chan_node].ylow] + tile_width + 1. + itrack;
02081 x2 = x1;
02082 if(is_opin(pin_num, type))
02083 {
02084 if(direction == INC_DIRECTION)
02085 {
02086 x2 = tile_x[rr_node[chan_node].xlow];
02087 }
02088 else if(direction == DEC_DIRECTION)
02089 {
02090 x2 = tile_x[rr_node[chan_node].xhigh] +
02091 tile_width;
02092 }
02093 }
02094 break;
02095
02096 case CHANY:
02097 start = rr_node[chan_node].ylow;
02098 end = rr_node[chan_node].yhigh;
02099 if(is_opin(pin_num, type))
02100 {
02101 if(direction == INC_DIRECTION)
02102 {
02103 end = rr_node[chan_node].ylow;
02104 }
02105 else if(direction == DEC_DIRECTION)
02106 {
02107 start = rr_node[chan_node].yhigh;
02108 }
02109 }
02110
02111 start = max(start, grid_y);
02112 end = min(end, (grid_y + height - 1));
02113 assert(end >= start);
02114
02115 if((grid_x) == chan_xlow)
02116 {
02117 iside = RIGHT;
02118 draw_pin_off = pin_size;
02119 }
02120 else
02121 {
02122 assert((grid_x - 1) == chan_xlow);
02123 iside = LEFT;
02124 draw_pin_off = -pin_size;
02125 }
02126 for(i = start; i <= end; i++)
02127 {
02128 ioff = i - grid_y;
02129 assert(ioff >= 0 && ioff < type->height);
02130
02131
02132
02133
02134
02135 if(grid[grid_x][grid_y].type->
02136 pinloc[ioff][iside][pin_num])
02137 {
02138 break;
02139 }
02140 }
02141 assert(grid[grid_x][grid_y].type->pinloc[ioff][iside][pin_num]);
02142
02143 get_rr_pin_draw_coords(pin_node, iside, ioff, &x1, &y1);
02144 x1 += draw_pin_off;
02145
02146 x2 = tile_x[chan_xlow] + tile_width + 1 + itrack;
02147 y2 = y1;
02148 if(is_opin(pin_num, type))
02149 {
02150 if(direction == INC_DIRECTION)
02151 {
02152 y2 = tile_y[rr_node[chan_node].ylow];
02153 }
02154 else if(direction == DEC_DIRECTION)
02155 {
02156 y2 = tile_y[rr_node[chan_node].yhigh] +
02157 tile_width;
02158 }
02159 }
02160 break;
02161
02162 default:
02163 printf
02164 ("Error in draw_pin_to_chan_edge: invalid channel node %d.\n",
02165 chan_node);
02166 exit(1);
02167 }
02168
02169 drawline(x1, y1, x2, y2);
02170 if(direction == BI_DIRECTION || !is_opin(pin_num, type))
02171 {
02172 draw_x(x2, y2, 0.7 * pin_size);
02173 }
02174 else
02175 {
02176 xend = x2 + (x1 - x2) / 10.;
02177 yend = y2 + (y1 - y2) / 10.;
02178 draw_triangle_along_line(xend, yend, x1, x2, y1, y2);
02179 }
02180 }
02181
02182