📄 draw.c
字号:
drawline (x1,y1,x2,y2); /* x1 = x2; */ /* Uncomment to draw a chain instead of a star. */ /* y1 = y2; */ } }}static void get_block_center (int bnum, float *x, float *y) {/* This routine finds the center of block bnum in the current placement, * * and returns it in *x and *y. This is used in routine shownets. */ int i, j, k; i = block[bnum].x; j = block[bnum].y; if (clb[i][j].type == CLB) { *x = x_clb_left[i] + clb_width/2.; *y = y_clb_bottom[j] + clb_width/2.; } else { /* IO clb. Have to figure out which subblock it is. */ for (k=0;k<clb[i][j].occ;k++) if (clb[i][j].u.io_blocks[k] == bnum) break; if (i == 0 || i == nx + 1) { /* clb split vertically */ *x = x_clb_left[i] + clb_width/2.; *y = y_clb_bottom[j] + (k + 0.5) * clb_width / (float) io_rat; } else { /* clb split horizontally */ *x = x_clb_left[i] + (k + 0.5) * clb_width / (float) io_rat; *y = y_clb_bottom[j] + clb_width/2.; } }}static void draw_congestion (void) {/* Draws all the overused routing resources (i.e. congestion) in RED. */ int inode, itrack; setcolor (RED); setlinewidth (2); for (inode=0;inode<num_rr_nodes;inode++) { if (rr_node[inode].occ > rr_node[inode].capacity) { switch (rr_node[inode].type) { case CHANX: itrack = rr_node[inode].ptc_num; draw_rr_chanx (inode, itrack); break; case CHANY: itrack = rr_node[inode].ptc_num; draw_rr_chany (inode, itrack); break; case IPIN: case OPIN: draw_rr_pin (inode, RED); break; default: break; } } }}static void draw_rr (void) {/* Draws the routing resources that exist in the FPGA, if the user wants * * them drawn. */ int inode, itrack; if (draw_rr_toggle == DRAW_NO_RR) { setlinewidth (3); drawroute (HIGHLIGHTED); setlinewidth (0); return; } setlinestyle (SOLID); setlinewidth (0); for (inode=0;inode<num_rr_nodes;inode++) { switch (rr_node[inode].type) { case SOURCE: case SINK: break; /* Don't draw. */ case CHANX: setcolor (BLACK); itrack = rr_node[inode].ptc_num; draw_rr_chanx (inode, itrack); draw_rr_edges (inode); break; case CHANY: setcolor (BLACK); itrack = rr_node[inode].ptc_num; draw_rr_chany (inode, itrack); draw_rr_edges (inode); break; case IPIN: draw_rr_pin (inode, BLUE); break; case OPIN: draw_rr_pin (inode, RED); setcolor (RED); draw_rr_edges (inode); break; default: printf("Error in draw_rr: Unexpected rr_node type: %d.\n", rr_node[inode].type); exit (1); } } setlinewidth (3); drawroute (HIGHLIGHTED); setlinewidth (0);}static void draw_rr_chanx (int inode, int itrack) {/* Draws an x-directed channel segment. */ float x1, x2, y; /* Track 0 at bottom edge, closest to "owning" clb. */ x1 = x_clb_left[rr_node[inode].xlow]; x2 = x_clb_left[rr_node[inode].xhigh] + clb_width; y = y_clb_bottom[rr_node[inode].ylow] + 1. + itrack + clb_width; drawline (x1, y, x2, y);}static void draw_rr_chany (int inode, int itrack) { /* Draws a y-directed channel segment. */ float x, y1, y2; /* Track 0 at left edge, closest to "owning" clb. */ x = x_clb_left[rr_node[inode].xlow] + 1. + itrack + clb_width; y1 = y_clb_bottom[rr_node[inode].ylow]; y2 = y_clb_bottom[rr_node[inode].yhigh] + clb_width; drawline (x, y1, x, y2);}static void draw_rr_edges (int inode) {/* Draws all the edges that the user wants shown between inode and what it * * connects to. inode is assumed to be a CHANX, CHANY, or OPIN. */ t_rr_type from_type, to_type; int iedge, to_node, from_ptc_num, to_ptc_num; short switch_type; from_type = rr_node[inode].type; if (draw_rr_toggle == DRAW_NODES_RR || (draw_rr_toggle == DRAW_NODES_AND_SBOX_RR && from_type == OPIN)) return; /* Nothing to draw. */ from_ptc_num = rr_node[inode].ptc_num; for (iedge=0;iedge<rr_node[inode].num_edges;iedge++) { to_node = rr_node[inode].edges[iedge]; to_type = rr_node[to_node].type; to_ptc_num = rr_node[to_node].ptc_num; switch (from_type) { case OPIN: switch (to_type) { case CHANX: case CHANY: setcolor (RED); draw_pin_to_chan_edge (inode, to_node, to_ptc_num, TRUE); break; default: printf("Error in draw_rr_edges: node %d (type: %d) connects to \n" "node %d (type: %d).\n", inode, from_type, to_node, to_type); exit (1); break; } break; case CHANX: /* from_type */ switch (to_type) { case IPIN: if (draw_rr_toggle == DRAW_NODES_AND_SBOX_RR) break; setcolor (BLUE); draw_pin_to_chan_edge (to_node, inode, from_ptc_num, TRUE); break; case CHANX: setcolor (DARKGREEN); switch_type = rr_node[inode].switches[iedge]; draw_chanx_to_chanx_edge (inode, from_ptc_num, to_node, to_ptc_num, switch_type); break; case CHANY: setcolor (DARKGREEN); switch_type = rr_node[inode].switches[iedge]; draw_chanx_to_chany_edge (inode, from_ptc_num, to_node, to_ptc_num, FROM_X_TO_Y, switch_type); break; default: printf("Error in draw_rr_edges: node %d (type: %d) connects to \n" "node %d (type: %d).\n", inode, from_type, to_node, to_type); exit (1); break; } break; case CHANY: /* from_type */ switch (to_type) { case IPIN: if (draw_rr_toggle == DRAW_NODES_AND_SBOX_RR) break; setcolor (BLUE); draw_pin_to_chan_edge (to_node, inode, from_ptc_num, TRUE); break; case CHANX: setcolor (DARKGREEN); switch_type = rr_node[inode].switches[iedge]; draw_chanx_to_chany_edge (to_node, to_ptc_num, inode, from_ptc_num, FROM_Y_TO_X, switch_type); break; case CHANY: setcolor (DARKGREEN); switch_type = rr_node[inode].switches[iedge]; draw_chany_to_chany_edge (inode, from_ptc_num, to_node, to_ptc_num, switch_type); break; default: printf("Error in draw_rr_edges: node %d (type: %d) connects to \n" "node %d (type: %d).\n", inode, from_type, to_node, to_type); exit (1); break; } break; default: /* from_type */ printf("Error: draw_rr_edges called with node %d of type %d.\n", inode, from_type); exit (1); break; } } /* End of for each edge loop */}static void draw_pin_to_chan_edge (int pin_node, int chan_node, int itrack, boolean mark_conn) {/* This routine draws an edge from the pin_node to the chan_node (CHANX or * * CHANY). The track number of the channel is passed in itrack, rather than * * taken from chan_node's ptc_num to allow this routine to draw global * * routings (where the track number isn't in the rr_graph). If mark_conn is * * TRUE, draw a box where the pin connects to the track (useful for drawing * * the rr graph). */ t_rr_type chan_type; int pin_x, pin_y, pin_num, chan_xlow, chan_ylow; float x1, x2, y1, y2; pin_x = rr_node[pin_node].xlow; pin_y = rr_node[pin_node].ylow; pin_num = rr_node[pin_node].ptc_num; chan_type = rr_node[chan_node].type; switch (chan_type) { case CHANX: chan_ylow = rr_node[chan_node].ylow; if (pin_y == chan_ylow) { get_rr_pin_draw_coords (pin_node, TOP, &x1, &y1); y1 += pin_size; /* Don't overdraw pin number. */ } else { get_rr_pin_draw_coords (pin_node, BOTTOM, &x1, &y1); y1 -= pin_size; } y2 = y_clb_bottom[chan_ylow] + clb_width + 1 + itrack; x2 = x1; break; case CHANY: chan_xlow = rr_node[chan_node].xlow; if (pin_x == chan_xlow) { get_rr_pin_draw_coords (pin_node, RIGHT, &x1, &y1); x1 += pin_size; } else { get_rr_pin_draw_coords (pin_node, LEFT, &x1, &y1); x1 -= pin_size; } x2 = x_clb_left[chan_xlow] + clb_width + 1 + itrack; y2 = y1; break; default: printf ("Error in draw_pin_to_chan_edge: invalid channel node %d.\n", chan_node); exit (1); } drawline (x1, y1, x2, y2); if (mark_conn) draw_x (x2, y2, 0.7 * pin_size);}static void draw_x (float x, float y, float size) {/* Draws an X centered at (x,y). The width and height of the X are each * * 2 * size. */ drawline (x-size, y+size, x+size, y-size); drawline (x-size, y-size, x+size, y+size);}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) {/* Draws an edge (SBOX connection) between an x-directed channel and a * * y-directed channel. */ float x1, y1, x2, y2; int chanx_y, chany_x, chanx_xlow, chany_ylow; chanx_y = rr_node[chanx_node].ylow; chanx_xlow = rr_node[chanx_node].xlow; chany_x = rr_node[chany_node].xlow; chany_ylow = rr_node[chany_node].ylow;/* (x1,y1): point on CHANX segment, (x2,y2): point on CHANY segment. */ y1 = y_clb_bottom[chanx_y] + clb_width + 1. + chanx_track; x2 = x_clb_left[chany_x] + clb_width + 1. + chany_track; if (chanx_xlow <= chany_x) { /* Can draw connection going right */ x1 = x_clb_left[chany_x] + clb_width; } else { /* Must draw connection going left. */ x1 = x_clb_left[chanx_xlow]; } if (chany_ylow <= chanx_y) { /* Can draw connection going up. */ y2 = y_clb_bottom[chanx_y] + clb_width; } else { /* Must draw connection going down. */ y2 = y_clb_bottom[chany_ylow]; } drawline (x1, y1, x2, y2); if (draw_rr_toggle != DRAW_ALL_RR) return; if (edge_dir == FROM_X_TO_Y) draw_rr_switch (x1, y1, x2, y2, switch_inf[switch_type].buffered); else draw_rr_switch (x2, y2, x1, y1, switch_inf[switch_type].buffered);}static void draw_chanx_to_chanx_edge (int from_node, int from_track, int to_node, int to_track, short switch_type) {/* Draws a connection between two x-channel segments. Passing in the track * * numbers allows this routine to be used for both rr_graph and routing * * drawing. */ float x1, x2, y1, y2; int from_y, to_y, from_xlow, to_xlow, from_xhigh, to_xhigh; from_y = rr_node[from_node].ylow; from_xlow = rr_node[from_node].xlow; from_xhigh = rr_node[from_node].xhigh; to_y = rr_node[to_node].ylow; to_xlow = rr_node[to_node].xlow; to_xhigh = rr_node[to_node].xhigh;/* (x1, y1) point on from_node, (x2, y2) point on to_node. */ y1 = y_clb_bottom[from_y] + clb_width + 1 + from_track; y2 = y_clb_bottom[to_y] + clb_width + 1 + to_track; if (to_xhigh < from_xlow) { /* From right to left */ x1 = x_clb_left[from_xlow]; x2 = x_clb_left[to_xhigh] + clb_width; } else if (to_xlow > from_xhigh) { /* From left to right */ x1 = x_clb_left[from_xhigh] + clb_width; x2 = x_clb_left[to_xlow]; }/* Segments overlap in the channel. Figure out best way to draw. Have to * * make sure the drawing is symmetric in the from rr and to rr so the edges * * will be drawn on top of each other for bidirectional connections. */ else if (to_xlow < from_xlow) { /* Draw from left edge of one to other */ x1 = x_clb_left[from_xlow]; x2 = x_clb_left[from_xlow - 1] + clb_width; } else if (from_xlow < to_xlow) { x1 = x_clb_left[to_xlow - 1] + clb_width; x2 = x_clb_left[to_xlow]; } else if (to_xhigh > from_xhigh) { /* Draw from right edge of one to other */ x1 = x_clb_left[from_xhigh] + clb_width; x2 = x_clb_left[from_xhigh + 1]; } else if (from_xhigh > to_xhigh) { x1 = x_clb_left[to_xhigh + 1]; x2 = x_clb_left[to_xhigh] + clb_width; } else { /* Complete overlap: start and end both align. Draw outside the sbox */ x1 = x_clb_left[from_xlow]; x2 = x_clb_left[from_xlow] + clb_width; } drawline (x1, y1, x2, y2); if (draw_rr_toggle == DRAW_ALL_RR) draw_rr_switch (x1, y1, x2, y2, switch_inf[switch_type].buffered);}static void draw_chany_to_chany_edge (int from_node, int from_track, int to_node, int to_track, short switch_type) { /* Draws a connection between two y-channel segments. Passing in the track * * numbers allows this routine to be used for both rr_graph and routing * * drawing. */ float x1, x2, y1, y2; int from_x, to_x, from_ylow, to_ylow, from_yhigh, to_yhigh; from_x = rr_node[from_node].xlow; from_ylow = rr_node[from_node].ylow; from_yhigh = rr_node[from_node].yhigh; to_x = rr_node[to_node].xlow; to_ylow = rr_node[to_node].ylow; to_yhigh = rr_node[to_node].yhigh;/* (x1, y1) point on from_node, (x2, y2) point on to_node. */ x1 = x_clb_left[from_x] + clb_width + 1 + from_track; x2 = x_clb_left[to_x] + clb_width + 1 + to_track; if (to_yhigh < from_ylow) { /* From upper to lower */ y1 = y_clb_bottom[from_ylow]; y2 = y_clb_bottom[to_yhigh] + clb_width; } else if (to_ylow > from_yhigh) { /* From lower to upper */ y1 = y_clb_bottom[from_yhigh] + clb_width; y2 = y_clb_bottom[to_ylow]; }/* Segments overlap in the channel. Figure out best way to draw. Have to * * make sure the drawing is symmetric in the from rr and to rr so the edges * * will be drawn on top of each other for bidirectional connections. */ else if (to_ylow < from_ylow) { /* Draw from bottom edge of one to other. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -