📄 draw.c
字号:
#include <stdio.h> #include <string.h>#include <math.h>#include "util.h"#include "vpr_types.h"#include "globals.h"#include "graphics.h"#include "path_delay.h"#include "draw.h"/*************** Types local to this module *********************************/enum e_draw_rr_toggle {DRAW_NO_RR = 0, DRAW_ALL_RR, DRAW_ALL_BUT_BUFFERS_RR, DRAW_NODES_AND_SBOX_RR, DRAW_NODES_RR};enum e_draw_net_type {ALL_NETS, HIGHLIGHTED};enum e_edge_dir {FROM_X_TO_Y, FROM_Y_TO_X}; /* Chanx to chany or vice versa? *//****************** Variables local to this module. *************************/static boolean show_nets = FALSE; /* Show nets of placement or routing? *//* Controls drawing of routing resources on screen, if pic_on_screen is * * ROUTING. */static enum e_draw_rr_toggle draw_rr_toggle = DRAW_NO_RR;static enum e_route_type draw_route_type;/* Controls if congestion is shown, when ROUTING is on screen. */static boolean show_congestion = FALSE; static boolean show_graphics; /* Graphics enabled or not? */static char default_message[BUFSIZE]; /* Default screen message on screen */static int gr_automode; /* Need user input after: 0: each t, * * 1: each place, 2: never */static enum pic_type pic_on_screen = NO_PICTURE; /* What do I draw? */static float *x_clb_left, *y_clb_bottom;/* The left and bottom coordinates of each clb in the FPGA. * * x_clb_left[0..nx+1] and y_clb_bottom[0..ny+1]. * * COORDINATE SYSTEM goes from (0,0) at the lower left corner to * * (x_clb_left[nx+1]+clb_width, y_clb_bottom[ny+1]+clb_width) in the * * upper right corner. */static float clb_width, pin_size;/* Drawn width (and height) of a clb, and the half-width or half-height of * * a clb pin, respectiviely. Set when init_draw_coords is called. */static enum color_types *net_color, *block_color;/* Color in which each block and net should be drawn. * * [0..num_nets-1] and [0..num_blocks-1], respectively. *//********************** Subroutines local to this module ********************/static void toggle_nets (void (*drawscreen) (void));static void toggle_rr (void (*drawscreen) (void));static void toggle_congestion (void (*drawscreen) (void));static void highlight_crit_path (void (*drawscreen_ptr) (void));static void drawscreen (void);static void redraw_screen (void);static void drawplace (void);static void drawnets (void);static void drawroute (enum e_draw_net_type draw_net_type);static void draw_congestion (void); static void highlight_blocks (float x, float y);static void get_block_center (int bnum, float *x, float *y);static void deselect_all (void);static void draw_rr (void); static void draw_rr_edges (int from_node); static void draw_rr_pin (int inode, enum color_types color); static void draw_rr_chanx (int inode, int itrack);static void draw_rr_chany (int inode, int itrack);static void get_rr_pin_draw_coords (int inode, int iside, float *xcen, float *ycen); static void draw_pin_to_chan_edge (int pin_node, int chan_node, int itrack, boolean mark_conn); static void draw_x (float x, float y, float size); static void draw_chany_to_chany_edge (int from_node, int from_track, int to_node, int to_track, short switch_type);static void draw_chanx_to_chanx_edge (int from_node, int from_track, int to_node, int to_track, short switch_type); static void draw_chanx_to_chany_edge (int chanx_node, int chanx_track, int chany_node, int chany_track, enum e_edge_dir edge_dir, short switch_type); static int get_track_num (int inode, int **chanx_track, int **chany_track); static void draw_rr_switch (float from_x, float from_y, float to_x, float to_y, boolean buffered); /********************** Subroutine definitions ******************************/void set_graphics_state (boolean show_graphics_val, int gr_automode_val, enum e_route_type route_type) {/* Sets the static show_graphics and gr_automode variables to the * * desired values. They control if graphics are enabled and, if so, * * how often the user is prompted for input. */ show_graphics = show_graphics_val; gr_automode = gr_automode_val; draw_route_type = route_type;}void update_screen (int priority, char *msg, enum pic_type pic_on_screen_val, boolean crit_path_button_enabled) {/* Updates the screen if the user has requested graphics. The priority * * value controls whether or not the Proceed button must be clicked to * * continue. Saves the pic_on_screen_val to allow pan and zoom redraws. */ if (!show_graphics) /* Graphics turned off */ return; /* If it's the type of picture displayed has changed, set up the proper * * buttons. */ if (pic_on_screen != pic_on_screen_val) { if (pic_on_screen_val == PLACEMENT && pic_on_screen == NO_PICTURE) { create_button ("Window", "Toggle Nets", toggle_nets); } else if (pic_on_screen_val == ROUTING && pic_on_screen == PLACEMENT) { create_button ("Toggle Nets", "Toggle RR", toggle_rr); create_button ("Toggle RR", "Congestion", toggle_congestion); if (crit_path_button_enabled) create_button ("Congestion", "Crit. Path", highlight_crit_path); } else if (pic_on_screen_val == PLACEMENT && pic_on_screen == ROUTING) { destroy_button ("Toggle RR"); destroy_button ("Congestion"); if (crit_path_button_enabled) destroy_button ("Crit. Path"); } }/* Save the main message. */ strncpy (default_message, msg, BUFSIZE); pic_on_screen = pic_on_screen_val; update_message (msg); drawscreen(); if (priority >= gr_automode) { event_loop(highlight_blocks, drawscreen); } else { flushinput(); }} static void drawscreen (void) {/* This is the screen redrawing routine that event_loop assumes exists. * * It erases whatever is on screen, then calls redraw_screen to redraw * * it. */ clearscreen(); redraw_screen ();}static void redraw_screen (void) {/* The screen redrawing routine called by drawscreen and * * highlight_blocks. Call this routine instead of drawscreen if * * you know you don't need to erase the current graphics, and want * * to avoid a screen "flash". */ if (pic_on_screen == PLACEMENT) { drawplace(); if (show_nets) drawnets (); } else { /* ROUTING on screen */ drawplace(); if (show_nets) drawroute (ALL_NETS); else draw_rr (); if (show_congestion) draw_congestion (); }}static void toggle_nets (void (*drawscreen_ptr) (void)) {/* Enables/disables drawing of nets when a the user clicks on a button. * * Also disables drawing of routing resources. See graphics.c for details * * of how buttons work. */ show_nets = !show_nets; draw_rr_toggle = DRAW_NO_RR; show_congestion = FALSE; update_message (default_message); drawscreen_ptr ();}static void toggle_rr (void (*drawscreen_ptr) (void)) {/* Cycles through the options for viewing the routing resources available * * in an FPGA. If a routing isn't on screen, the routing graph hasn't been * * built, and this routine doesn't switch the view. Otherwise, this routine * * switches to the routing resource view. Clicking on the toggle cycles * * through the options: DRAW_NO_RR, DRAW_ALL_RR, DRAW_ALL_BUT_BUFFERS_RR, * * DRAW_NODES_AND_SBOX_RR, and DRAW_NODES_RR. */ draw_rr_toggle = (draw_rr_toggle + 1) % (DRAW_NODES_RR + 1); show_nets = FALSE; show_congestion = FALSE; update_message (default_message); drawscreen_ptr ();}static void toggle_congestion (void (*drawscreen_ptr) (void)) {/* Turns the congestion display on and off. */ char msg[BUFSIZE]; int inode, num_congested; show_nets = FALSE; draw_rr_toggle = DRAW_NO_RR; show_congestion = !show_congestion; if (!show_congestion) { update_message (default_message); } else { num_congested = 0; for (inode=0;inode<num_rr_nodes;inode++) { if (rr_node[inode].occ > rr_node[inode].capacity) num_congested++; } sprintf (msg, "%d routing resources are overused.", num_congested); update_message (msg); } drawscreen_ptr ();}static void highlight_crit_path (void (*drawscreen_ptr) (void)) {/* Highlights all the blocks and nets on the critical path. */ t_linked_int *critical_path_head, *critical_path_node; int inode, iblk, inet, num_nets_seen; static int nets_to_highlight = 1; char msg[BUFSIZE]; if (nets_to_highlight == 0) { /* Clear the display of all highlighting. */ nets_to_highlight = 1; deselect_all (); update_message (default_message); drawscreen_ptr (); return; } critical_path_head = allocate_and_load_critical_path (); critical_path_node = critical_path_head; num_nets_seen = 0; while (critical_path_node != NULL) { inode = critical_path_node->data; get_tnode_block_and_output_net (inode, &iblk, &inet); if (num_nets_seen == nets_to_highlight) /* Last block */ block_color[iblk] = MAGENTA; else if (num_nets_seen == nets_to_highlight - 1) /* 2nd last block */ block_color[iblk] = YELLOW; else if (num_nets_seen < nets_to_highlight) /* Earlier block */ block_color[iblk] = DARKGREEN; if (inet != OPEN) { num_nets_seen++; if (num_nets_seen < nets_to_highlight) /* First nets. */ net_color[inet] = DARKGREEN; else if (num_nets_seen == nets_to_highlight) net_color[inet] = CYAN; /* Last (new) net. */ } critical_path_node = critical_path_node->next; } if (nets_to_highlight == num_nets_seen) { nets_to_highlight = 0; sprintf (msg, "All %d nets on the critical path highlighted.", num_nets_seen); } else { sprintf (msg, "First %d nets on the critical path highlighted.", nets_to_highlight); nets_to_highlight++; } free_int_list (&critical_path_head); update_message (msg); drawscreen_ptr ();}void alloc_draw_structs (void) {/* Allocate the structures needed to draw the placement and routing. Set * * up the default colors for blocks and nets. */ x_clb_left = (float *) my_malloc ((nx+2)*sizeof(float)); y_clb_bottom = (float *) my_malloc ((ny+2)*sizeof(float)); net_color = (enum color_types *) my_malloc (num_nets * sizeof (enum color_types)); block_color = (enum color_types *) my_malloc (num_blocks * sizeof (enum color_types)); deselect_all(); /* Set initial colors */}void init_draw_coords (float clb_width_val) {/* Load the arrays containing the left and bottom coordinates of the clbs * * forming the FPGA. clb_width_val sets the width and height of a drawn * * clb. */ int i; if (!show_graphics) return; /* -nodisp was selected. */ clb_width = clb_width_val; pin_size = clb_width / (4. * pins_per_clb); pin_size = min (pin_size, clb_width / (4. * io_rat)); pin_size = min (pin_size, 0.3); x_clb_left[0] = 0.; for (i=1;i<=nx+1;i++) x_clb_left[i] = x_clb_left[i-1] + clb_width + chan_width_y[i-1] + 1.; y_clb_bottom[0] = 0.; for (i=1;i<=ny+1;i++) y_clb_bottom[i] = y_clb_bottom[i-1] + clb_width + chan_width_x[i-1] + 1.; init_world (0., y_clb_bottom[ny+1] + clb_width, x_clb_left[nx+1]+ clb_width, 0.);}static void drawplace (void) {/* Draws the blocks placed on the proper clbs. Occupied clbs are light * * grey, while empty ones are left white and have a dashed border. */ float io_step = clb_width/io_rat; float x1, y1, x2, y2; int i, j, k, bnum; /* Draw the IO Pads first. Want each subblock to border on core. */ setlinewidth (0); for (i=1;i<=nx;i++) { for (j=0;j<=ny+1;j+=ny+1) { /* top and bottom */ y1 = y_clb_bottom[j]; y2 = y1 + clb_width; setlinestyle (SOLID); for (k=0;k<clb[i][j].occ;k++) { bnum = clb[i][j].u.io_blocks[k]; setcolor (block_color[bnum]); x1 = x_clb_left[i] + k * io_step; x2 = x1 + io_step; fillrect (x1,y1,x2,y2); setcolor (BLACK); drawrect (x1,y1,x2,y2);/* Vertically offset text so these closely spaced names don't overlap. */ drawtext ((x1 + x2)/2., y1 + io_step * (k + 0.5), block[clb[i][j].u.io_blocks[k]].name, clb_width); } setlinestyle (DASHED); setcolor (BLACK); for (k=clb[i][j].occ;k<io_rat;k++) { x1 = x_clb_left[i] + k * io_step; x2 = x1 + io_step; drawrect (x1,y1,x2,y2); } } } for (j=1;j<=ny;j++) { for (i=0;i<=nx+1;i+=nx+1) { /* IOs on left and right */ x1 = x_clb_left[i]; x2 = x1 + clb_width; setlinestyle (SOLID); for (k=0;k<clb[i][j].occ;k++) { bnum = clb[i][j].u.io_blocks[k]; setcolor (block_color[bnum]); y1 = y_clb_bottom[j] + k * io_step; y2 = y1 + io_step; fillrect (x1,y1,x2,y2); setcolor (BLACK); drawrect (x1,y1,x2,y2); drawtext ((x1 + x2)/2., (y1 + y2)/2., block[clb[i][j].u.io_blocks[k]].name, clb_width); } setlinestyle (DASHED); setcolor (BLACK); for (k=clb[i][j].occ;k<io_rat;k++) { y1 = y_clb_bottom[j] + k * io_step; y2 = y1 + io_step; drawrect (x1,y1,x2,y2); } } } /* Now do the CLBs in the middle. */ for (i=1;i<=nx;i++) { x1 = x_clb_left[i]; x2 = x1 + clb_width; for (j=1;j<=ny;j++) { y1 = y_clb_bottom[j]; y2 = y1 + clb_width; if (clb[i][j].occ != 0) { setlinestyle (SOLID); bnum = clb[i][j].u.block; setcolor (block_color[bnum]); fillrect (x1,y1,x2,y2); setcolor (BLACK); drawrect (x1,y1,x2,y2); drawtext ((x1 + x2)/2., (y1 + y2)/2., block[clb[i][j].u.block].name, clb_width); } else { setlinestyle (DASHED); setcolor (BLACK); drawrect (x1,y1,x2,y2); } } /* end j */ } /* end i */}static void drawnets (void) {/* This routine draws the nets on the placement. The nets have not * * yet been routed, so we just draw a chain showing a possible path * * for each net. This gives some idea of future congestion. */ int inet, ipin, b1, b2; float x1, y1, x2, y2; setlinestyle (SOLID); setlinewidth (0); /* Draw the net as a star from the source to each sink. Draw from centers of * * blocks (or sub blocks in the case of IOs). */ for (inet=0;inet<num_nets;inet++) { if (is_global[inet]) /* Don't draw global nets. */ continue; setcolor (net_color[inet]); b1 = net[inet].blocks[0]; get_block_center (b1, &x1, &y1); for (ipin=1;ipin<net[inet].num_pins;ipin++) { b2 = net[inet].blocks[ipin]; get_block_center (b2, &x2, &y2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -