@@ -2121,24 +2121,32 @@ static void draw_rr_pin(int inode, const ezgl::color& color, ezgl::renderer* g)
2121
2121
g->set_color (color);
2122
2122
2123
2123
/* TODO: This is where we can hide fringe physical pins and also identify globals (hide, color, show) */
2124
- draw_get_rr_pin_coords (inode, &xcen, &ycen);
2125
- g->fill_rectangle ({xcen - draw_coords->pin_size , ycen - draw_coords->pin_size },
2126
- {xcen + draw_coords->pin_size , ycen + draw_coords->pin_size });
2127
- sprintf (str, " %d" , ipin);
2128
- g->set_color (ezgl::BLACK);
2129
- g->draw_text ({xcen, ycen}, str, 2 * draw_coords->pin_size , 2 * draw_coords->pin_size );
2130
- g->set_color (color);
2124
+ /* As nodes may appear on more than one side, walk through the possible nodes
2125
+ * - draw the pin on each side that it appears
2126
+ */
2127
+ for (const e_side& pin_side : SIDES) {
2128
+ if (!device_ctx.rr_nodes [inode].is_node_on_specific_side (pin_side)) {
2129
+ continue ;
2130
+ }
2131
+ draw_get_rr_pin_coords (inode, &xcen, &ycen, pin_side);
2132
+ g->fill_rectangle ({xcen - draw_coords->pin_size , ycen - draw_coords->pin_size },
2133
+ {xcen + draw_coords->pin_size , ycen + draw_coords->pin_size });
2134
+ sprintf (str, " %d" , ipin);
2135
+ g->set_color (ezgl::BLACK);
2136
+ g->draw_text ({xcen, ycen}, str, 2 * draw_coords->pin_size , 2 * draw_coords->pin_size );
2137
+ g->set_color (color);
2138
+ }
2131
2139
}
2132
2140
2133
2141
/* Returns the coordinates at which the center of this pin should be drawn. *
2134
2142
* inode gives the node number, and iside gives the side of the clb or pad *
2135
2143
* the physical pin is on. */
2136
- void draw_get_rr_pin_coords (int inode, float * xcen, float * ycen) {
2144
+ void draw_get_rr_pin_coords (int inode, float * xcen, float * ycen, const e_side& pin_side ) {
2137
2145
auto & device_ctx = g_vpr_ctx.device ();
2138
- draw_get_rr_pin_coords (device_ctx.rr_nodes [inode], xcen, ycen);
2146
+ draw_get_rr_pin_coords (device_ctx.rr_nodes [inode], xcen, ycen, pin_side );
2139
2147
}
2140
2148
2141
- void draw_get_rr_pin_coords (const t_rr_node& node, float * xcen, float * ycen) {
2149
+ void draw_get_rr_pin_coords (const t_rr_node& node, float * xcen, float * ycen, const e_side& pin_side ) {
2142
2150
t_draw_coords* draw_coords = get_draw_coords_vars ();
2143
2151
2144
2152
int i, j, k, ipin, pins_per_sub_tile;
@@ -2164,7 +2172,7 @@ void draw_get_rr_pin_coords(const t_rr_node& node, float* xcen, float* ycen) {
2164
2172
step = (float )(draw_coords->get_tile_width ()) / (float )(type->num_pins + type->capacity );
2165
2173
offset = (ipin + k + 1 ) * step;
2166
2174
2167
- switch (node. side () ) {
2175
+ switch (pin_side ) {
2168
2176
case LEFT:
2169
2177
yc += offset;
2170
2178
break ;
@@ -2185,7 +2193,8 @@ void draw_get_rr_pin_coords(const t_rr_node& node, float* xcen, float* ycen) {
2185
2193
2186
2194
default :
2187
2195
vpr_throw (VPR_ERROR_OTHER, __FILE__, __LINE__,
2188
- " in draw_get_rr_pin_coords: Unexpected side %s.\n " , node.side_string ());
2196
+ " in draw_get_rr_pin_coords: Unexpected side %s.\n " ,
2197
+ SIDE_STRING[pin_side]);
2189
2198
break ;
2190
2199
}
2191
2200
@@ -2588,11 +2597,10 @@ static int draw_check_rr_node_hit(float click_x, float click_y) {
2588
2597
int height_offset = device_ctx.grid [i][j].height_offset ;
2589
2598
int ipin = device_ctx.rr_nodes [inode].ptc_num ();
2590
2599
float xcen, ycen;
2591
- int iside;
2592
- for (iside = 0 ; iside < 4 ; iside++) {
2600
+ for (const e_side& iside : SIDES) {
2593
2601
// If pin exists on this side of the block, then get pin coordinates
2594
- if (type->pinloc [width_offset][height_offset][iside][ipin]) {
2595
- draw_get_rr_pin_coords (inode, &xcen, &ycen);
2602
+ if (type->pinloc [width_offset][height_offset][size_t ( iside) ][ipin]) {
2603
+ draw_get_rr_pin_coords (inode, &xcen, &ycen, iside );
2596
2604
2597
2605
// Now check if we clicked on this pin
2598
2606
if (click_x >= xcen - draw_coords->pin_size && click_x <= xcen + draw_coords->pin_size && click_y >= ycen - draw_coords->pin_size && click_y <= ycen + draw_coords->pin_size ) {
@@ -2955,19 +2963,108 @@ static void draw_pin_to_chan_edge(int pin_node, int chan_node, ezgl::renderer* g
2955
2963
2956
2964
const t_grid_tile& grid_tile = device_ctx.grid [pin_rr.xlow ()][pin_rr.ylow ()];
2957
2965
t_physical_tile_type_ptr grid_type = grid_tile.type ;
2958
- VTR_ASSERT_MSG (grid_type->pinloc [grid_tile.width_offset ][grid_tile.height_offset ][pin_rr.side ()][pin_rr.pin_num ()],
2959
- " Pin coordinates should match block type pin locations" );
2960
2966
2967
+ float x1 = 0 , y1 = 0 ;
2968
+ /* If there is only one side, no need for the following inference!!!
2969
+ * When a node may have multiple sides,
2970
+ * we lack direct information about which side of the node drives the channel node
2971
+ * However, we can infer which side is actually used by the driver based on the
2972
+ * coordinates of the channel node.
2973
+ * In principle, in a regular rr_graph that can pass check_rr_graph() function,
2974
+ * the coordinates should follow the illustration:
2975
+ *
2976
+ * +----------+
2977
+ * | CHANX |
2978
+ * | [x][y] |
2979
+ * +----------+
2980
+ * +----------+ +----------+ +--------+
2981
+ * | | | | | |
2982
+ * | CHANY | | Grid | | CHANY |
2983
+ * | [x-1][y] | | [x][y] | | [x][y] |
2984
+ * | | | | | |
2985
+ * +----------+ +----------+ +--------+
2986
+ * +----------+
2987
+ * | CHANX |
2988
+ * | [x][y-1] |
2989
+ * +----------+
2990
+ *
2991
+ *
2992
+ * Therefore, when there are multiple side:
2993
+ * - a TOP side node is considered when the ylow of CHANX >= ylow of the node
2994
+ * - a BOTTOM side node is considered when the ylow of CHANX <= ylow - 1 of the node
2995
+ * - a RIGHT side node is considered when the xlow of CHANY >= xlow of the node
2996
+ * - a LEFT side node is considered when the xlow of CHANY <= xlow - 1 of the node
2997
+ *
2998
+ * Note: ylow == yhigh for CHANX and xlow == xhigh for CHANY
2999
+ *
3000
+ * Note: Similar rules are applied for grid that has width > 1 and height > 1
3001
+ * This is because (xlow, ylow) or (xhigh, yhigh) of the node follows
3002
+ * the actual offset of the pin in the context of grid width and height
3003
+ */
3004
+ std::vector<e_side> pin_candidate_sides;
3005
+ for (const e_side& pin_candidate_side : SIDES) {
3006
+ if ((pin_rr.is_node_on_specific_side (pin_candidate_side))
3007
+ && (grid_type->pinloc [grid_tile.width_offset ][grid_tile.height_offset ][pin_candidate_side][pin_rr.pin_num ()])) {
3008
+ pin_candidate_sides.push_back (pin_candidate_side);
3009
+ }
3010
+ }
3011
+ /* Only 1 side will be picked in the end
3012
+ * Any rr_node of a grid should have at least 1 side!!!
3013
+ */
3014
+ e_side pin_side = NUM_SIDES;
3015
+ if (1 == pin_candidate_sides.size ()) {
3016
+ pin_side = pin_candidate_sides[0 ];
3017
+ } else {
3018
+ VTR_ASSERT (1 < pin_candidate_sides.size ());
3019
+ if (CHANX == chan_rr.type () && pin_rr.ylow () <= chan_rr.ylow ()) {
3020
+ pin_side = TOP;
3021
+ } else if (CHANX == chan_rr.type () && pin_rr.ylow () - 1 >= chan_rr.ylow ()) {
3022
+ pin_side = BOTTOM;
3023
+ } else if (CHANY == chan_rr.type () && pin_rr.xlow () <= chan_rr.xlow ()) {
3024
+ pin_side = RIGHT;
3025
+ } else if (CHANY == chan_rr.type () && pin_rr.xlow () - 1 >= chan_rr.xlow ()) {
3026
+ pin_side = LEFT;
3027
+ }
3028
+ /* The inferred side must be in the list of sides of the pin rr_node!!! */
3029
+ VTR_ASSERT (pin_candidate_sides.end () != std::find (pin_candidate_sides.begin (), pin_candidate_sides.end (), pin_side));
3030
+ }
3031
+ /* Sanity check */
3032
+ VTR_ASSERT (NUM_SIDES != pin_side);
3033
+
3034
+ /* Now we determine which side to be used, calculate the offset for the pin to be drawn
3035
+ * - For the pin locates above/right to the grid (at the top/right side),
3036
+ * a positive offset (+ve) is required
3037
+ * - For the pin locates below/left to the grid (at the bottom/left side),
3038
+ * a negative offset (-ve) is required
3039
+ *
3040
+ * y
3041
+ * ^ +-----+ ---
3042
+ * | | PIN | ^
3043
+ * | | | offset
3044
+ * | | | v
3045
+ * | +-----------+-----+----------+
3046
+ * | | |<- offset ->|
3047
+ * | |<-offset->| +------------+
3048
+ * | +----------+ Grid | PIN |
3049
+ * | | PIN | +------------+
3050
+ * | +----------+ |
3051
+ * | | |
3052
+ * | +---+-----+------------------+
3053
+ * | ^ | |
3054
+ * | offset | PIN |
3055
+ * | v | |
3056
+ * | ----+-----+
3057
+ * +------------------------------------------------------------>x
3058
+ */
2961
3059
float draw_pin_offset;
2962
- if (pin_rr. side () == TOP || pin_rr. side () == RIGHT ) {
3060
+ if (TOP == pin_side || RIGHT == pin_side ) {
2963
3061
draw_pin_offset = draw_coords->pin_size ;
2964
3062
} else {
2965
- VTR_ASSERT (pin_rr. side () == BOTTOM || pin_rr. side () == LEFT );
3063
+ VTR_ASSERT (BOTTOM == pin_side || LEFT == pin_side );
2966
3064
draw_pin_offset = -draw_coords->pin_size ;
2967
3065
}
2968
3066
2969
- float x1 = 0 , y1 = 0 ;
2970
- draw_get_rr_pin_coords (pin_node, &x1, &y1);
3067
+ draw_get_rr_pin_coords (pin_node, &x1, &y1, pin_side);
2971
3068
2972
3069
ezgl::rectangle chan_bbox = draw_get_rr_chan_bbox (chan_node);
2973
3070
@@ -3022,11 +3119,30 @@ static void draw_pin_to_pin(int opin_node, int ipin_node, ezgl::renderer* g) {
3022
3119
VTR_ASSERT (device_ctx.rr_nodes [opin_node].type () == OPIN);
3023
3120
VTR_ASSERT (device_ctx.rr_nodes [ipin_node].type () == IPIN);
3024
3121
3122
+ /* FIXME: May use a smarter strategy
3123
+ * Currently, we use the last side found for both OPIN and IPIN
3124
+ * when draw the direct connection between the two nodes
3125
+ * Note: tried first side but see missing connections
3126
+ */
3025
3127
float x1 = 0 , y1 = 0 ;
3026
- draw_get_rr_pin_coords (opin_node, &x1, &y1);
3128
+ std::vector<e_side> opin_candidate_sides;
3129
+ for (const e_side& opin_candidate_side : SIDES) {
3130
+ if (device_ctx.rr_nodes [opin_node].is_node_on_specific_side (opin_candidate_side)) {
3131
+ opin_candidate_sides.push_back (opin_candidate_side);
3132
+ }
3133
+ }
3134
+ VTR_ASSERT (1 <= opin_candidate_sides.size ());
3135
+ draw_get_rr_pin_coords (opin_node, &x1, &y1, opin_candidate_sides.back ());
3027
3136
3028
3137
float x2 = 0 , y2 = 0 ;
3029
- draw_get_rr_pin_coords (ipin_node, &x2, &y2);
3138
+ std::vector<e_side> ipin_candidate_sides;
3139
+ for (const e_side& ipin_candidate_side : SIDES) {
3140
+ if (device_ctx.rr_nodes [ipin_node].is_node_on_specific_side (ipin_candidate_side)) {
3141
+ ipin_candidate_sides.push_back (ipin_candidate_side);
3142
+ }
3143
+ }
3144
+ VTR_ASSERT (1 <= ipin_candidate_sides.size ());
3145
+ draw_get_rr_pin_coords (ipin_node, &x2, &y2, ipin_candidate_sides.back ());
3030
3146
3031
3147
g->draw_line ({x1, y1}, {x2, y2});
3032
3148
@@ -3039,16 +3155,23 @@ static void draw_pin_to_sink(int ipin_node, int sink_node, ezgl::renderer* g) {
3039
3155
auto & device_ctx = g_vpr_ctx.device ();
3040
3156
3041
3157
float x1 = 0 , y1 = 0 ;
3042
- draw_get_rr_pin_coords (ipin_node, &x1, &y1);
3158
+ /* Draw the line for each ipin on different sides */
3159
+ for (const e_side& pin_side : SIDES) {
3160
+ if (!device_ctx.rr_nodes [ipin_node].is_node_on_specific_side (pin_side)) {
3161
+ continue ;
3162
+ }
3043
3163
3044
- float x2 = 0 , y2 = 0 ;
3045
- draw_get_rr_src_sink_coords (device_ctx.rr_nodes [sink_node], &x2, &y2);
3164
+ draw_get_rr_pin_coords (ipin_node, &x1, &y1, pin_side);
3046
3165
3047
- g->draw_line ({x1, y1}, {x2, y2});
3166
+ float x2 = 0 , y2 = 0 ;
3167
+ draw_get_rr_src_sink_coords (device_ctx.rr_nodes [sink_node], &x2, &y2);
3048
3168
3049
- float xend = x2 + (x1 - x2) / 10 .;
3050
- float yend = y2 + (y1 - y2) / 10 .;
3051
- draw_triangle_along_line (g, xend, yend, x1, x2, y1, y2);
3169
+ g->draw_line ({x1, y1}, {x2, y2});
3170
+
3171
+ float xend = x2 + (x1 - x2) / 10 .;
3172
+ float yend = y2 + (y1 - y2) / 10 .;
3173
+ draw_triangle_along_line (g, xend, yend, x1, x2, y1, y2);
3174
+ }
3052
3175
}
3053
3176
3054
3177
static void draw_source_to_pin (int source_node, int opin_node, ezgl::renderer* g) {
@@ -3057,14 +3180,21 @@ static void draw_source_to_pin(int source_node, int opin_node, ezgl::renderer* g
3057
3180
float x1 = 0 , y1 = 0 ;
3058
3181
draw_get_rr_src_sink_coords (device_ctx.rr_nodes [source_node], &x1, &y1);
3059
3182
3060
- float x2 = 0 , y2 = 0 ;
3061
- draw_get_rr_pin_coords (opin_node, &x2, &y2);
3183
+ /* Draw the line for each ipin on different sides */
3184
+ for (const e_side& pin_side : SIDES) {
3185
+ if (!device_ctx.rr_nodes [opin_node].is_node_on_specific_side (pin_side)) {
3186
+ continue ;
3187
+ }
3062
3188
3063
- g->draw_line ({x1, y1}, {x2, y2});
3189
+ float x2 = 0 , y2 = 0 ;
3190
+ draw_get_rr_pin_coords (opin_node, &x2, &y2, pin_side);
3064
3191
3065
- float xend = x2 + (x1 - x2) / 10 .;
3066
- float yend = y2 + (y1 - y2) / 10 .;
3067
- draw_triangle_along_line (g, xend, yend, x1, x2, y1, y2);
3192
+ g->draw_line ({x1, y1}, {x2, y2});
3193
+
3194
+ float xend = x2 + (x1 - x2) / 10 .;
3195
+ float yend = y2 + (y1 - y2) / 10 .;
3196
+ draw_triangle_along_line (g, xend, yend, x1, x2, y1, y2);
3197
+ }
3068
3198
}
3069
3199
3070
3200
static inline void draw_mux_with_size (ezgl::point2d origin, e_side orientation, float height, int size, ezgl::renderer* g) {
0 commit comments