VPR-6.0

vpr/SRC/base/draw.c

Go to the documentation of this file.
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 #include "read_xml_arch_file.h"
00013 
00014 #ifdef DEBUG
00015 #include "rr_graph.h"
00016 #endif
00017 
00018 /*************** Types local to this module *********************************/
00019 #define MAX_BLOCK_COLOURS 5
00020 
00021 enum e_draw_rr_toggle
00022 {
00023     DRAW_NO_RR = 0,
00024     DRAW_ALL_RR,
00025     DRAW_ALL_BUT_BUFFERS_RR,
00026     DRAW_NODES_AND_SBOX_RR,
00027     DRAW_NODES_RR,
00028     DRAW_RR_TOGGLE_MAX
00029 };
00030 
00031 enum e_draw_net_type
00032 { ALL_NETS, HIGHLIGHTED };
00033 
00034 enum e_edge_dir
00035 { FROM_X_TO_Y, FROM_Y_TO_X };   /* Chanx to chany or vice versa? */
00036 
00037 
00038 /****************** Variables local to this module. *************************/
00039 
00040 /** Show nets of placement or routing? */
00041 static boolean show_nets = FALSE;       
00042 
00043 /* Controls drawing of routing resources on screen, if pic_on_screen is   *
00044  * ROUTING.                                                               */
00045 
00046 /** Can toggle to DRAW_NO_RR;*/
00047 static enum e_draw_rr_toggle draw_rr_toggle = DRAW_NO_RR;       /* UDSD by AY */
00048 
00049 static enum e_route_type draw_route_type;
00050 
00051 /** Controls if congestion is shown, when ROUTING is on screen. */
00052 static boolean show_congestion = FALSE;
00053 
00054 /** Show defective stuff */
00055 static boolean show_defects = FALSE;  
00056 
00057 /** Graphics enabled or not? */
00058 static boolean show_graphics;   
00059 
00060 /** Default screen message on screen */
00061 static char default_message[BUFSIZE];   
00062 
00063 /** Need user input after: 0: each t,   
00064  * 1: each place, 2: never             
00065  */
00066 static int gr_automode;         
00067 
00068 /** What do I draw? */
00069 static enum pic_type pic_on_screen = NO_PICTURE;        
00070 
00071 /** The left and bottom coordinates of each grid_tile in the FPGA. 
00072  * tile_x[0..nx+1] and tile_y[0..ny+1].                         
00073  * COORDINATE SYSTEM goes from (0,0) at the lower left corner to   
00074  * (tile_x[nx+1]+tile_width, tile_y[ny+1]+tile_width) in the      
00075  * upper right corner.                                                    
00076  */
00077 static float *tile_x, *tile_y;
00078 
00079 /** Drawn width (and height) of a grid_tile, and the half-width or half-height of 
00080  * a pin, respectively.  Set when init_draw_coords is called.         
00081  */
00082 static float tile_width, pin_size;
00083 
00084 /** Color in which each block and net should be drawn.     
00085  * [0..num_nets-1] and [0..num_blocks-1], respectively.    
00086  */
00087 static enum color_types *net_color, *block_color;
00088 
00089 static float line_fuz = 0.3;
00090 static char *name_type[] = { "SOURCE", "SINK", "IPIN", "OPIN", "CHANX",
00091                              "CHANY", "INTRA_CLUSTER_EDGE" };
00092 
00093 static float *x_rr_node_left = NULL;
00094 static float *x_rr_node_right = NULL;
00095 static float *y_rr_node_top = NULL;
00096 static float *y_rr_node_bottom = NULL;
00097 static enum color_types *rr_node_color = NULL;
00098 static int old_num_rr_nodes = 0;
00099 
00100 /********************** Subroutines local to this module ********************/
00101 
00102 static void toggle_nets(void (*drawscreen) (void));
00103 static void toggle_rr(void (*drawscreen) (void));
00104 static void toggle_defects(void (*drawscreen) (void));
00105 static void toggle_congestion(void (*drawscreen) (void));
00106 static void highlight_crit_path(void (*drawscreen_ptr) (void));
00107 
00108 static void drawscreen(void);
00109 static void redraw_screen(void);
00110 static void drawplace(void);
00111 static void drawnets(void);
00112 static void drawroute(enum e_draw_net_type draw_net_type);
00113 static void draw_congestion(void);
00114 
00115 static void highlight_blocks(float x,
00116                              float y);
00117 static void get_block_center(int bnum,
00118                              float *x,
00119                              float *y);
00120 static void deselect_all(void);
00121 
00122 static void draw_rr(void);
00123 static void draw_rr_edges(int from_node);
00124 static void draw_rr_pin(int inode,
00125                         enum color_types color);
00126 static void draw_rr_chanx(int inode,
00127                           int itrack);
00128 static void draw_rr_chany(int inode,
00129                           int itrack);
00130 static void get_rr_pin_draw_coords(int inode,
00131                                    int iside,
00132                                    int ioff,
00133                                    float *xcen,
00134                                    float *ycen);
00135 static void draw_pin_to_chan_edge(int pin_node,
00136                                   int chan_node);
00137 static void draw_x(float x,
00138                    float y,
00139                    float size);
00140 static void draw_chany_to_chany_edge(int from_node,
00141                                      int from_track,
00142                                      int to_node,
00143                                      int to_track,
00144                                      short switch_type);
00145 static void draw_chanx_to_chanx_edge(int from_node,
00146                                      int from_track,
00147                                      int to_node,
00148                                      int to_track,
00149                                      short switch_type);
00150 static void draw_chanx_to_chany_edge(int chanx_node,
00151                                      int chanx_track,
00152                                      int chany_node,
00153                                      int chany_track,
00154                                      enum e_edge_dir edge_dir,
00155                                      short switch_type);
00156 static int get_track_num(int inode,
00157                          int **chanx_track,
00158                          int **chany_track);
00159 static void draw_rr_switch(float from_x,
00160                            float from_y,
00161                            float to_x,
00162                            float to_y,
00163                            boolean buffered);
00164 static void draw_triangle_along_line(float xend,
00165                                      float yend,        /* UDSD by AY */
00166 
00167                                      float x1,
00168                                      float x2,  /* UDSD by AY */
00169 
00170                                      float y1,
00171                                      float y2); /* UDSD by AY */
00172 
00173 
00174 /********************** Subroutine definitions ******************************/
00175 
00176 
00177 /** Sets the static show_graphics and gr_automode variables to the    
00178  * desired values.  They control if graphics are enabled and, if so, 
00179  * how often the user is prompted for input.                         
00180  */
00181 void
00182 set_graphics_state(boolean show_graphics_val,
00183                    int gr_automode_val,
00184                    enum e_route_type route_type)
00185 {
00186     show_graphics = show_graphics_val;
00187     gr_automode = gr_automode_val;
00188     draw_route_type = route_type;
00189 }
00190 
00191 
00192 /** Updates the screen if the user has requested graphics.  The priority  
00193  * value controls whether or not the Proceed button must be clicked to   
00194  * continue.  Saves the pic_on_screen_val to allow pan and zoom redraws. 
00195  */
00196 void
00197 update_screen(int priority,
00198               char *msg,
00199               enum pic_type pic_on_screen_val,
00200               boolean crit_path_button_enabled)
00201 {
00202     if(!show_graphics)          /* Graphics turned off */
00203         return;
00204 
00205     /* If it's the type of picture displayed has changed, set up the proper  *
00206      * buttons.                                                              */
00207     if(pic_on_screen != pic_on_screen_val)
00208         {
00209             if(pic_on_screen_val == PLACEMENT && pic_on_screen == NO_PICTURE)
00210                 {
00211                     create_button("Window", "Toggle Nets", toggle_nets);
00212                 }
00213             else if(pic_on_screen_val == ROUTING
00214                     && pic_on_screen == PLACEMENT)
00215                 {
00216                     create_button("Toggle Nets", "Toggle RR", toggle_rr);
00217                     create_button("Toggle RR", "Tog Defects", toggle_defects);
00218                     create_button("Toggle RR", "Congestion",
00219                                   toggle_congestion);
00220 
00221                     if(crit_path_button_enabled)
00222                         {
00223                             create_button("Congestion", "Crit. Path",
00224                                           highlight_crit_path);
00225                         }
00226                 }
00227             else if(pic_on_screen_val == PLACEMENT
00228                     && pic_on_screen == ROUTING)
00229                 {
00230                     destroy_button("Toggle RR");
00231                     destroy_button("Congestion");
00232 
00233                     if(crit_path_button_enabled)
00234                         {
00235                             destroy_button("Crit. Path");
00236                         }
00237                 }
00238             else if(pic_on_screen_val == ROUTING
00239                     && pic_on_screen == NO_PICTURE)
00240                 {
00241                     create_button("Window", "Toggle Nets", toggle_nets);
00242                     create_button("Toggle Nets", "Toggle RR", toggle_rr);
00243                     create_button("Toggle RR", "Tog Defects", toggle_defects);
00244                     create_button("Tog Defects", "Congestion",
00245                                   toggle_congestion);
00246 
00247                     if(crit_path_button_enabled)
00248                         {
00249                             create_button("Congestion", "Crit. Path",
00250                                           highlight_crit_path);
00251                         }
00252                 }
00253         }
00254     /* Save the main message. */
00255 
00256     my_strncpy(default_message, msg, BUFSIZE);
00257 
00258     pic_on_screen = pic_on_screen_val;
00259     update_message(msg);
00260     drawscreen();
00261     if(priority >= gr_automode)
00262         {
00263             event_loop(highlight_blocks, drawscreen);
00264         }
00265     else
00266         {
00267             flushinput();
00268         }
00269 }
00270 
00271 
00272 /** This is the screen redrawing routine that event_loop assumes exists.  
00273  * It erases whatever is on screen, then calls redraw_screen to redraw   
00274  * it.                                                                   
00275  */
00276 static void
00277 drawscreen()
00278 {
00279 
00280     clearscreen();
00281     redraw_screen();
00282 }
00283 
00284 
00285 /** The screen redrawing routine called by drawscreen and           
00286  * highlight_blocks.  Call this routine instead of drawscreen if   
00287  * you know you don't need to erase the current graphics, and want 
00288  * to avoid a screen "flash".                                      
00289  */
00290 static void
00291 redraw_screen()
00292 {
00293 
00294     setfontsize(14);            /* UDSD Modification by WMF */
00295     if(pic_on_screen == PLACEMENT)
00296         {
00297             drawplace();
00298             if(show_nets)
00299                 {
00300                     drawnets();
00301                 }
00302         }
00303     else
00304         {                       /* ROUTING on screen */
00305             drawplace();
00306 
00307             if(show_nets)
00308                 {
00309                     drawroute(ALL_NETS);
00310                 }
00311             else
00312                 {
00313                     draw_rr();
00314                 }
00315 
00316             if(show_congestion)
00317                 {
00318                     draw_congestion();
00319                 }
00320         }
00321 }
00322 
00323 
00324 /** Enables/disables drawing of nets when a the user clicks on a button.    
00325  * Also disables drawing of routing resources.  See graphics.c for details 
00326  * of how buttons work.                                                    
00327  */
00328 static void
00329 toggle_nets(void (*drawscreen_ptr) (void))
00330 {
00331     show_nets = !show_nets;
00332     draw_rr_toggle = DRAW_NO_RR;
00333     show_congestion = FALSE;
00334 
00335     update_message(default_message);
00336     drawscreen_ptr();
00337 }
00338 
00339 
00340 /** Cycles through the options for viewing the routing resources available   
00341  * in an FPGA.  If a routing isn't on screen, the routing graph hasn't been 
00342  * built, and this routine doesn't switch the view. Otherwise, this routine 
00343  * switches to the routing resource view.  Clicking on the toggle cycles    
00344  * through the options:  DRAW_NO_RR, DRAW_ALL_RR, DRAW_ALL_BUT_BUFFERS_RR,  
00345  * DRAW_NODES_AND_SBOX_RR, and DRAW_NODES_RR.                               
00346  */
00347 static void
00348 toggle_rr(void (*drawscreen_ptr) (void))
00349 {
00350     draw_rr_toggle = (draw_rr_toggle + 1) % (DRAW_RR_TOGGLE_MAX);
00351     show_nets = FALSE;
00352     show_congestion = FALSE;
00353 
00354     update_message(default_message);
00355     drawscreen_ptr();
00356 }
00357 
00358 static void
00359 toggle_defects(void (*drawscreen_ptr) (void))
00360 {
00361     show_defects = !show_defects;
00362     update_message(default_message);
00363     drawscreen_ptr();
00364 }
00365 
00366 
00367 /** Turns the congestion display on and off.   */
00368 static void
00369 toggle_congestion(void (*drawscreen_ptr) (void))
00370 {
00371     char msg[BUFSIZE];
00372     int inode, num_congested;
00373 
00374     show_nets = FALSE;
00375     draw_rr_toggle = DRAW_NO_RR;
00376     show_congestion = !show_congestion;
00377 
00378     if(!show_congestion)
00379         {
00380             update_message(default_message);
00381         }
00382     else
00383         {
00384             num_congested = 0;
00385             for(inode = 0; inode < num_rr_nodes; inode++)
00386                 {
00387                     if(rr_node[inode].occ > rr_node[inode].capacity)
00388                         {
00389                             num_congested++;
00390                         }
00391                 }
00392 
00393             sprintf(msg, "%d routing resources are overused.", num_congested);
00394             update_message(msg);
00395         }
00396 
00397     drawscreen_ptr();
00398 }
00399 
00400 
00401 /** Highlights all the blocks and nets on the critical path. */
00402 static void
00403 highlight_crit_path(void (*drawscreen_ptr) (void))
00404 {
00405     t_linked_int *critical_path_head, *critical_path_node;
00406     int inode, iblk, inet, num_nets_seen;
00407     static int nets_to_highlight = 1;
00408     char msg[BUFSIZE];
00409 
00410     if(nets_to_highlight == 0)
00411         {                       /* Clear the display of all highlighting. */
00412             nets_to_highlight = 1;
00413             deselect_all();
00414             update_message(default_message);
00415             drawscreen_ptr();
00416             return;
00417         }
00418 
00419     critical_path_head = allocate_and_load_critical_path();
00420     critical_path_node = critical_path_head;
00421     num_nets_seen = 0;
00422 
00423     while(critical_path_node != NULL)
00424         {
00425             inode = critical_path_node->data;
00426             get_tnode_block_and_output_net(inode, &iblk, &inet);
00427 
00428             if(num_nets_seen == nets_to_highlight)
00429                 {               /* Last block */
00430                     block_color[iblk] = MAGENTA;
00431                 }
00432             else if(num_nets_seen == nets_to_highlight - 1)
00433                 {               /* 2nd last block */
00434                     block_color[iblk] = YELLOW;
00435                 }
00436             else if(num_nets_seen < nets_to_highlight)
00437                 {               /* Earlier block */
00438                     block_color[iblk] = DARKGREEN;
00439                 }
00440 
00441             if(inet != OPEN)
00442                 {
00443                     num_nets_seen++;
00444 
00445                     if(num_nets_seen < nets_to_highlight)
00446                         {       /* First nets. */
00447                             net_color[inet] = DARKGREEN;
00448                         }
00449                     else if(num_nets_seen == nets_to_highlight)
00450                         {
00451                             net_color[inet] = CYAN;     /* Last (new) net. */
00452                         }
00453                 }
00454 
00455             critical_path_node = critical_path_node->next;
00456         }
00457 
00458     if(nets_to_highlight == num_nets_seen)
00459         {
00460             nets_to_highlight = 0;
00461             sprintf(msg, "All %d nets on the critical path highlighted.",
00462                     num_nets_seen);
00463         }
00464     else
00465         {
00466             sprintf(msg, "First %d nets on the critical path highlighted.",
00467                     nets_to_highlight);
00468             nets_to_highlight++;
00469         }
00470 
00471     free_int_list(&critical_path_head);
00472 
00473     update_message(msg);
00474     drawscreen_ptr();
00475 }
00476 
00477 
00478 /** Allocate the structures needed to draw the placement and routing.  Set 
00479  * up the default colors for blocks and nets.                             
00480  */
00481 void
00482 alloc_draw_structs(void)
00483 {
00484     tile_x = (float *)my_malloc((nx + 2) * sizeof(float));
00485     tile_y = (float *)my_malloc((ny + 2) * sizeof(float));
00486 
00487     net_color = (enum color_types *)
00488         my_malloc(num_nets * sizeof(enum color_types));
00489 
00490     block_color = (enum color_types *)
00491         my_malloc(num_blocks * sizeof(enum color_types));
00492 
00493     x_rr_node_left = (float *) my_malloc(num_rr_nodes*sizeof(float));
00494     x_rr_node_right = (float *) my_malloc(num_rr_nodes*sizeof(float));
00495     y_rr_node_top = (float *) my_malloc(num_rr_nodes*sizeof(float));
00496     y_rr_node_bottom = (float *) my_malloc(num_rr_nodes*sizeof(float));
00497     rr_node_color = (enum color_types *) my_malloc(num_rr_nodes*sizeof(enum color_types));
00498 
00499     deselect_all();             /* Set initial colors */
00500 }
00501 
00502 
00503 /** Load the arrays containing the left and bottom coordinates of the clbs   
00504  * forming the FPGA.  tile_width_val sets the width and height of a drawn    
00505  * clb.                                                                     
00506  */
00507 void
00508 init_draw_coords(float width_val)
00509 {
00510     int i;
00511     int j;
00512 
00513     if(!show_graphics)
00514         return;                 /* -nodisp was selected. */
00515 
00516     if(num_rr_nodes != old_num_rr_nodes)
00517     {
00518         x_rr_node_left = (float *) my_realloc(x_rr_node_left, (num_rr_nodes)*sizeof(float));
00519         x_rr_node_right = (float *) my_realloc(x_rr_node_right, (num_rr_nodes)*sizeof(float));
00520         y_rr_node_top = (float *) my_realloc(y_rr_node_top, (num_rr_nodes)*sizeof(float));
00521         y_rr_node_bottom = (float *) my_realloc(y_rr_node_bottom, (num_rr_nodes)*sizeof(float));
00522         rr_node_color = (enum color_types *) my_realloc(rr_node_color, (num_rr_nodes)*sizeof(enum color_types));
00523         for (i = 0; i < num_rr_nodes; i++)
00524         {
00525                 x_rr_node_left[i] = -1;
00526                 x_rr_node_right[i] = -1;
00527                 y_rr_node_top[i] = -1;
00528                 y_rr_node_bottom[i] = -1;
00529                 rr_node_color[i] = BLACK;
00530         }
00531     }
00532 
00533 
00534     tile_width = width_val;
00535     pin_size = 0.3;
00536     for(i = 0; i < num_types; ++i)
00537         {
00538             pin_size =
00539                 min(pin_size,
00540                     (tile_width / (4.0 * type_descriptors[i].num_pins)));
00541         }
00542 
00543     j = 0;
00544     for(i = 0; i < (nx + 1); i++)
00545         {
00546             tile_x[i] = (i * tile_width) + j;
00547             j += chan_width_y[i] + 1;   /* N wires need N+1 units of space */
00548         }
00549     tile_x[nx + 1] = ((nx + 1) * tile_width) + j;
00550 
00551     j = 0;
00552     for(i = 0; i < (ny + 1); ++i)
00553         {
00554             tile_y[i] = (i * tile_width) + j;
00555             j += chan_width_x[i] + 1;
00556         }
00557     tile_y[ny + 1] = ((ny + 1) * tile_width) + j;
00558 
00559     init_world(0.0,
00560                tile_y[ny + 1] + tile_width, tile_x[nx + 1] + tile_width, 0.0);
00561 }
00562 
00563 
00564 /** Draws the blocks placed on the proper clbs.  Occupied blocks are darker colours 
00565  * while empty ones are lighter colours and have a dashed border.      
00566  */
00567 static void
00568 drawplace(void)
00569 {
00570     float sub_tile_step;
00571     float x1, y1, x2, y2;
00572     int i, j, k, bnum;
00573     int num_sub_tiles;
00574     int height;
00575 
00576     setlinewidth(0);
00577 
00578     for(i = 0; i <= (nx + 1); i++)
00579         {
00580             for(j = 0; j <= (ny + 1); j++)
00581                 {
00582                     /* Only the first block of a group should control drawing */
00583                     if(grid[i][j].offset > 0)
00584                         continue;
00585 
00586                     /* Don't draw corners */
00587                     if(((i < 1) || (i > nx)) && ((j < 1) || (j > ny)))
00588                         continue;
00589 
00590                     num_sub_tiles = grid[i][j].type->capacity;
00591                     sub_tile_step = tile_width / num_sub_tiles;
00592                     height = grid[i][j].type->height;
00593 
00594                     if(num_sub_tiles < 1)
00595                         {
00596                             setcolor(BLACK);
00597                             setlinestyle(DASHED);
00598                             drawrect(tile_x[i], tile_y[j],
00599                                      tile_x[i] + tile_width,
00600                                      tile_y[j] + tile_width);
00601                             draw_x(tile_x[i] + (tile_width / 2),
00602                                    tile_y[j] + (tile_width / 2),
00603                                    (tile_width / 2));
00604                         }
00605 
00606                     for(k = 0; k < num_sub_tiles; ++k)
00607                         {
00608                             /* Graphics will look unusual for multiple height and capacity */
00609                             assert(height == 1 || num_sub_tiles == 1);
00610                             /* Get coords of current sub_tile */
00611                             if((i < 1) || (i > nx))
00612                                 {       /* left and right fringes */
00613                                     x1 = tile_x[i];
00614                                     y1 = tile_y[j] + (k * sub_tile_step);
00615                                     x2 = x1 + tile_width;
00616                                     y2 = y1 + sub_tile_step;
00617                                 }
00618                             else if((j < 1) || (j > ny))
00619                                 {       /* top and bottom fringes */
00620                                     x1 = tile_x[i] + (k * sub_tile_step);
00621                                     y1 = tile_y[j];
00622                                     x2 = x1 + sub_tile_step;
00623                                     y2 = y1 + tile_width;
00624                                 }
00625                             else
00626                                 {
00627                                     assert(num_sub_tiles <= 1); /* Need to change draw code to support */
00628 
00629                                     x1 = tile_x[i];
00630                                     y1 = tile_y[j];
00631                                     x2 = x1 + tile_width;
00632                                     y2 = tile_y[j + height - 1] + tile_width;
00633                                 }
00634 
00635                             /* Look at the tile at start of large block */
00636                             bnum = grid[i][j].blocks[k];
00637 
00638 
00639                             /* Draw background */
00640                             if(bnum != EMPTY)
00641                                 {
00642                                     setcolor(block_color[bnum]);
00643                                     fillrect(x1, y1, x2, y2);
00644                                 } else { 
00645                                         /* colour empty blocks a particular colour depending on type  */
00646                                         if(grid[i][j].type->index < 3) {
00647                                                 setcolor(WHITE);
00648                                         } else if(grid[i][j].type->index < 3 + MAX_BLOCK_COLOURS) {
00649                                                 setcolor(BISQUE + grid[i][j].type->index - 3);
00650                                         } else {
00651                                                 setcolor(BISQUE + MAX_BLOCK_COLOURS - 1);
00652                                         }
00653                                         fillrect(x1, y1, x2, y2);
00654                                 }
00655 
00656                             setcolor(BLACK);
00657 
00658                             setlinestyle((EMPTY == bnum) ? DASHED : SOLID);
00659                             drawrect(x1, y1, x2, y2);
00660 
00661                             /* Draw text if the space has parts of the netlist */
00662                             if(bnum != EMPTY)
00663                                 {
00664                                     drawtext((x1 + x2) / 2.0, (y1 + y2) / 2.0,
00665                                              block[bnum].name, tile_width);
00666                                 }
00667 
00668                                 /* Draw text for block type so that user knows what block */
00669                                 if(grid[i][j].offset == 0) {
00670                                         if(i > 0 && i <= nx && j > 0 && j <= ny) {
00671                                                 drawtext((x1 + x2) / 2.0, y1 + (tile_width / 4.0),
00672                                                         grid[i][j].type->name, tile_width);
00673                                         }
00674                                 }
00675                         }
00676                 }
00677         }
00678 }
00679 
00680 
00681 /** This routine draws the nets on the placement.  The nets have not 
00682  * yet been routed, so we just draw a chain showing a possible path 
00683  * for each net.  This gives some idea of future congestion.        
00684  */
00685 static void
00686 drawnets(void)
00687 {
00688     int inet, ipin, b1, b2;
00689     float x1, y1, x2, y2;
00690 
00691     setlinestyle(SOLID);
00692     setlinewidth(0);
00693 
00694     /* Draw the net as a star from the source to each sink. Draw from centers of *
00695      * blocks (or sub blocks in the case of IOs).                                */
00696 
00697     for(inet = 0; inet < num_nets; inet++)
00698         {
00699             if(clb_net[inet].is_global)
00700                 continue;       /* Don't draw global nets. */
00701 
00702             setcolor(net_color[inet]);
00703             b1 = clb_net[inet].node_block[0];   /* The DRIVER */
00704             get_block_center(b1, &x1, &y1);
00705 
00706             for(ipin = 1; ipin < (clb_net[inet].num_sinks + 1); ipin++)
00707                 {
00708                     b2 = clb_net[inet].node_block[ipin];
00709                     get_block_center(b2, &x2, &y2);
00710                     drawline(x1, y1, x2, y2);
00711 
00712                     /* Uncomment to draw a chain instead of a star. */
00713                     /*      x1 = x2;  */
00714                     /*      y1 = y2;  */
00715                 }
00716         }
00717 }
00718 
00719 
00720 /** This routine finds the center of block bnum in the current placement, 
00721  * and returns it in *x and *y.  This is used in routine shownets.       
00722  */
00723 static void
00724 get_block_center(int bnum,
00725                  float *x,
00726                  float *y)
00727 {
00728 
00729     int i, j, k;
00730     float sub_tile_step;
00731 
00732     i = block[bnum].x;
00733     j = block[bnum].y;
00734     k = block[bnum].z;
00735 
00736     sub_tile_step = tile_width / block[bnum].type->capacity;
00737 
00738     if((i < 1) || (i > nx))
00739         {                       /* Left and right fringe */
00740             *x = tile_x[i] + (sub_tile_step * (k + 0.5));
00741         }
00742     else
00743         {
00744             *x = tile_x[i] + (tile_width / 2.0);
00745         }
00746 
00747     if((j < 1) || (j > ny))
00748         {                       /* Top and bottom fringe */
00749             *y = tile_y[j] + (sub_tile_step * (k + 0.5));
00750         }
00751     else
00752         {
00753             *y = tile_y[j] + (tile_width / 2.0);
00754         }
00755 }
00756 
00757 /** Draws all the overused routing resources (i.e. congestion) in RED.   */
00758 static void
00759 draw_congestion(void)
00760 {
00761     int inode, itrack;
00762 
00763     setcolor(RED);
00764     setlinewidth(2);
00765 
00766     for(inode = 0; inode < num_rr_nodes; inode++)
00767         {
00768             if(rr_node[inode].occ > rr_node[inode].capacity)
00769                 {
00770                     switch (rr_node[inode].type)
00771                         {
00772                         case CHANX:
00773                             itrack = rr_node[inode].ptc_num;
00774                             draw_rr_chanx(inode, itrack);
00775                             break;
00776 
00777                         case CHANY:
00778                             itrack = rr_node[inode].ptc_num;
00779                             draw_rr_chany(inode, itrack);
00780                             break;
00781 
00782                         case IPIN:
00783                         case OPIN:
00784                             draw_rr_pin(inode, RED);
00785                             break;
00786                         default:
00787                                 break;
00788                         }
00789                 }
00790         }
00791 }
00792 
00793 
00794 /** Draws the routing resources that exist in the FPGA, if the user wants 
00795  * them drawn.                                                           
00796  */
00797 void
00798 draw_rr(void)
00799 {
00800     int inode, itrack;
00801 
00802     if(draw_rr_toggle == DRAW_NO_RR)
00803         {
00804             setlinewidth(3);
00805             drawroute(HIGHLIGHTED);
00806             setlinewidth(0);
00807             return;
00808         }
00809 
00810     setlinestyle(SOLID);
00811     setlinewidth(0);
00812 
00813     for(inode = 0; inode < num_rr_nodes; inode++)
00814         {
00815             switch (rr_node[inode].type)
00816                 {
00817 
00818                 case SOURCE:
00819                 case SINK:
00820                     break;      /* Don't draw. */
00821 
00822                 case CHANX:
00823                     if(show_defects && (rr_node[inode].capacity <= 0))
00824                             setcolor(RED);
00825                     else
00826                             setcolor(BLACK);
00827                     if(show_defects && (rr_node[inode].occ > 0))
00828                             setcolor(CYAN);
00829                     itrack = rr_node[inode].ptc_num;
00830                     draw_rr_chanx(inode, itrack);
00831                     draw_rr_edges(inode);
00832                     break;
00833 
00834                 case CHANY:
00835                     if(show_defects && (rr_node[inode].capacity <= 0))
00836                             setcolor(RED);
00837                     else
00838                             setcolor (BLACK);
00839                     if(show_defects && (rr_node[inode].occ > 0))
00840                             setcolor(CYAN);
00841                     itrack = rr_node[inode].ptc_num;
00842                     draw_rr_chany(inode, itrack);
00843                     draw_rr_edges(inode);
00844                     break;
00845 
00846                 case IPIN:
00847                     if(show_defects)
00848                     {
00849                             if(rr_node[inode].capacity < 0)
00850                                     draw_rr_pin(inode, RED);
00851                             else if(rr_node[inode].occ > 0)
00852                                     draw_rr_pin(inode, CYAN);
00853                             else
00854                                     draw_rr_pin(inode, BLACK);
00855                     }
00856                     else
00857                             draw_rr_pin(inode, BLUE);
00858                     break;
00859 
00860                 case OPIN:
00861                     if(show_defects)
00862                     {
00863                             if(rr_node[inode].capacity < 0)
00864                                     draw_rr_pin(inode, RED);
00865                             else if(rr_node[inode].occ > 0)
00866                                     draw_rr_pin(inode, CYAN);
00867                             else
00868                                     draw_rr_pin(inode, BLACK);
00869                             setcolor(BLACK);
00870                     }
00871                     else
00872                     {
00873                             draw_rr_pin(inode, RED);
00874                             setcolor(RED);
00875                     }
00876                     setcolor(RED);
00877                     draw_rr_edges(inode);
00878                     break;
00879 
00880                 default:
00881                     printf
00882                         ("Error in draw_rr:  Unexpected rr_node type: %d.\n",
00883                          rr_node[inode].type);
00884                     exit(1);
00885                 }
00886         }
00887 
00888     setlinewidth(3);
00889     drawroute(HIGHLIGHTED);
00890     setlinewidth(0);
00891 }
00892 
00893 
00894 /** Draws an x-directed channel segment.                       */
00895 static void
00896 draw_rr_chanx(int inode,
00897               int itrack)
00898 {
00899     enum
00900     { BUFFSIZE = 80 };
00901     float x1, x2, y;
00902     float y1, y2;               /* UDSD by AY */
00903     int k;                      /* UDSD by AY */
00904     char str[BUFFSIZE];
00905         int savecolor;
00906 
00907     /* Track 0 at bottom edge, closest to "owning" clb. */
00908 
00909     x1 = tile_x[rr_node[inode].xlow];
00910     x2 = tile_x[rr_node[inode].xhigh] + tile_width;
00911     y = tile_y[rr_node[inode].ylow] + tile_width + 1.0 + itrack;
00912     x_rr_node_left[inode] = x1;
00913     x_rr_node_right[inode] = x2;
00914     y_rr_node_bottom[inode] = y - line_fuz;
00915     y_rr_node_top[inode] = y + line_fuz;
00916     if(rr_node_color[inode] != BLACK)
00917     {
00918             savecolor=getcolor();
00919             setcolor(rr_node_color[inode]);
00920             setlinewidth(3);
00921             drawline(x1, y, x2, y);
00922             setlinewidth(0);
00923             setcolor(savecolor);
00924     }
00925     else
00926     {
00927             drawline(x1, y, x2, y);
00928     }
00929     /* UDSD by AY Start */
00930     y1 = y - 0.25;
00931     y2 = y + 0.25;
00932 
00933     if(rr_node[inode].direction == INC_DIRECTION)
00934         {
00935             setlinewidth(2);
00936             setcolor(YELLOW);
00937             drawline(x1, y1, x1, y2);   /* Draw a line at start of wire to indicate mux */
00938 
00939             /* Mux balence numbers */
00940             setcolor(BLACK);
00941             sprintf(str, "%d", rr_node[inode].fan_in);
00942             drawtext(x1, y, str, 5);
00943 
00944             setcolor(BLACK);
00945             setlinewidth(0);
00946             draw_triangle_along_line(x2 - 0.15, y, x1, x2, y, y);
00947 
00948             setcolor(LIGHTGREY);
00949             /* TODO: this looks odd, why does it ignore final block? does this mean nothing appears with L=1 ? */
00950             for(k = rr_node[inode].xlow; k < rr_node[inode].xhigh; k++)
00951                 {
00952                     x2 = tile_x[k] + tile_width;
00953                     draw_triangle_along_line(x2 - 0.15, y, x1, x2, y, y);
00954                     x2 = tile_x[k + 1];
00955                     draw_triangle_along_line(x2 + 0.15, y, x1, x2, y, y);
00956                 }
00957             setcolor(BLACK);
00958         }
00959     else if(rr_node[inode].direction == DEC_DIRECTION)
00960         {
00961             setlinewidth(2);
00962             setcolor(YELLOW);
00963             drawline(x2, y1, x2, y2);
00964 
00965             /* Mux balance numbers */
00966             setcolor(BLACK);
00967             sprintf(str, "%d", rr_node[inode].fan_in);
00968             drawtext(x2, y, str, 5);
00969 
00970             setlinewidth(0);
00971             draw_triangle_along_line(x1 + 0.15, y, x2, x1, y, y);
00972             setcolor(LIGHTGREY);
00973             for(k = rr_node[inode].xhigh; k > rr_node[inode].xlow; k--)
00974                 {
00975                     x1 = tile_x[k];
00976                     draw_triangle_along_line(x1 + 0.15, y, x2, x1, y, y);
00977                     x1 = tile_x[k - 1] + tile_width;
00978                     draw_triangle_along_line(x1 - 0.15, y, x2, x1, y, y);
00979                 }
00980             setcolor(BLACK);
00981         }
00982     /* UDSD by AY End */
00983 }
00984 
00985 
00986 /** Draws a y-directed channel segment.                       */
00987 static void
00988 draw_rr_chany(int inode,
00989               int itrack)
00990 {
00991     enum
00992     { BUFFSIZE = 80 };
00993     float x, y1, y2;
00994     float x1, x2;               /* UDSD by AY */
00995     int k;                      /* UDSD by AY */
00996     char str[BUFFSIZE];
00997         int savecolor;
00998 
00999     /* Track 0 at left edge, closest to "owning" clb. */
01000 
01001     x = tile_x[rr_node[inode].xlow] + tile_width + 1. + itrack;
01002     y1 = tile_y[rr_node[inode].ylow];
01003     y2 = tile_y[rr_node[inode].yhigh] + tile_width;
01004     x_rr_node_left[inode] = x - line_fuz;
01005     x_rr_node_right[inode] = x + line_fuz;
01006     y_rr_node_bottom[inode] = y1;
01007     y_rr_node_top[inode] = y2;
01008     if(rr_node_color[inode] != BLACK)
01009     {
01010             savecolor=getcolor();
01011             setcolor(rr_node_color[inode]);
01012             setlinewidth(3);
01013             drawline(x, y1, x, y2);
01014             setlinewidth(0);
01015             setcolor(savecolor);
01016     }
01017     else
01018     {
01019             drawline(x, y1, x, y2);
01020     }
01021 
01022     /* UDSD by AY Start */
01023     x1 = x - 0.25;
01024     x2 = x + 0.25;
01025     if(rr_node[inode].direction == INC_DIRECTION)
01026         {
01027             setlinewidth(2);
01028             setcolor(YELLOW);
01029             drawline(x1, y1, x2, y1);
01030 
01031             /* UDSD Modifications by WMF Begin */
01032             setcolor(BLACK);
01033             sprintf(str, "%d", rr_node[inode].fan_in);
01034             drawtext(x, y1, str, 5);
01035             setcolor(BLACK);
01036             /* UDSD Modifications by WMF End */
01037 
01038             setlinewidth(0);
01039             draw_triangle_along_line(x, y2 - 0.15, x, x, y1, y2);
01040             setcolor(LIGHTGREY);
01041             for(k = rr_node[inode].ylow; k < rr_node[inode].yhigh; k++)
01042                 {
01043                     y2 = tile_y[k] + tile_width;
01044                     draw_triangle_along_line(x, y2 - 0.15, x, x, y1, y2);
01045                     y2 = tile_y[k + 1];
01046                     draw_triangle_along_line(x, y2 + 0.15, x, x, y1, y2);
01047                 }
01048             setcolor(BLACK);
01049         }
01050     else if(rr_node[inode].direction == DEC_DIRECTION)
01051         {
01052             setlinewidth(2);
01053             setcolor(YELLOW);
01054             drawline(x1, y2, x2, y2);
01055 
01056             /* UDSD Modifications by WMF Begin */
01057             setcolor(BLACK);
01058             sprintf(str, "%d", rr_node[inode].fan_in);
01059             drawtext(x, y2, str, 5);
01060             setcolor(BLACK);
01061             /* UDSD Modifications by WMF End */
01062 
01063             setlinewidth(0);
01064             draw_triangle_along_line(x, y1 + 0.15, x, x, y2, y1);
01065             setcolor(LIGHTGREY);
01066             for(k = rr_node[inode].yhigh; k > rr_node[inode].ylow; k--)
01067                 {
01068                     y1 = tile_y[k];
01069                     draw_triangle_along_line(x, y1 + 0.15, x, x, y2, y1);
01070                     y1 = tile_y[k - 1] + tile_width;
01071                     draw_triangle_along_line(x, y1 - 0.15, x, x, y2, y1);
01072                 }
01073             setcolor(BLACK);
01074         }
01075     /* UDSD by AY End */
01076 }
01077 
01078 
01079 /** Draws all the edges that the user wants shown between inode and what it 
01080  * connects to.  inode is assumed to be a CHANX, CHANY, or OPIN.           
01081  */
01082 static void
01083 draw_rr_edges(int inode)
01084 {
01085 
01086     t_rr_type from_type, to_type;
01087     int iedge, to_node, from_ptc_num, to_ptc_num;
01088     short switch_type;
01089     boolean defective=FALSE;
01090 
01091     from_type = rr_node[inode].type;
01092 
01093     if((draw_rr_toggle == DRAW_NODES_RR) ||
01094        (draw_rr_toggle == DRAW_NODES_AND_SBOX_RR && from_type == OPIN))
01095         {
01096             return;             /* Nothing to draw. */
01097         }
01098 
01099     from_ptc_num = rr_node[inode].ptc_num;
01100 
01101     for(iedge = 0; iedge < rr_node[inode].num_edges; iedge++)
01102         {
01103             to_node = rr_node[inode].edges[iedge];
01104             to_type = rr_node[to_node].type;
01105             to_ptc_num = rr_node[to_node].ptc_num;
01106 
01107             if(show_defects)
01108                     defective = (switch_inf[rr_node[inode].switches[iedge]].R < 0);
01109             switch (from_type)
01110                 {
01111 
01112                 case OPIN:
01113                     switch (to_type)
01114                         {
01115                         case CHANX:
01116                         case CHANY:
01117                                 if(show_defects)
01118                                 {
01119                                         if(defective)
01120                                                 setcolor(RED);
01121                                         else
01122                                                 setcolor(BLACK);
01123                                 }
01124                                 else
01125                                         setcolor(RED);
01126                                 draw_pin_to_chan_edge(inode, to_node);
01127                                 break;
01128 
01129                         default:
01130                             printf
01131                                 ("Error in draw_rr_edges:  node %d (type: %d) connects to \n"
01132                                  "node %d (type: %d).\n", inode, from_type,
01133                                  to_node, to_type);
01134                             exit(1);
01135                             break;
01136                         }
01137                     break;
01138 
01139                 case CHANX:     /* from_type */
01140                     switch (to_type)
01141                         {
01142                         case IPIN:
01143                             if(draw_rr_toggle == DRAW_NODES_AND_SBOX_RR)
01144                                 {
01145                                     break;
01146                                 }
01147 
01148                             if(show_defects)
01149                             {
01150                                     if(defective)
01151                                             setcolor(RED);
01152                                     else
01153                                             setcolor(BLACK);
01154                             }
01155                             else
01156                                     setcolor(BLUE);
01157                             draw_pin_to_chan_edge(to_node, inode);
01158                             break;
01159 
01160                         case CHANX:
01161                             if(show_defects)
01162                             {
01163                                     if(defective)
01164                                             setcolor(RED);
01165                                     else
01166                                             setcolor(BLACK);
01167                             }
01168                             else
01169                                     setcolor(DARKGREEN);
01170                             switch_type = rr_node[inode].switches[iedge];
01171                             draw_chanx_to_chanx_edge(inode, from_ptc_num,
01172                                                      to_node, to_ptc_num,
01173                                                      switch_type);
01174                             break;
01175 
01176                         case CHANY:
01177                             if(show_defects)
01178                             {
01179                                     if(defective)
01180                                             setcolor(RED);
01181                                     else
01182                                             setcolor(BLACK);
01183                             }
01184                             else
01185                                     setcolor(DARKGREEN);
01186                             switch_type = rr_node[inode].switches[iedge];
01187                             draw_chanx_to_chany_edge(inode, from_ptc_num,
01188                                                      to_node, to_ptc_num,
01189                                                      FROM_X_TO_Y,
01190                                                      switch_type);
01191                             break;
01192 
01193                         default:
01194                             printf
01195                                 ("Error in draw_rr_edges:  node %d (type: %d) connects to \n"
01196                                  "node %d (type: %d).\n", inode, from_type,
01197                                  to_node, to_type);
01198                             exit(1);
01199                             break;
01200                         }
01201                     break;
01202 
01203 
01204                 case CHANY:     /* from_type */
01205                     switch (to_type)
01206                         {
01207                         case IPIN:
01208                             if(draw_rr_toggle == DRAW_NODES_AND_SBOX_RR)
01209                                 {
01210                                     break;
01211                                 }
01212 
01213                             if(show_defects)
01214                             {
01215                                     if(defective)
01216                                             setcolor(RED);
01217                                     else
01218                                             setcolor(BLACK);
01219                             }
01220                             else
01221                                     setcolor(BLUE);
01222                             draw_pin_to_chan_edge(to_node, inode);
01223                             break;
01224 
01225                         case CHANX:
01226                             if(show_defects)
01227                             {
01228                                     if(defective)
01229                                             setcolor(RED);
01230                                     else
01231                                             setcolor(BLACK);
01232                             }
01233                             else
01234                                     setcolor(DARKGREEN);
01235                             switch_type = rr_node[inode].switches[iedge];
01236                             draw_chanx_to_chany_edge(to_node, to_ptc_num,
01237                                                      inode, from_ptc_num,
01238                                                      FROM_Y_TO_X,
01239                                                      switch_type);
01240                             break;
01241 
01242                         case CHANY:
01243                             if(show_defects)
01244                             {
01245                                     if(defective)
01246                                             setcolor(RED);
01247                                     else
01248                                             setcolor(BLACK);
01249                             }
01250                             else
01251                                     setcolor(DARKGREEN);
01252                             switch_type = rr_node[inode].switches[iedge];
01253                             draw_chany_to_chany_edge(inode, from_ptc_num,
01254                                                      to_node, to_ptc_num,
01255                                                      switch_type);
01256                             break;
01257 
01258                         default:
01259                             printf
01260                                 ("Error in draw_rr_edges:  node %d (type: %d) connects to \n"
01261                                  "node %d (type: %d).\n", inode, from_type,
01262                                  to_node, to_type);
01263                             exit(1);
01264                             break;
01265                         }
01266                     break;
01267 
01268                 default:        /* from_type */
01269                     printf
01270                         ("Error:  draw_rr_edges called with node %d of type %d.\n",
01271                          inode, from_type);
01272                     exit(1);
01273                     break;
01274                 }
01275         }                       /* End of for each edge loop */
01276 }
01277 
01278 /** Draws an X centered at (x,y).  The width and height of the X are each    
01279  * 2 * size.                                                                
01280  */
01281 static void
01282 draw_x(float x,
01283        float y,
01284        float size)
01285 {
01286 
01287     drawline(x - size, y + size, x + size, y - size);
01288     drawline(x - size, y - size, x + size, y + size);
01289 }
01290 
01291 
01292 /** Draws an edge (SBOX connection) between an x-directed channel and a    
01293  * y-directed channel.                                                    
01294  */
01295 /* UDSD Modifications by WMF: Thank God Andy fixed this. */
01296 static void
01297 draw_chanx_to_chany_edge(int chanx_node,
01298                          int chanx_track,
01299                          int chany_node,
01300                          int chany_track,
01301                          enum e_edge_dir edge_dir,
01302                          short switch_type)
01303 {
01304     float x1, y1, x2, y2;
01305     int chanx_y, chany_x, chanx_xlow, chany_ylow;
01306 
01307     chanx_y = rr_node[chanx_node].ylow;
01308     chanx_xlow = rr_node[chanx_node].xlow;
01309     chany_x = rr_node[chany_node].xlow;
01310     chany_ylow = rr_node[chany_node].ylow;
01311 
01312     /* (x1,y1): point on CHANX segment, (x2,y2): point on CHANY segment. */
01313 
01314     y1 = tile_y[chanx_y] + tile_width + 1. + chanx_track;
01315     x2 = tile_x[chany_x] + tile_width + 1. + chany_track;
01316 
01317     if(chanx_xlow <= chany_x)
01318         {                       /* Can draw connection going right */
01319             x1 = tile_x[chany_x] + tile_width;
01320             /* UDSD by AY Start */
01321             if(rr_node[chanx_node].direction != BI_DIRECTION)
01322                 {
01323                     if(edge_dir == FROM_X_TO_Y)
01324                         {
01325                             if((chanx_track % 2) == 1)
01326                                 {       /* UDSD Modifications by WMF: If dec wire, then going left */
01327                                     x1 = tile_x[chany_x + 1];
01328                                 }
01329                         }
01330                 }
01331             /* UDSD by AY End */
01332         }
01333     else
01334         {                       /* Must draw connection going left. */
01335             x1 = tile_x[chanx_xlow];
01336         }
01337 
01338     if(chany_ylow <= chanx_y)
01339         {                       /* Can draw connection going up. */
01340             y2 = tile_y[chanx_y] + tile_width;
01341             /* UDSD by AY Start */
01342             if(rr_node[chany_node].direction != BI_DIRECTION)
01343                 {
01344                     if(edge_dir == FROM_Y_TO_X)
01345                         {
01346                             if((chany_track % 2) == 1)
01347                                 {       /* UDSD Modifications by WMF: If dec wire, then going down */
01348                                     y2 = tile_y[chanx_y + 1];
01349                                 }
01350                         }
01351                 }
01352             /* UDSD by AY End */
01353         }
01354     else
01355         {                       /* Must draw connection going down. */
01356             y2 = tile_y[chany_ylow];
01357         }
01358 
01359     drawline(x1, y1, x2, y2);
01360 
01361     if(draw_rr_toggle != DRAW_ALL_RR)
01362         return;
01363 
01364     if(edge_dir == FROM_X_TO_Y)
01365         draw_rr_switch(x1, y1, x2, y2, switch_inf[switch_type].buffered);
01366     else
01367         draw_rr_switch(x2, y2, x1, y1, switch_inf[switch_type].buffered);
01368 }
01369 
01370 
01371 /** Draws a connection between two x-channel segments.  Passing in the track 
01372  * numbers allows this routine to be used for both rr_graph and routing     
01373  * drawing.                                                                 
01374  */
01375 static void
01376 draw_chanx_to_chanx_edge(int from_node,
01377                          int from_track,
01378                          int to_node,
01379                          int to_track,
01380                          short switch_type)
01381 {
01382     float x1, x2, y1, y2;
01383     int from_y, to_y, from_xlow, to_xlow, from_xhigh, to_xhigh;
01384 
01385     from_y = rr_node[from_node].ylow;
01386     from_xlow = rr_node[from_node].xlow;
01387     from_xhigh = rr_node[from_node].xhigh;
01388     to_y = rr_node[to_node].ylow;
01389     to_xlow = rr_node[to_node].xlow;
01390     to_xhigh = rr_node[to_node].xhigh;
01391 
01392 /* (x1, y1) point on from_node, (x2, y2) point on to_node. */
01393 
01394     y1 = tile_y[from_y] + tile_width + 1 + from_track;
01395     y2 = tile_y[to_y] + tile_width + 1 + to_track;
01396 
01397 
01398     if(to_xhigh < from_xlow)
01399         {                       /* From right to left */
01400             /* UDSD Note by WMF: could never happen for INC wires, unless U-turn. For DEC 
01401              * wires this handles well */
01402             x1 = tile_x[from_xlow];
01403             x2 = tile_x[to_xhigh] + tile_width;
01404         }
01405     else if(to_xlow > from_xhigh)
01406         {                       /* From left to right */
01407             /* UDSD Note by WMF: could never happen for DEC wires, unless U-turn. For INC 
01408              * wires this handles well */
01409             x1 = tile_x[from_xhigh] + tile_width;
01410             x2 = tile_x[to_xlow];
01411         }
01412 
01413 /* Segments overlap in the channel.  Figure out best way to draw.  Have to  *
01414  * make sure the drawing is symmetric in the from rr and to rr so the edges *
01415  * will be drawn on top of each other for bidirectional connections.        */
01416 
01417     /* UDSD Modification by WMF Begin */
01418     else
01419         {
01420             if(rr_node[to_node].direction != BI_DIRECTION)
01421                 {
01422                     /* must connect to to_node's wire beginning at x2 */
01423                     if(to_track % 2 == 0)
01424                         {       /* INC wire starts at leftmost edge */
01425                             assert(from_xlow < to_xlow);
01426                             x2 = tile_x[to_xlow];
01427                             /* since no U-turns from_track must be INC as well */
01428                             x1 = tile_x[to_xlow - 1] + tile_width;
01429                         }
01430                     else
01431                         {       /* DEC wire starts at rightmost edge */
01432                             assert(from_xhigh > to_xhigh);
01433                             x2 = tile_x[to_xhigh] + tile_width;
01434                             x1 = tile_x[to_xhigh + 1];
01435                         }
01436                 }
01437             else
01438                 {
01439                     if(to_xlow < from_xlow)
01440                         {       /* Draw from left edge of one to other */
01441                             x1 = tile_x[from_xlow];
01442                             x2 = tile_x[from_xlow - 1] + tile_width;
01443                         }
01444                     else if(from_xlow < to_xlow)
01445                         {
01446                             x1 = tile_x[to_xlow - 1] + tile_width;
01447                             x2 = tile_x[to_xlow];
01448                         }       /* The following then is executed when from_xlow == to_xlow */
01449                     else if(to_xhigh > from_xhigh)
01450                         {       /* Draw from right edge of one to other */
01451                             x1 = tile_x[from_xhigh] + tile_width;
01452                             x2 = tile_x[from_xhigh + 1];
01453                         }
01454                     else if(from_xhigh > to_xhigh)
01455                         {
01456                             x1 = tile_x[to_xhigh + 1];
01457                             x2 = tile_x[to_xhigh] + tile_width;
01458                         }
01459                     else
01460                         {       /* Complete overlap: start and end both align. Draw outside the sbox */
01461                             x1 = tile_x[from_xlow];
01462                             x2 = tile_x[from_xlow] + tile_width;
01463                         }
01464                 }
01465         }
01466     /* UDSD Modification by WMF End */
01467     drawline(x1, y1, x2, y2);
01468 
01469     if(draw_rr_toggle == DRAW_ALL_RR)
01470         draw_rr_switch(x1, y1, x2, y2, switch_inf[switch_type].buffered);
01471 }
01472 
01473 
01474 /** Draws a connection between two y-channel segments.  Passing in the track 
01475  * numbers allows this routine to be used for both rr_graph and routing     
01476  * drawing.                                                                 
01477  */
01478 static void
01479 draw_chany_to_chany_edge(int from_node,
01480                          int from_track,
01481                          int to_node,
01482                          int to_track,
01483                          short switch_type)
01484 {
01485     float x1, x2, y1, y2;
01486     int from_x, to_x, from_ylow, to_ylow, from_yhigh, to_yhigh;
01487 
01488     from_x = rr_node[from_node].xlow;
01489     from_ylow = rr_node[from_node].ylow;
01490     from_yhigh = rr_node[from_node].yhigh;
01491     to_x = rr_node[to_node].xlow;
01492     to_ylow = rr_node[to_node].ylow;
01493     to_yhigh = rr_node[to_node].yhigh;
01494 
01495 /* (x1, y1) point on from_node, (x2, y2) point on to_node. */
01496 
01497     x1 = tile_x[from_x] + tile_width + 1 + from_track;
01498     x2 = tile_x[to_x] + tile_width + 1 + to_track;
01499 
01500     if(to_yhigh < from_ylow)
01501         {                       /* From upper to lower */
01502             y1 = tile_y[from_ylow];
01503             y2 = tile_y[to_yhigh] + tile_width;
01504         }
01505     else if(to_ylow > from_yhigh)
01506         {                       /* From lower to upper */
01507             y1 = tile_y[from_yhigh] + tile_width;
01508             y2 = tile_y[to_ylow];
01509         }
01510 
01511 /* Segments overlap in the channel.  Figure out best way to draw.  Have to  *
01512  * make sure the drawing is symmetric in the from rr and to rr so the edges *
01513  * will be drawn on top of each other for bidirectional connections.        */
01514 
01515     /* UDSD Modification by WMF Begin */
01516     else
01517         {
01518             if(rr_node[to_node].direction != BI_DIRECTION)
01519                 {
01520                     if(to_track % 2 == 0)
01521                         {       /* INC wire starts at bottom edge */
01522                             assert(from_ylow < to_ylow);
01523                             y2 = tile_y[to_ylow];
01524                             /* since no U-turns from_track must be INC as well */
01525                             y1 = tile_y[to_ylow - 1] + tile_width;
01526                         }
01527                     else
01528                         {       /* DEC wire starts at top edge */
01529                             if(!(from_yhigh > to_yhigh))
01530                                 {
01531                                     printf
01532                                         ("from_yhigh (%d) !> to_yhigh (%d).\n",
01533                                          from_yhigh, to_yhigh);
01534                                     printf
01535                                         ("from is (%d, %d) to (%d, %d) track %d.\n",
01536                                          rr_node[from_node].xhigh,
01537                                          rr_node[from_node].yhigh,
01538                                          rr_node[from_node].xlow,
01539                                          rr_node[from_node].ylow,
01540                                          rr_node[from_node].ptc_num);
01541                                     printf
01542                                         ("to is (%d, %d) to (%d, %d) track %d.\n",
01543                                          rr_node[to_node].xhigh,
01544                                          rr_node[to_node].yhigh,
01545                                          rr_node[to_node].xlow,
01546                                          rr_node[to_node].ylow,
01547                                          rr_node[to_node].ptc_num);
01548                                     exit(1);
01549                                 }
01550                             y2 = tile_y[to_yhigh] + tile_width;
01551                             y1 = tile_y[to_yhigh + 1];
01552                         }
01553                 }
01554             else
01555                 {
01556                     if(to_ylow < from_ylow)
01557                         {       /* Draw from bottom edge of one to other. */
01558                             y1 = tile_y[from_ylow];
01559                             y2 = tile_y[from_ylow - 1] + tile_width;
01560                         }
01561                     else if(from_ylow < to_ylow)
01562                         {
01563                             y1 = tile_y[to_ylow - 1] + tile_width;
01564                             y2 = tile_y[to_ylow];
01565                         }
01566                     else if(to_yhigh > from_yhigh)
01567                         {       /* Draw from top edge of one to other. */
01568                             y1 = tile_y[from_yhigh] + tile_width;
01569                             y2 = tile_y[from_yhigh + 1];
01570                         }
01571                     else if(from_yhigh > to_yhigh)
01572                         {
01573                             y1 = tile_y[to_yhigh + 1];
01574                             y2 = tile_y[to_yhigh] + tile_width;
01575                         }
01576                     else
01577                         {       /* Complete overlap: start and end both align. Draw outside the sbox */
01578                             y1 = tile_y[from_ylow];
01579                             y2 = tile_y[from_ylow] + tile_width;
01580                         }
01581                 }
01582         }
01583     /* UDSD Modification by WMF End */
01584     drawline(x1, y1, x2, y2);
01585 
01586     if(draw_rr_toggle == DRAW_ALL_RR)
01587         draw_rr_switch(x1, y1, x2, y2, switch_inf[switch_type].buffered);
01588 }
01589 
01590 
01591 /** Draws a buffer (triangle) or pass transistor (circle) on the edge        
01592  * connecting from to to, depending on the status of buffered.  The drawing 
01593  * is closest to the from_node, since it reflects the switch type of from.  
01594  */
01595 static void
01596 draw_rr_switch(float from_x,
01597                float from_y,
01598                float to_x,
01599                float to_y,
01600                boolean buffered)
01601 {
01602     const float switch_rad = 0.15;
01603     float magnitude, xcen, ycen, xdelta, ydelta, xbaseline, ybaseline;
01604     float xunit, yunit;
01605     t_point poly[3];
01606 
01607     xcen = from_x + (to_x - from_x) / 10.;
01608     ycen = from_y + (to_y - from_y) / 10.;
01609 
01610     if(!buffered)
01611         {                       /* Draw a circle for a pass transistor */
01612             drawarc(xcen, ycen, switch_rad, 0., 360.);
01613         }
01614     else
01615         {                       /* Buffer */
01616             xdelta = to_x - from_x;
01617             ydelta = to_y - from_y;
01618             magnitude = sqrt(xdelta * xdelta + ydelta * ydelta);
01619             xunit = xdelta / magnitude;
01620             yunit = ydelta / magnitude;
01621             poly[0].x = xcen + xunit * switch_rad;
01622             poly[0].y = ycen + yunit * switch_rad;
01623             xbaseline = xcen - xunit * switch_rad;
01624             ybaseline = ycen - yunit * switch_rad;
01625 
01626 /* Recall: perpendicular vector to the unit vector along the switch (xv, yv) *
01627  * is (yv, -xv).                                                             */
01628 
01629             poly[1].x = xbaseline + yunit * switch_rad;
01630             poly[1].y = ybaseline - xunit * switch_rad;
01631             poly[2].x = xbaseline - yunit * switch_rad;
01632             poly[2].y = ybaseline + xunit * switch_rad;
01633             fillpoly(poly, 3);
01634         }
01635 }
01636 
01637 
01638 /** Draws an IPIN or OPIN rr_node.  Note that the pin can appear on more    
01639  * than one side of a clb.  Also note that this routine can change the     
01640  * current color to BLACK.                                                 
01641  */
01642 static void
01643 draw_rr_pin(int inode,
01644             enum color_types color)
01645 {
01646     int ipin, i, j, iside, iclass, ioff;
01647     float xcen, ycen;
01648     char str[BUFSIZE];
01649     t_type_ptr type;
01650 
01651     i = rr_node[inode].xlow;
01652     j = rr_node[inode].ylow;
01653     ipin = rr_node[inode].ptc_num;
01654     type = grid[i][j].type;
01655     ioff = grid[i][j].offset;
01656 
01657     setcolor(color);
01658     iclass = type->pin_class[ipin];
01659     /* TODO: This is where we can hide fringe physical pins and also identify globals (hide, color, show) */
01660     for(iside = 0; iside < 4; iside++)
01661         {
01662             if(type->pinloc[grid[i][j].offset][iside][ipin])
01663                 {               /* Pin exists on this side. */
01664                     get_rr_pin_draw_coords(inode, iside, ioff, &xcen, &ycen);
01665                     fillrect(xcen - pin_size, ycen - pin_size,
01666                              xcen + pin_size, ycen + pin_size);
01667                     sprintf(str, "%d", ipin);
01668                     setcolor(BLACK);
01669                     drawtext(xcen, ycen, str, 2 * pin_size);
01670                     setcolor(color);
01671                 }
01672         }
01673 }
01674 
01675 
01676 /** Returns the coordinates at which the center of this pin should be drawn.
01677  * inode gives the node number, and iside gives the side of the clb or pad  
01678  * the physical pin is on.                                                  
01679  */
01680 static void
01681 get_rr_pin_draw_coords(int inode,
01682                        int iside,
01683                        int ioff,
01684                        float *xcen,
01685                        float *ycen)
01686 {
01687 
01688     int i, j, k, ipin, pins_per_sub_tile;
01689     float offset, xc, yc, step;
01690     t_type_ptr type;
01691 
01692     i = rr_node[inode].xlow;
01693     j = rr_node[inode].ylow + ioff;     /* Need correct tile of block */
01694 
01695     xc = tile_x[i];
01696     yc = tile_y[j];
01697 
01698     ipin = rr_node[inode].ptc_num;
01699     type = grid[i][j].type;
01700     pins_per_sub_tile = grid[i][j].type->num_pins / grid[i][j].type->capacity;
01701     k = ipin / pins_per_sub_tile;
01702 
01703     /* Since pins numbers go across all sub_tiles in a block in order
01704      * we can treat as a block box for this step */
01705 
01706     /* For each sub_tile we need and extra padding space */
01707     step = (float)(tile_width) / (float)(type->num_pins + type->capacity);
01708     offset = (ipin + k + 1) * step;
01709 
01710     switch (iside)
01711         {
01712         case LEFT:
01713             yc += offset;
01714             break;
01715 
01716         case RIGHT:
01717             xc += tile_width;
01718             yc += offset;
01719             break;
01720 
01721         case BOTTOM:
01722             xc += offset;
01723             break;
01724 
01725         case TOP:
01726             xc += offset;
01727             yc += tile_width;
01728             break;
01729 
01730         default:
01731             printf("Error in get_rr_pin_draw_coords:  Unexpected iside %d.\n",
01732                    iside);
01733             exit(1);
01734             break;
01735         }
01736 
01737     *xcen = xc;
01738     *ycen = yc;
01739 }
01740 
01741 
01742 /** Draws the nets in the positions fixed by the router.  If draw_net_type is 
01743  * ALL_NETS, draw all the nets.  If it is HIGHLIGHTED, draw only the nets    
01744  * that are not coloured black (useful for drawing over the rr_graph).       
01745  * Next free track in each channel segment if routing is GLOBAL. 
01746  */
01747 static void
01748 drawroute(enum e_draw_net_type draw_net_type)
01749 {
01750 
01751     static int **chanx_track = NULL;    /* [1..nx][0..ny] */
01752     static int **chany_track = NULL;    /* [0..nx][1..ny] */
01753 
01754     int inet, i, j, inode, prev_node, prev_track, itrack;
01755     short switch_type;
01756     struct s_trace *tptr;
01757     t_rr_type rr_type, prev_type;
01758 
01759 
01760     if(draw_route_type == GLOBAL)
01761         {
01762             /* Allocate some temporary storage if it's not already available. */
01763             if(chanx_track == NULL)
01764                 {
01765                     chanx_track =
01766                         (int **)alloc_matrix(1, nx, 0, ny, sizeof(int));
01767                 }
01768 
01769             if(chany_track == NULL)
01770                 {
01771                     chany_track =
01772                         (int **)alloc_matrix(0, nx, 1, ny, sizeof(int));
01773                 }
01774 
01775             for(i = 1; i <= nx; i++)
01776                 for(j = 0; j <= ny; j++)
01777                     chanx_track[i][j] = (-1);
01778 
01779             for(i = 0; i <= nx; i++)
01780                 for(j = 1; j <= ny; j++)
01781                     chany_track[i][j] = (-1);
01782         }
01783 
01784     setlinestyle(SOLID);
01785 
01786 /* Now draw each net, one by one.      */
01787 
01788     for(inet = 0; inet < num_nets; inet++)
01789         {
01790             if(clb_net[inet].is_global) /* Don't draw global nets. */
01791                 continue;
01792 
01793             if(trace_head[inet] == NULL)        /* No routing.  Skip.  (Allows me to draw */
01794                 continue;       /* partially complete routes).            */
01795 
01796             if(draw_net_type == HIGHLIGHTED && net_color[inet] == BLACK)
01797                 continue;
01798 
01799             setcolor(net_color[inet]);
01800             tptr = trace_head[inet];    /* SOURCE to start */
01801             inode = tptr->index;
01802             rr_type = rr_node[inode].type;
01803 
01804 
01805             for(;;)
01806                 {
01807                     prev_node = inode;
01808                     prev_type = rr_type;
01809                     switch_type = tptr->iswitch;
01810                     tptr = tptr->next;
01811                     inode = tptr->index;
01812                     rr_type = rr_node[inode].type;
01813 
01814                     switch (rr_type)
01815                         {
01816 
01817                         case OPIN:
01818                             draw_rr_pin(inode, net_color[inet]);
01819                             break;
01820 
01821                         case IPIN:
01822                             draw_rr_pin(inode, net_color[inet]);
01823                             prev_track =
01824                                 get_track_num(prev_node, chanx_track,
01825                                               chany_track);
01826                             draw_pin_to_chan_edge(inode, prev_node);
01827                             break;
01828 
01829                         case CHANX:
01830                             if(draw_route_type == GLOBAL)
01831                                 chanx_track[rr_node[inode].
01832                                             xlow][rr_node[inode].ylow]++;
01833 
01834                             itrack =
01835                                 get_track_num(inode, chanx_track,
01836                                               chany_track);
01837                             draw_rr_chanx(inode, itrack);
01838 
01839                             switch (prev_type)
01840                                 {
01841 
01842                                 case CHANX:
01843                                     prev_track =
01844                                         get_track_num(prev_node, chanx_track,
01845                                                       chany_track);
01846                                     draw_chanx_to_chanx_edge(prev_node,
01847                                                              prev_track,
01848                                                              inode, itrack,
01849                                                              switch_type);
01850                                     break;
01851 
01852                                 case CHANY:
01853                                     prev_track =
01854                                         get_track_num(prev_node, chanx_track,
01855                                                       chany_track);
01856                                     draw_chanx_to_chany_edge(inode, itrack,
01857                                                              prev_node,
01858                                                              prev_track,
01859                                                              FROM_Y_TO_X,
01860                                                              switch_type);
01861                                     break;
01862 
01863                                 case OPIN:
01864                                     draw_pin_to_chan_edge(prev_node, inode);
01865                                     break;
01866 
01867                                 default:
01868                                     printf
01869                                         ("Error in drawroute:  Unexpected connection from an \n"
01870                                          "rr_node of type %d to one of type %d.\n",
01871                                          prev_type, rr_type);
01872                                     exit(1);
01873                                 }
01874 
01875                             break;
01876 
01877                         case CHANY:
01878                             if(draw_route_type == GLOBAL)
01879                                 chany_track[rr_node[inode].
01880                                             xlow][rr_node[inode].ylow]++;
01881 
01882                             itrack =
01883                                 get_track_num(inode, chanx_track,
01884                                               chany_track);
01885                             draw_rr_chany(inode, itrack);
01886 
01887                             switch (prev_type)
01888                                 {
01889 
01890                                 case CHANX:
01891                                     prev_track =
01892                                         get_track_num(prev_node, chanx_track,
01893                                                       chany_track);
01894                                     draw_chanx_to_chany_edge(prev_node,
01895                                                              prev_track,
01896                                                              inode, itrack,
01897                                                              FROM_X_TO_Y,
01898                                                              switch_type);
01899                                     break;
01900 
01901                                 case CHANY:
01902                                     prev_track =
01903                                         get_track_num(prev_node, chanx_track,
01904                                                       chany_track);
01905                                     draw_chany_to_chany_edge(prev_node,
01906                                                              prev_track,
01907                                                              inode, itrack,
01908                                                              switch_type);
01909                                     break;
01910 
01911                                 case OPIN:
01912                                     draw_pin_to_chan_edge(prev_node, inode);
01913 
01914                                     break;
01915 
01916                                 default:
01917                                     printf
01918                                         ("Error in drawroute:  Unexpected connection from an \n"
01919                                          "rr_node of type %d to one of type %d.\n",
01920                                          prev_type, rr_type);
01921                                     exit(1);
01922                                 }
01923 
01924                             break;
01925 
01926                         default:
01927                             break;
01928 
01929                         }
01930 
01931                     if(rr_type == SINK)
01932                         {       /* Skip the next segment */
01933                             tptr = tptr->next;
01934                             if(tptr == NULL)
01935                                 break;
01936                             inode = tptr->index;
01937                             rr_type = rr_node[inode].type;
01938                         }
01939 
01940                 }               /* End loop over traceback. */
01941         }                       /* End for (each net) */
01942 }
01943 
01944 
01945 /** Returns the track number of this routing resource node.   */
01946 static int
01947 get_track_num(int inode,
01948               int **chanx_track,
01949               int **chany_track)
01950 {
01951     int i, j;
01952     t_rr_type rr_type;
01953 
01954     if(draw_route_type == DETAILED)
01955         return (rr_node[inode].ptc_num);
01956 
01957 /* GLOBAL route stuff below. */
01958 
01959     rr_type = rr_node[inode].type;
01960     i = rr_node[inode].xlow;    /* NB: Global rr graphs must have only unit */
01961     j = rr_node[inode].ylow;    /* length channel segments.                 */
01962 
01963     switch (rr_type)
01964         {
01965         case CHANX:
01966             return (chanx_track[i][j]);
01967 
01968         case CHANY:
01969             return (chany_track[i][j]);
01970 
01971         default:
01972             printf
01973                 ("Error in get_track_num:  unexpected node type %d for node %d."
01974                  "\n", rr_type, inode);
01975             exit(1);
01976         }
01977 }
01978 
01979 static void
01980 highlight_nets(char *message)
01981 {
01982     int inet;
01983     struct s_trace *tptr;
01984 
01985     for(inet = 0; inet < num_nets; inet++)
01986     {
01987             for(tptr = trace_head[inet]; tptr != NULL; tptr = tptr->next)
01988             {
01989                     if(rr_node_color[tptr->index] != BLACK)
01990                     {
01991                             net_color[inet] = rr_node_color[tptr->index];
01992                             sprintf(message, "%s  ||  Net:%d %d", message,inet,
01993                                             trace_head[inet]->index
01994                                    );
01995                             break;
01996                     }
01997             }
01998     }
01999     update_message (message);
02000 }
02001 
02002 static void
02003 highlight_rr_nodes(float x, float y)
02004 {
02005     int inode;
02006     int hit = 0;
02007     char message[250] = "";
02008     int edge;
02009 
02010     if(draw_rr_toggle == DRAW_NO_RR && ! show_nets)
02011     {
02012         update_message(default_message);
02013         drawscreen();
02014         return;
02015     }
02016 
02017     for(inode = 0; inode < num_rr_nodes; inode++)
02018     {
02019         if(x >= x_rr_node_left[inode] &&
02020                 x <= x_rr_node_right[inode] &&
02021                 y >= y_rr_node_bottom[inode] &&
02022                 y <= y_rr_node_top[inode])
02023         {
02024             t_rr_type rr_type = rr_node[inode].type;
02025             int xlow = rr_node[inode].xlow;
02026             int xhigh = rr_node[inode].xhigh;
02027             int ylow = rr_node[inode].ylow;
02028             int yhigh = rr_node[inode].yhigh;
02029             int ptc_num = rr_node[inode].ptc_num;
02030             rr_node_color[inode] = MAGENTA;
02031             sprintf(message, "%s%s %d: %s (%d,%d) -> (%d,%d) track: %d", message,
02032                     (hit?"   |   ":""), inode, name_type[rr_type], xlow,ylow
02033                     , xhigh, yhigh, ptc_num
02034                    );
02035 
02036 #ifdef DEBUG
02037             print_rr_node(stdout, rr_node, inode);
02038 #endif
02039             for(edge = 0; edge < rr_node[inode].num_edges; edge++)
02040             {
02041                 if(rr_node_color[rr_node[inode].edges[edge]] == BLACK &&
02042                         rr_node[rr_node[inode].edges[edge]].capacity >
02043                         rr_node[rr_node[inode].edges[edge]].occ)
02044                     rr_node_color[rr_node[inode].edges[edge]] = GREEN;
02045                 else if(rr_node_color[rr_node[inode].edges[edge]] == BLACK &&
02046                         rr_node[rr_node[inode].edges[edge]].capacity ==
02047                         rr_node[rr_node[inode].edges[edge]].occ)
02048                     rr_node_color[rr_node[inode].edges[edge]] = BLUE;
02049 
02050             }
02051             hit = 1;
02052         }
02053     }
02054 
02055 
02056     if (!hit) {
02057         update_message(default_message);
02058         drawscreen();
02059         return;
02060     }
02061 
02062     if(show_nets)
02063     {
02064         highlight_nets(message);
02065     }else
02066         update_message(message);
02067     drawscreen();
02068 }
02069 
02070 /** This routine is called when the user clicks in the graphics area. 
02071  * It determines if a clb was clicked on.  If one was, it is         
02072  * highlighted in green, it's fanin nets and clbs are highlighted in 
02073  * blue and it's fanout is highlighted in red.  If no clb was        
02074  * clicked on (user clicked on white space) any old highlighting is  
02075  * removed.  Note that even though global nets are not drawn, their  
02076  * fanins and fanouts are highlighted when you click on a block      
02077  * attached to them.                                                 
02078  */
02079 static void
02080 highlight_blocks(float x,
02081                  float y)
02082 {
02083     int i, j, k, hit, bnum, ipin, netnum, fanblk;
02084     int iclass;
02085     float io_step;
02086     t_type_ptr type;
02087     char msg[BUFSIZE];
02088         
02089     deselect_all();
02090 
02091     hit = i = j = k = 0;
02092 
02093     for(i = 0; i <= (nx + 1) && !hit; i++)
02094         {
02095             if(x <= tile_x[i] + tile_width)
02096                 {
02097                         if(x >= tile_x[i]){
02098                             for(j = 0; j <= (ny + 1) && !hit; j++)
02099                                 {
02100                                         if(grid[i][j].offset != 0)
02101                                                 continue;
02102                                         type = grid[i][j].type;
02103                                         if(y <= tile_y[j + type->height - 1] + tile_width)
02104                                         {
02105                                                 if(y >= tile_y[j])
02106                                                         hit = 1;
02107                                         }
02108                                 }
02109 
02110                         }
02111                 }
02112         }
02113         i--;
02114         j--;
02115         
02116     if(!hit)
02117         {
02118             highlight_rr_nodes(x, y);
02119             /* update_message(default_message);
02120                drawscreen(); */
02121             return;
02122         }
02123     type = grid[i][j].type;
02124     hit = 0;
02125 
02126     if(EMPTY_TYPE == type)
02127         {
02128             update_message(default_message);
02129             drawscreen();
02130             return;
02131         }
02132 
02133     /* The user selected the clb at location (i,j). */
02134     io_step = tile_width / type->capacity;
02135 
02136     if((i < 1) || (i > nx))     /* Vertical columns of IOs */
02137         k = (int)((y - tile_y[j]) / io_step);
02138     else
02139         k = (int)((x - tile_x[i]) / io_step);
02140 
02141     assert(k < type->capacity);
02142     if(grid[i][j].blocks[k] == EMPTY)
02143         {
02144             update_message(default_message);
02145             drawscreen();
02146             return;
02147         }
02148     bnum = grid[i][j].blocks[k];
02149 
02150     /* Highlight fanin and fanout. */
02151 
02152     for(k = 0; k < type->num_pins; k++)
02153         {                       /* Each pin on a CLB */
02154             netnum = block[bnum].nets[k];
02155 
02156             if(netnum == OPEN)
02157                 continue;
02158 
02159             iclass = type->pin_class[k];
02160 
02161             if(type->class_inf[iclass].type == DRIVER)
02162                 {               /* Fanout */
02163                     net_color[netnum] = RED;
02164                     for(ipin = 1; ipin <= clb_net[netnum].num_sinks; ipin++)
02165                         {
02166                             fanblk = clb_net[netnum].node_block[ipin];
02167                             block_color[fanblk] = RED;
02168                         }
02169                 }
02170             else
02171                 {               /* This net is fanin to the block. */
02172                     net_color[netnum] = BLUE;
02173                     fanblk = clb_net[netnum].node_block[0];     /* DRIVER to net */
02174                     block_color[fanblk] = BLUE;
02175                 }
02176         }
02177 
02178     block_color[bnum] = GREEN;  /* Selected block. */
02179 
02180     sprintf(msg, "Block %d (%s) at (%d, %d) selected.", bnum,
02181             block[bnum].name, i, j);
02182     update_message(msg);
02183     drawscreen();               /* Need to erase screen. */
02184 }
02185 
02186 
02187 /** Sets the color of all clbs and nets to the default.  */
02188 static void
02189 deselect_all(void)
02190 {
02191     int i;
02192 
02193     /* Create some colour highlighting */
02194     for(i = 0; i < num_blocks; i++) {
02195                 if(block[i].type->index < 3) {
02196                         block_color[i] = LIGHTGREY;
02197                 } else if(block[i].type->index < 3 + MAX_BLOCK_COLOURS) {
02198                         block_color[i] = BISQUE + MAX_BLOCK_COLOURS + block[i].type->index - 3;
02199                 } else {
02200                         block_color[i] = BISQUE + 2 * MAX_BLOCK_COLOURS - 1;
02201                 }
02202         }
02203 
02204     for(i = 0; i < num_nets; i++)
02205             net_color[i] = BLACK;
02206 
02207     for (i = 0; i < num_rr_nodes; i++)
02208             rr_node_color[i] = BLACK;
02209 }
02210 
02211 
02212 /* UDSD by AY Start */
02213 static void
02214 draw_triangle_along_line(float xend,
02215                          float yend,
02216                          float x1,
02217                          float x2,
02218                          float y1,
02219                          float y2)
02220 {
02221     float switch_rad = 0.15;
02222     float xdelta, ydelta;
02223     float magnitude;
02224     float xunit, yunit;
02225     float xbaseline, ybaseline;
02226     t_point poly[3];
02227 
02228     xdelta = x2 - x1;
02229     ydelta = y2 - y1;
02230     magnitude = sqrt(xdelta * xdelta + ydelta * ydelta);
02231     xunit = xdelta / magnitude;
02232     yunit = ydelta / magnitude;
02233 
02234     poly[0].x = xend + xunit * switch_rad;
02235     poly[0].y = yend + yunit * switch_rad;
02236     xbaseline = xend - xunit * switch_rad;
02237     ybaseline = yend - yunit * switch_rad;
02238     poly[1].x = xbaseline + yunit * switch_rad;
02239     poly[1].y = ybaseline - xunit * switch_rad;
02240     poly[2].x = xbaseline - yunit * switch_rad;
02241     poly[2].y = ybaseline + xunit * switch_rad;
02242 
02243     fillpoly(poly, 3);
02244 }
02245 
02246 
02247 /** This routine draws an edge from the pin_node to the chan_node (CHANX or  
02248  * CHANY).  The connection is made to the nearest end of the track instead   
02249  * of perpundicular to the track to symbolize a single-drive connection.     
02250  * If mark_conn is TRUE, draw a box where the pin connects to the track      
02251  * (useful for drawing  the rr graph)                                        
02252  */
02253 static void
02254 draw_pin_to_chan_edge(int pin_node,
02255                       int chan_node)
02256 {
02257 /* TODO: Fix this for global routing, currently for detailed only */
02258 
02259     t_rr_type chan_type;
02260     int grid_x, grid_y, pin_num, chan_xlow, chan_ylow, ioff, height;
02261     float x1, x2, y1, y2;
02262     int start, end, i;
02263     int itrack;
02264     float xend, yend;
02265     float draw_pin_off;
02266     enum e_direction direction;
02267     enum e_side iside;
02268     t_type_ptr type;
02269 
02270     direction = rr_node[chan_node].direction;
02271     grid_x = rr_node[pin_node].xlow;
02272     grid_y = rr_node[pin_node].ylow;
02273     pin_num = rr_node[pin_node].ptc_num;
02274     chan_type = rr_node[chan_node].type;
02275     itrack = rr_node[chan_node].ptc_num;
02276     type = grid[grid_x][grid_y].type;
02277 
02278     ioff = grid[grid_x][grid_y].offset;
02279     /* large block begins at primary tile (offset == 0) */
02280     grid_y = grid_y - ioff;
02281     height = grid[grid_x][grid_y].type->height;
02282     chan_ylow = rr_node[chan_node].ylow;
02283     chan_xlow = rr_node[chan_node].xlow;
02284     start = -1;
02285     end = -1;
02286 
02287 
02288     switch (chan_type)
02289         {
02290 
02291         case CHANX:
02292             start = rr_node[chan_node].xlow;
02293             end = rr_node[chan_node].xhigh;
02294             if(is_opin(pin_num, type))
02295                 {
02296                     if(direction == INC_DIRECTION)
02297                         {
02298                             end = rr_node[chan_node].xlow;
02299                         }
02300                     else if(direction == DEC_DIRECTION)
02301                         {
02302                             start = rr_node[chan_node].xhigh;
02303                         }
02304                 }
02305 
02306             start = max(start, grid_x);
02307             end = min(end, grid_x);     /* Width is 1 always */
02308             assert(end >= start);       /* Make sure we are nearby */
02309 
02310             if((grid_y + height - 1) == chan_ylow)
02311                 {
02312                     iside = TOP;
02313                     ioff = height - 1;
02314                     draw_pin_off = pin_size;
02315                 }
02316             else
02317                 {
02318                     assert((grid_y - 1) == chan_ylow);
02319 
02320                     iside = BOTTOM;
02321                     ioff = 0;
02322                     draw_pin_off = -pin_size;
02323                 }
02324             assert(grid[grid_x][grid_y].type->pinloc[ioff][iside][pin_num]);
02325 
02326             get_rr_pin_draw_coords(pin_node, iside, ioff, &x1, &y1);
02327             y1 += draw_pin_off;
02328 
02329             y2 = tile_y[rr_node[chan_node].ylow] + tile_width + 1. + itrack;
02330             x2 = x1;
02331             if(is_opin(pin_num, type))
02332                 {
02333                     if(direction == INC_DIRECTION)
02334                         {
02335                             x2 = tile_x[rr_node[chan_node].xlow];
02336                         }
02337                     else if(direction == DEC_DIRECTION)
02338                         {
02339                             x2 = tile_x[rr_node[chan_node].xhigh] +
02340                                 tile_width;
02341                         }
02342                 }
02343             break;
02344 
02345         case CHANY:
02346             start = rr_node[chan_node].ylow;
02347             end = rr_node[chan_node].yhigh;
02348             if(is_opin(pin_num, type))
02349                 {
02350                     if(direction == INC_DIRECTION)
02351                         {
02352                             end = rr_node[chan_node].ylow;
02353                         }
02354                     else if(direction == DEC_DIRECTION)
02355                         {
02356                             start = rr_node[chan_node].yhigh;
02357                         }
02358                 }
02359 
02360             start = max(start, grid_y);
02361             end = min(end, (grid_y + height - 1));      /* Width is 1 always */
02362             assert(end >= start);       /* Make sure we are nearby */
02363 
02364             if((grid_x) == chan_xlow)
02365                 {
02366                     iside = RIGHT;
02367                     draw_pin_off = pin_size;
02368                 }
02369             else
02370                 {
02371                     assert((grid_x - 1) == chan_xlow);
02372                     iside = LEFT;
02373                     draw_pin_off = -pin_size;
02374                 }
02375             for(i = start; i <= end; i++)
02376                 {
02377                     ioff = i - grid_y;
02378                     assert(ioff >= 0 && ioff < type->height);
02379                     /* Once we find the location, break out, this will leave ioff pointing
02380                      * to the correct offset.  If an offset is not found, the assertion after
02381                      * this will fail.  With the correct routing graph, the assertion will not
02382                      * be triggered.  This also takes care of connecting a wire once to multiple
02383                      * physical pins on the same side. */
02384                     if(grid[grid_x][grid_y].type->
02385                        pinloc[ioff][iside][pin_num])
02386                         {
02387                             break;
02388                         }
02389                 }
02390             assert(grid[grid_x][grid_y].type->pinloc[ioff][iside][pin_num]);
02391 
02392             get_rr_pin_draw_coords(pin_node, iside, ioff, &x1, &y1);
02393             x1 += draw_pin_off;
02394 
02395             x2 = tile_x[chan_xlow] + tile_width + 1 + itrack;
02396             y2 = y1;
02397             if(is_opin(pin_num, type))
02398                 {
02399                     if(direction == INC_DIRECTION)
02400                         {
02401                             y2 = tile_y[rr_node[chan_node].ylow];
02402                         }
02403                     else if(direction == DEC_DIRECTION)
02404                         {
02405                             y2 = tile_y[rr_node[chan_node].yhigh] +
02406                                 tile_width;
02407                         }
02408                 }
02409             break;
02410 
02411         default:
02412             printf
02413                 ("Error in draw_pin_to_chan_edge:  invalid channel node %d.\n",
02414                  chan_node);
02415             exit(1);
02416         }
02417 
02418     drawline(x1, y1, x2, y2);
02419     if(direction == BI_DIRECTION || !is_opin(pin_num, type))
02420         {
02421             draw_x(x2, y2, 0.7 * pin_size);
02422         }
02423     else
02424         {
02425             xend = x2 + (x1 - x2) / 10.;
02426             yend = y2 + (y1 - y2) / 10.;
02427             draw_triangle_along_line(xend, yend, x1, x2, y1, y2);
02428         }
02429 }
02430 
02431 /* UDSD by AY End */