📄 draw.c
字号:
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 voiddraw_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);}/* UDSD Modifications by WMF: Thank God Andy fixed this. */static voiddraw_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 = tile_y[chanx_y] + tile_width + 1. + chanx_track; x2 = tile_x[chany_x] + tile_width + 1. + chany_track; if(chanx_xlow <= chany_x) { /* Can draw connection going right */ x1 = tile_x[chany_x] + tile_width; /* UDSD by AY Start */ if(rr_node[chanx_node].direction != BI_DIRECTION) { if(edge_dir == FROM_X_TO_Y) { if((chanx_track % 2) == 1) { /* UDSD Modifications by WMF: If dec wire, then going left */ x1 = tile_x[chany_x + 1]; } } } /* UDSD by AY End */ } else { /* Must draw connection going left. */ x1 = tile_x[chanx_xlow]; } if(chany_ylow <= chanx_y) { /* Can draw connection going up. */ y2 = tile_y[chanx_y] + tile_width; /* UDSD by AY Start */ if(rr_node[chany_node].direction != BI_DIRECTION) { if(edge_dir == FROM_Y_TO_X) { if((chany_track % 2) == 1) { /* UDSD Modifications by WMF: If dec wire, then going down */ y2 = tile_y[chanx_y + 1]; } } } /* UDSD by AY End */ } else { /* Must draw connection going down. */ y2 = tile_y[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 voiddraw_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 = tile_y[from_y] + tile_width + 1 + from_track; y2 = tile_y[to_y] + tile_width + 1 + to_track; if(to_xhigh < from_xlow) { /* From right to left */ /* UDSD Note by WMF: could never happen for INC wires, unless U-turn. For DEC * wires this handles well */ x1 = tile_x[from_xlow]; x2 = tile_x[to_xhigh] + tile_width; } else if(to_xlow > from_xhigh) { /* From left to right */ /* UDSD Note by WMF: could never happen for DEC wires, unless U-turn. For INC * wires this handles well */ x1 = tile_x[from_xhigh] + tile_width; x2 = tile_x[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. */ /* UDSD Modification by WMF Begin */ else { if(rr_node[to_node].direction != BI_DIRECTION) { /* must connect to to_node's wire beginning at x2 */ if(to_track % 2 == 0) { /* INC wire starts at leftmost edge */ assert(from_xlow < to_xlow); x2 = tile_x[to_xlow]; /* since no U-turns from_track must be INC as well */ x1 = tile_x[to_xlow - 1] + tile_width; } else { /* DEC wire starts at rightmost edge */ assert(from_xhigh > to_xhigh); x2 = tile_x[to_xhigh] + tile_width; x1 = tile_x[to_xhigh + 1]; } } else { if(to_xlow < from_xlow) { /* Draw from left edge of one to other */ x1 = tile_x[from_xlow]; x2 = tile_x[from_xlow - 1] + tile_width; } else if(from_xlow < to_xlow) { x1 = tile_x[to_xlow - 1] + tile_width; x2 = tile_x[to_xlow]; } /* The following then is executed when from_xlow == to_xlow */ else if(to_xhigh > from_xhigh) { /* Draw from right edge of one to other */ x1 = tile_x[from_xhigh] + tile_width; x2 = tile_x[from_xhigh + 1]; } else if(from_xhigh > to_xhigh) { x1 = tile_x[to_xhigh + 1]; x2 = tile_x[to_xhigh] + tile_width; } else { /* Complete overlap: start and end both align. Draw outside the sbox */ x1 = tile_x[from_xlow]; x2 = tile_x[from_xlow] + tile_width; } } } /* UDSD Modification by WMF End */ 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 voiddraw_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 = tile_x[from_x] + tile_width + 1 + from_track; x2 = tile_x[to_x] + tile_width + 1 + to_track; if(to_yhigh < from_ylow) { /* From upper to lower */ y1 = tile_y[from_ylow]; y2 = tile_y[to_yhigh] + tile_width; } else if(to_ylow > from_yhigh) { /* From lower to upper */ y1 = tile_y[from_yhigh] + tile_width; y2 = tile_y[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. */ /* UDSD Modification by WMF Begin */ else { if(rr_node[to_node].direction != BI_DIRECTION) { if(to_track % 2 == 0) { /* INC wire starts at bottom edge */ assert(from_ylow < to_ylow); y2 = tile_y[to_ylow]; /* since no U-turns from_track must be INC as well */ y1 = tile_y[to_ylow - 1] + tile_width; } else { /* DEC wire starts at top edge */ if(!(from_yhigh > to_yhigh)) { printf ("from_yhigh (%d) !> to_yhigh (%d).\n", from_yhigh, to_yhigh); printf ("from is (%d, %d) to (%d, %d) track %d.\n", rr_node[from_node].xhigh, rr_node[from_node].yhigh, rr_node[from_node].xlow, rr_node[from_node].ylow, rr_node[from_node].ptc_num); printf ("to is (%d, %d) to (%d, %d) track %d.\n", rr_node[to_node].xhigh, rr_node[to_node].yhigh, rr_node[to_node].xlow, rr_node[to_node].ylow, rr_node[to_node].ptc_num); exit(1); } y2 = tile_y[to_yhigh] + tile_width; y1 = tile_y[to_yhigh + 1]; } } else { if(to_ylow < from_ylow) { /* Draw from bottom edge of one to other. */ y1 = tile_y[from_ylow]; y2 = tile_y[from_ylow - 1] + tile_width; } else if(from_ylow < to_ylow) { y1 = tile_y[to_ylow - 1] + tile_width; y2 = tile_y[to_ylow]; } else if(to_yhigh > from_yhigh) { /* Draw from top edge of one to other. */ y1 = tile_y[from_yhigh] + tile_width; y2 = tile_y[from_yhigh + 1]; } else if(from_yhigh > to_yhigh) { y1 = tile_y[to_yhigh + 1]; y2 = tile_y[to_yhigh] + tile_width; } else { /* Complete overlap: start and end both align. Draw outside the sbox */ y1 = tile_y[from_ylow]; y2 = tile_y[from_ylow] + tile_width; } } } /* UDSD Modification by WMF End */ 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 voiddraw_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 voiddraw_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, ioff; float xcen, ycen; char str[BUFSIZE]; t_type_ptr type; i = rr_node[inode].xlow; j = rr_node[inode].ylow; ipin = rr_node[inode].ptc_num; type = grid[i][j].type; ioff = grid[i][j].offset; setcolor(color); iclass = type->pin_class[ipin]; /* TODO: This is where we can hide fringe physical pins and also identify globals (hide, color, show) */ for(iside = 0; iside < 4; iside++) { if(type->pinloc[grid[i][j].offset][iside][ipin]) { /* Pin exists on this side. */ get_rr_pin_draw_coords(inode, iside, ioff, &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); } }}static voidget_rr_pin_draw_coords(int inode, int iside, int ioff, 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, k, ipin, pins_per_sub_tile; float offset, xc, yc, step; t_type_ptr type; i = rr_node[inode].xlow; j = rr_node[inode].ylow + ioff; /* Need correct tile of block */ xc = tile_x[i]; yc = tile_y[j]; ipin = rr_node[inode].ptc_num; type = grid[i][j].type; pins_per_sub_tile = grid[i][j].type->num_pins / grid[i][j].type->capacity; k = ipin / pins_per_sub_tile; /* Since pins numbers go across all sub_tiles in a block in order * we can treat as a block box for this step */ /* For each sub_tile we need and extra padding space */ step = (float)(tile_width) / (float)(type->num_pins + type->capacity); offset = (ipin + k + 1) * step; switch (iside) { case LEFT: yc += offset; break; case RIGHT: xc += tile_width; yc += offset; break; case BOTTOM: xc += offset; break; case TOP: xc += offset; yc += tile_width; break; default: printf("Error in get_rr_pin_draw_coords: Unexpected iside %d.\n", iside); exit(1); break; } *xcen = xc; *ycen = yc;}static voiddrawroute(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(net[inet].is_global) /* 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]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -