📄 draw.c
字号:
y1 = y_clb_bottom[from_ylow]; y2 = y_clb_bottom[from_ylow - 1] + clb_width; } else if (from_ylow < to_ylow) { y1 = y_clb_bottom[to_ylow - 1] + clb_width; y2 = y_clb_bottom[to_ylow]; } else if (to_yhigh > from_yhigh) { /* Draw from top edge of one to other. */ y1 = y_clb_bottom[from_yhigh] + clb_width; y2 = y_clb_bottom[from_yhigh + 1]; } else if (from_yhigh > to_yhigh) { y1 = y_clb_bottom[to_yhigh + 1]; y2 = y_clb_bottom[to_yhigh] + clb_width; } else { /* Complete overlap: start and end both align. Draw outside the sbox */ y1 = y_clb_bottom[from_ylow]; y2 = y_clb_bottom[from_ylow] + 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_rr_switch (float from_x, float from_y, float to_x, float to_y, boolean buffered) {/* Draws a buffer (triangle) or pass transistor (circle) on the edge * * connecting from to to, depending on the status of buffered. The drawing * * is closest to the from_node, since it reflects the switch type of from. */ const float switch_rad = 0.15; float magnitude, xcen, ycen, xdelta, ydelta, xbaseline, ybaseline; float xunit, yunit; t_point poly[3]; xcen = from_x + (to_x - from_x) / 10.; ycen = from_y + (to_y - from_y) / 10.; if (!buffered) { /* Draw a circle for a pass transistor */ drawarc (xcen, ycen, switch_rad, 0., 360.); } else { /* Buffer */ xdelta = to_x - from_x; ydelta = to_y - from_y; magnitude = sqrt (xdelta * xdelta + ydelta * ydelta); xunit = xdelta / magnitude; yunit = ydelta / magnitude; poly[0].x = xcen + xunit * switch_rad; poly[0].y = ycen + yunit * switch_rad; xbaseline = xcen - xunit * switch_rad; ybaseline = ycen - yunit * switch_rad;/* Recall: perpendicular vector to the unit vector along the switch (xv, yv) * * is (yv, -xv). */ poly[1].x = xbaseline + yunit * switch_rad; poly[1].y = ybaseline - xunit * switch_rad; poly[2].x = xbaseline - yunit * switch_rad; poly[2].y = ybaseline + xunit * switch_rad; fillpoly (poly, 3); }}static void draw_rr_pin (int inode, enum color_types color) {/* Draws an IPIN or OPIN rr_node. Note that the pin can appear on more * * than one side of a clb. Also note that this routine can change the * * current color to BLACK. */ int ipin, i, j, iside, iclass, iblk; float xcen, ycen; char str[BUFSIZE]; i = rr_node[inode].xlow; j = rr_node[inode].ylow; ipin = rr_node[inode].ptc_num; setcolor (color); if (clb[i][j].type == CLB) { iclass = clb_pin_class[ipin]; for (iside=0;iside<=3;iside++) { if (pinloc[iside][ipin] == 1) { /* Pin exists on this side. */ get_rr_pin_draw_coords (inode, iside, &xcen, &ycen); fillrect (xcen-pin_size, ycen-pin_size, xcen+pin_size, ycen+pin_size); sprintf (str, "%d", ipin); setcolor (BLACK); drawtext (xcen, ycen, str, 2*pin_size); setcolor (color); } } } else { /* IO pad. */ iblk = clb[i][j].u.io_blocks[ipin]; if (i == 0) iside = RIGHT; else if (j == 0) iside = TOP; else if (i == nx+1) iside = LEFT; else iside = BOTTOM; get_rr_pin_draw_coords (inode, iside, &xcen, &ycen); fillrect (xcen-pin_size, ycen-pin_size, xcen+pin_size, ycen+pin_size); }}static void get_rr_pin_draw_coords (int inode, int iside, float *xcen, float *ycen) {/* Returns the coordinates at which the center of this pin should be drawn. * * inode gives the node number, and iside gives the side of the clb or pad * * the physical pin is on. */ int i, j, ipin, ipad; float step_size, offset, xc, yc; i = rr_node[inode].xlow; j = rr_node[inode].ylow; xc = x_clb_left[i]; yc = y_clb_bottom[j]; if (clb[i][j].type == CLB) { ipin = rr_node[inode].ptc_num; step_size = clb_width / (pins_per_clb + 1.); offset = (ipin + 1.) * step_size; } else { /* IO pad. */ ipad = rr_node[inode].ptc_num; step_size = clb_width / (float) io_rat; offset = ipad * step_size + clb_width / (3. * io_rat); /* Pads have both an IPIN and an OPIN. Stagger them. */ if (rr_node[inode].type == IPIN) offset += clb_width / (3. * io_rat); } switch (iside) { case LEFT: yc += offset; break; case RIGHT: xc += clb_width; yc += offset; break; case BOTTOM: xc += offset; break; case TOP: xc += offset; yc += clb_width; break; default: printf ("Error in get_rr_pin_draw_coords: Unexpected iside %d.\n", iside); exit (1); break; } *xcen = xc; *ycen = yc;}static void drawroute (enum e_draw_net_type draw_net_type) {/* Draws the nets in the positions fixed by the router. If draw_net_type is * * ALL_NETS, draw all the nets. If it is HIGHLIGHTED, draw only the nets * * that are not coloured black (useful for drawing over the rr_graph). */ /* Next free track in each channel segment if routing is GLOBAL */ static int **chanx_track = NULL; /* [1..nx][0..ny] */ static int **chany_track = NULL; /* [0..nx][1..ny] */ int inet, i, j, inode, prev_node, prev_track, itrack; short switch_type; struct s_trace *tptr; t_rr_type rr_type, prev_type; if (draw_route_type == GLOBAL) { /* Allocate some temporary storage if it's not already available. */ if (chanx_track == NULL) chanx_track = (int **) alloc_matrix (1, nx, 0, ny, sizeof(int)); if (chany_track == NULL) chany_track = (int **) alloc_matrix (0, nx, 1, ny, sizeof(int)); for (i=1;i<=nx;i++) for (j=0;j<=ny;j++) chanx_track[i][j] = -1; for (i=0;i<=nx;i++) for (j=1;j<=ny;j++) chany_track[i][j] = -1; } setlinestyle (SOLID);/* Now draw each net, one by one. */ for (inet=0;inet<num_nets;inet++) { if (is_global[inet]) /* Don't draw global nets. */ continue; if (trace_head[inet] == NULL) /* No routing. Skip. (Allows me to draw */ continue; /* partially complete routes). */ if (draw_net_type == HIGHLIGHTED && net_color[inet] == BLACK) continue; setcolor (net_color[inet]); tptr = trace_head[inet]; /* SOURCE to start */ inode = tptr->index; rr_type = rr_node[inode].type; while (1) { prev_node = inode; prev_type = rr_type; switch_type = tptr->iswitch; tptr = tptr->next; inode = tptr->index; rr_type = rr_node[inode].type; switch (rr_type) { case OPIN: draw_rr_pin (inode, net_color[inet]); break; case IPIN: draw_rr_pin (inode, net_color[inet]); prev_track = get_track_num (prev_node, chanx_track, chany_track); draw_pin_to_chan_edge (inode, prev_node, prev_track, FALSE); break; case CHANX: if (draw_route_type == GLOBAL) chanx_track[rr_node[inode].xlow][rr_node[inode].ylow]++; itrack = get_track_num (inode, chanx_track, chany_track); draw_rr_chanx (inode, itrack); switch (prev_type) { case CHANX: prev_track = get_track_num (prev_node, chanx_track, chany_track); draw_chanx_to_chanx_edge (prev_node, prev_track, inode, itrack, switch_type); break; case CHANY: prev_track = get_track_num (prev_node, chanx_track, chany_track); draw_chanx_to_chany_edge (inode, itrack, prev_node, prev_track, FROM_Y_TO_X, switch_type); break; case OPIN: draw_pin_to_chan_edge (prev_node, inode, itrack, FALSE); break; default: printf ("Error in drawroute: Unexpected connection from an \n" "rr_node of type %d to one of type %d.\n", prev_type, rr_type); exit (1); } break; case CHANY: if (draw_route_type == GLOBAL) chany_track[rr_node[inode].xlow][rr_node[inode].ylow]++; itrack = get_track_num (inode, chanx_track, chany_track); draw_rr_chany (inode, itrack); switch (prev_type) { case CHANX: prev_track = get_track_num (prev_node, chanx_track, chany_track); draw_chanx_to_chany_edge (prev_node, prev_track, inode, itrack, FROM_X_TO_Y, switch_type); break; case CHANY: prev_track = get_track_num (prev_node, chanx_track, chany_track); draw_chany_to_chany_edge (prev_node, prev_track, inode, itrack, switch_type); break; case OPIN: draw_pin_to_chan_edge (prev_node, inode, itrack, FALSE); break; default: printf ("Error in drawroute: Unexpected connection from an \n" "rr_node of type %d to one of type %d.\n", prev_type, rr_type); exit (1); } break; default: break; } if (rr_type == SINK) { /* Skip the next segment */ tptr = tptr->next; if (tptr == NULL) break; inode = tptr->index; rr_type = rr_node[inode].type; } } /* End loop over traceback. */ } /* End for (each net) */}static int get_track_num (int inode, int **chanx_track, int **chany_track) {/* Returns the track number of this routing resource node. */ int i, j; t_rr_type rr_type; if (draw_route_type == DETAILED) return (rr_node[inode].ptc_num);/* GLOBAL route stuff below. */ rr_type = rr_node[inode].type; i = rr_node[inode].xlow; /* NB: Global rr graphs must have only unit */ j = rr_node[inode].ylow; /* length channel segments. */ switch (rr_type) { case CHANX: return (chanx_track[i][j]); case CHANY: return (chany_track[i][j]); default: printf ("Error in get_track_num: unexpected node type %d for node %d." "\n", rr_type, inode); exit (1); }}static void highlight_blocks (float x, float y) {/* This routine is called when the user clicks in the graphics area. * * It determines if a clb was clicked on. If one was, it is * * highlighted in green, it's fanin nets and clbs are highlighted in * * blue and it's fanout is highlighted in red. If no clb was * * clicked on (user clicked on white space) any old highlighting is * * removed. Note that even though global nets are not drawn, their * * fanins and fanouts are highlighted when you click on a block * * attached to them. */ int i, j, k, hit, bnum, ipin, netnum, fanblk; int class; float io_step; char msg[BUFSIZE]; io_step = clb_width/io_rat; deselect_all (); hit = 0; for (i=0;i<=nx+1;i++) { if (x <= x_clb_left[i]+clb_width) { if (x >= x_clb_left[i]) hit = 1; break; } } if (!hit) { update_message (default_message); drawscreen(); return; } hit = 0; for (j=0;j<=ny+1;j++) { if (y <= y_clb_bottom[j]+clb_width) { if (y >= y_clb_bottom[j]) hit = 1; break; } } if (!hit) { update_message (default_message); drawscreen(); return; }/* The user selected the clb at location (i,j). */ if (clb[i][j].type == CLB) { if (clb[i][j].occ == 0) { update_message (default_message); drawscreen (); return; } bnum = clb[i][j].u.block; } else { /* IO block clb */ if (i == 0 || i == nx+1) /* Vertical columns of IOs */ k = (int) ((y - y_clb_bottom[j]) / io_step); else k = (int) ((x - x_clb_left[i]) / io_step); if (k >= clb[i][j].occ) { /* Empty spot */ update_message (default_message); drawscreen(); return; } bnum = clb[i][j].u.io_blocks[k]; }/* Highlight fanin and fanout. */ if (block[bnum].type == OUTPAD) { netnum = block[bnum].nets[0]; /* Only net. */ net_color[netnum] = BLUE; /* Outpad drives nothing */ fanblk = net[netnum].blocks[0]; /* Net driver */ block_color[fanblk] = BLUE; } else if (block[bnum].type == INPAD) { netnum = block[bnum].nets[0]; /* Only net. */ net_color[netnum] = RED; /* Driven by INPAD *//* Highlight fanout blocks in RED */ for (ipin=1;ipin<net[netnum].num_pins;ipin++) { fanblk = net[netnum].blocks[ipin]; block_color[fanblk] = RED; } } else { /* CLB block. */ for (k=0;k<pins_per_clb;k++) { /* Each pin on a CLB */ netnum = block[bnum].nets[k]; if (netnum == OPEN) continue; class = clb_pin_class[k]; if (class_inf[class].type == DRIVER) { /* Fanout */ net_color[netnum] = RED; for (ipin=1;ipin<net[netnum].num_pins;ipin++) { fanblk = net[netnum].blocks[ipin]; block_color[fanblk] = RED; } } else { /* This net is fanin to the block. */ net_color[netnum] = BLUE; fanblk = net[netnum].blocks[0]; block_color[fanblk] = BLUE; } } } block_color[bnum] = GREEN; /* Selected block. */ sprintf (msg, "Block %d (%s) at (%d, %d) selected.", bnum, block[bnum].name, i, j); update_message (msg); drawscreen (); /* Need to erase screen. */}static void deselect_all (void) {/* Sets the color of all clbs and nets to the default. */ int i; for (i=0;i<num_blocks;i++) block_color[i] = LIGHTGREY; for (i=0;i<num_nets;i++) net_color[i] = BLACK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -