📄 draw.c
字号:
#include <stdio.h>#include <string.h>#include <math.h>#include "util.h"#include "vpr_types.h"#include "vpr_utils.h"#include "globals.h"#include "graphics.h"#include "path_delay.h"#include "draw.h"#include <assert.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, DRAW_RR_TOGGLE_MAX};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. *//* Can toggle to DRAW_NO_RR;*/static enum e_draw_rr_toggle draw_rr_toggle = DRAW_NO_RR; /* UDSD by AY */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 *tile_x, *tile_y;/* The left and bottom coordinates of each grid_tile in the FPGA. * * tile_x[0..nx+1] and tile_y[0..ny+1]. * * COORDINATE SYSTEM goes from (0,0) at the lower left corner to * * (tile_x[nx+1]+tile_width, tile_y[ny+1]+tile_width) in the * * upper right corner. */static float tile_width, pin_size;/* Drawn width (and height) of a grid_tile, and the half-width or half-height of * * a 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, int ioff, float *xcen, float *ycen);static void draw_pin_to_chan_edge(int pin_node, int chan_node);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);static void draw_triangle_along_line(float xend, float yend, /* UDSD by AY */ float x1, float x2, /* UDSD by AY */ float y1, float y2); /* UDSD by AY *//********************** Subroutine definitions ******************************/voidset_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;}voidupdate_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"); } } else if(pic_on_screen_val == ROUTING && pic_on_screen == NO_PICTURE) { create_button("Window", "Toggle Nets", toggle_nets); 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); } } } /* Save the main message. */ my_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 voiddrawscreen(){ /* 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 voidredraw_screen(){ /* 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". */ setfontsize(20); /* UDSD Modification by WMF */ 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 voidtoggle_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 voidtoggle_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_RR_TOGGLE_MAX); show_nets = FALSE; show_congestion = FALSE; update_message(default_message); drawscreen_ptr();}static voidtoggle_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 voidhighlight_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();}voidalloc_draw_structs(void){ /* Allocate the structures needed to draw the placement and routing. Set * * up the default colors for blocks and nets. */ tile_x = (float *)my_malloc((nx + 2) * sizeof(float)); tile_y = (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 */}voidinit_draw_coords(float width_val){ /* Load the arrays containing the left and bottom coordinates of the clbs * * forming the FPGA. tile_width_val sets the width and height of a drawn * * clb. */ int i; int j; if(!show_graphics) return; /* -nodisp was selected. */ tile_width = width_val; pin_size = 0.3; for(i = 0; i < num_types; ++i) { pin_size = min(pin_size, (tile_width / (4.0 * type_descriptors[i].num_pins))); } j = 0; for(i = 0; i < (nx + 1); i++) { tile_x[i] = (i * tile_width) + j; j += chan_width_y[i] + 1; /* N wires need N+1 units of space */ } tile_x[nx + 1] = ((nx + 1) * tile_width) + j; j = 0; for(i = 0; i < (ny + 1); ++i) { tile_y[i] = (i * tile_width) + j; j += chan_width_x[i] + 1; } tile_y[ny + 1] = ((ny + 1) * tile_width) + j; init_world(0.0, tile_y[ny + 1] + tile_width, tile_x[nx + 1] + tile_width, 0.0);}static voiddrawplace(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 sub_tile_step; float x1, y1, x2, y2; int i, j, k, bnum; int num_sub_tiles; int height; setlinewidth(0); for(i = 0; i <= (nx + 1); i++) { for(j = 0; j <= (ny + 1); j++) { /* Only the first block of a group should control drawing */ if(grid[i][j].offset > 0) continue; /* Don't draw corners */ if(((i < 1) || (i > nx)) && ((j < 1) || (j > ny))) continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -