Skip to content

Commit 940852d

Browse files
Merge pull request #2380 from verilog-to-routing/3D-graphics
3D FPGA block select fix, and rr-node display fix for 3D FPGAs
2 parents 190fc90 + 738f455 commit 940852d

File tree

4 files changed

+109
-66
lines changed

4 files changed

+109
-66
lines changed

vpr/src/draw/draw.cpp

Lines changed: 66 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -983,10 +983,66 @@ static void draw_router_expansion_costs(ezgl::renderer* g) {
983983
}
984984
}
985985

986+
/**
987+
* @brief Highlights the block that was clicked on, looking from the top layer downwards for 3D devices (chooses the block on the top visible layer for overlapping blocks)
988+
* It highlights the block green, as well as its fanin and fanout to blue and red respectively by updating the draw_state variables responsible for holding the
989+
* color of the block as well as its fanout and fanin.
990+
* @param x
991+
* @param y
992+
*/
986993
static void highlight_blocks(double x, double y) {
987994
t_draw_coords* draw_coords = get_draw_coords_vars();
995+
t_draw_state* draw_state = get_draw_state_vars();
988996

989997
char msg[vtr::bufsize];
998+
ClusterBlockId clb_index = get_cluster_block_id_from_xy_loc(x, y);
999+
if (clb_index == EMPTY_BLOCK_ID || clb_index == ClusterBlockId::INVALID()) {
1000+
return; /* Nothing was found on any layer*/
1001+
}
1002+
1003+
auto& cluster_ctx = g_vpr_ctx.clustering();
1004+
auto& place_ctx = g_vpr_ctx.placement();
1005+
1006+
VTR_ASSERT(clb_index != EMPTY_BLOCK_ID);
1007+
1008+
ezgl::rectangle clb_bbox = draw_coords->get_absolute_clb_bbox(clb_index, cluster_ctx.clb_nlist.block_type(clb_index));
1009+
// note: this will clear the selected sub-block if show_blk_internal is 0,
1010+
// or if it doesn't find anything
1011+
ezgl::point2d point_in_clb = ezgl::point2d(x, y) - clb_bbox.bottom_left();
1012+
highlight_sub_block(point_in_clb, clb_index,
1013+
cluster_ctx.clb_nlist.block_pb(clb_index));
1014+
1015+
if (get_selected_sub_block_info().has_selection()) {
1016+
t_pb* selected_subblock = get_selected_sub_block_info().get_selected_pb();
1017+
sprintf(msg, "sub-block %s (a \"%s\") selected",
1018+
selected_subblock->name,
1019+
selected_subblock->pb_graph_node->pb_type->name);
1020+
} else {
1021+
/* Highlight block and fan-in/fan-outs. */
1022+
draw_highlight_blocks_color(cluster_ctx.clb_nlist.block_type(clb_index),
1023+
clb_index);
1024+
sprintf(msg, "Block #%zu (%s) at (%d, %d) selected.", size_t(clb_index),
1025+
cluster_ctx.clb_nlist.block_name(clb_index).c_str(),
1026+
place_ctx.block_locs[clb_index].loc.x,
1027+
place_ctx.block_locs[clb_index].loc.y);
1028+
}
1029+
1030+
//If manual moves is activated, then user can select block from the grid.
1031+
if (draw_state->manual_moves_state.manual_move_enabled) {
1032+
draw_state->manual_moves_state.user_highlighted_block = true;
1033+
if (!draw_state->manual_moves_state.manual_move_window_is_open) {
1034+
draw_manual_moves_window(std::to_string(size_t(clb_index)));
1035+
}
1036+
}
1037+
1038+
application.update_message(msg);
1039+
application.refresh_drawing();
1040+
return;
1041+
}
1042+
1043+
ClusterBlockId get_cluster_block_id_from_xy_loc(double x, double y) {
1044+
t_draw_coords* draw_coords = get_draw_coords_vars();
1045+
t_draw_state* draw_state = get_draw_state_vars();
9901046
ClusterBlockId clb_index = EMPTY_BLOCK_ID;
9911047
auto& device_ctx = g_vpr_ctx.device();
9921048
auto& cluster_ctx = g_vpr_ctx.clustering();
@@ -995,8 +1051,11 @@ static void highlight_blocks(double x, double y) {
9951051
/// determine block ///
9961052
ezgl::rectangle clb_bbox;
9971053

998-
//iterate over grid z (layers) first, so we draw from bottom to top die. This makes partial transparency of layers draw properly.
999-
for (int layer_num = 0; layer_num < device_ctx.grid.get_num_layers(); layer_num++) {
1054+
//iterate over grid z (layers) first. Start search of the block at the top layer to prioritize highlighting of blocks at higher levels during overlapping of layers.
1055+
for (int layer_num = device_ctx.grid.get_num_layers() - 1; layer_num >= 0; layer_num--) {
1056+
if (!draw_state->draw_layer_display[layer_num].visible) {
1057+
continue; /* Don't check for blocks on non-visible layers*/
1058+
}
10001059
// iterate over grid x
10011060
for (int i = 0; i < (int)device_ctx.grid.width(); ++i) {
10021061
if (draw_coords->tile_x[i] > x) {
@@ -1015,61 +1074,17 @@ static void highlight_blocks(double x, double y) {
10151074
clb_bbox = draw_coords->get_absolute_clb_bbox(clb_index,
10161075
cluster_ctx.clb_nlist.block_type(clb_index));
10171076
if (clb_bbox.contains({x, y})) {
1018-
break;
1077+
return clb_index; // we've found the clb
10191078
} else {
10201079
clb_index = EMPTY_BLOCK_ID;
10211080
}
10221081
}
10231082
}
1024-
if (clb_index != EMPTY_BLOCK_ID) {
1025-
break; // we've found something
1026-
}
1027-
}
1028-
if (clb_index != EMPTY_BLOCK_ID) {
1029-
break; // we've found something
10301083
}
10311084
}
1032-
1033-
if (clb_index == EMPTY_BLOCK_ID || clb_index == ClusterBlockId::INVALID()) {
1034-
//Nothing found
1035-
return;
1036-
}
1037-
1038-
VTR_ASSERT(clb_index != EMPTY_BLOCK_ID);
1039-
1040-
// note: this will clear the selected sub-block if show_blk_internal is 0,
1041-
// or if it doesn't find anything
1042-
ezgl::point2d point_in_clb = ezgl::point2d(x, y) - clb_bbox.bottom_left();
1043-
highlight_sub_block(point_in_clb, clb_index,
1044-
cluster_ctx.clb_nlist.block_pb(clb_index));
1045-
1046-
if (get_selected_sub_block_info().has_selection()) {
1047-
t_pb* selected_subblock = get_selected_sub_block_info().get_selected_pb();
1048-
sprintf(msg, "sub-block %s (a \"%s\") selected",
1049-
selected_subblock->name,
1050-
selected_subblock->pb_graph_node->pb_type->name);
1051-
} else {
1052-
/* Highlight block and fan-in/fan-outs. */
1053-
draw_highlight_blocks_color(cluster_ctx.clb_nlist.block_type(clb_index),
1054-
clb_index);
1055-
sprintf(msg, "Block #%zu (%s) at (%d, %d) selected.", size_t(clb_index),
1056-
cluster_ctx.clb_nlist.block_name(clb_index).c_str(),
1057-
place_ctx.block_locs[clb_index].loc.x,
1058-
place_ctx.block_locs[clb_index].loc.y);
1059-
}
1060-
1061-
//If manual moves is activated, then user can select block from the grid.
1062-
t_draw_state* draw_state = get_draw_state_vars();
1063-
if (draw_state->manual_moves_state.manual_move_enabled) {
1064-
draw_state->manual_moves_state.user_highlighted_block = true;
1065-
if (!draw_state->manual_moves_state.manual_move_window_is_open) {
1066-
draw_manual_moves_window(std::to_string(size_t(clb_index)));
1067-
}
1068-
}
1069-
1070-
application.update_message(msg);
1071-
application.refresh_drawing();
10721085
}
1086+
// Searched all layers and found no clb at specified location, returning clb_index = EMPTY_BLOCK_ID.
1087+
return clb_index;
10731088
}
10741089

10751090
static void setup_default_ezgl_callbacks(ezgl::application* app) {
@@ -1450,8 +1465,8 @@ t_draw_layer_display get_element_visibility_and_transparency(int src_layer, int
14501465
element_visibility.visible = true;
14511466
bool cross_layer_enabled = draw_state->cross_layer_display.visible;
14521467

1453-
//To only show primitive nets that are connected to currently active layers on the screen
1454-
if (!draw_state->draw_layer_display[sink_layer].visible || (!cross_layer_enabled && src_layer != sink_layer)) {
1468+
//To only show elements (net flylines,noc links,etc...) that are connected to currently active layers on the screen
1469+
if (!draw_state->draw_layer_display[sink_layer].visible || !draw_state->draw_layer_display[src_layer].visible || (!cross_layer_enabled && src_layer != sink_layer)) {
14551470
element_visibility.visible = false; /* Don't Draw */
14561471
}
14571472

vpr/src/draw/draw.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,17 @@ bool rgb_is_same(ezgl::color color1, ezgl::color color2);
155155
*/
156156
t_draw_layer_display get_element_visibility_and_transparency(int src_layer, int sink_layer);
157157

158+
/**
159+
* @brief takes in the x and y world coordinates of where the user clicked on the screen and returns the corresponding clusterBlockId that represents
160+
* the clb clicked upon by the user on a currently visible FPGA layer. Search for the clb begins from the top layer to ensure it
161+
* returns the clusterBlockId of a clb on a higher layer during instances of overlap between clb blocks.
162+
* @param x
163+
* @param y
164+
* @return returns the ClusterBlockId of the clb at the specified (x,y) location (in world coordinates) as seen by looking downwards from the top of a 3D FPGA.
165+
* Chooses the clb on the top visible layer if there are overlapping blocks. Returns EMPTY_BLOCK_ID (-1) otherwise,if clb is not found on any visible layer.
166+
*/
167+
ClusterBlockId get_cluster_block_id_from_xy_loc(double x, double y);
168+
158169
#endif /* NO_GRAPHICS */
159170

160171
#endif /* DRAW_H */

vpr/src/draw/draw_basic.cpp

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -653,25 +653,31 @@ void draw_partial_route(const std::vector<RRNodeId>& rr_nodes_to_draw, ezgl::ren
653653
auto rr_type = rr_graph.node_type(inode);
654654

655655
RRNodeId prev_node = rr_nodes_to_draw[i - 1];
656-
RRNodeId prev_rr_node = prev_node;
657656
auto prev_type = rr_graph.node_type(RRNodeId(prev_node));
658657

659658
auto iedge = find_edge(prev_node, inode);
660659
auto switch_type = rr_graph.edge_switch(RRNodeId(prev_node), iedge);
661660

661+
int current_node_layer = rr_graph.node_layer(inode);
662+
int prev_node_layer = rr_graph.node_layer(prev_node);
663+
t_draw_layer_display edge_visibility = get_element_visibility_and_transparency(prev_node_layer, current_node_layer);
664+
662665
//Don't draw node if the layer of the node is not set to visible on screen
663-
if (!draw_state->draw_layer_display[rr_graph.node_layer(inode)].visible) {
666+
if (!draw_state->draw_layer_display[current_node_layer].visible) {
664667
continue;
665668
}
666669

670+
ezgl::color color = draw_state->draw_rr_node[inode].color;
671+
667672
switch (rr_type) {
668673
case OPIN: {
669-
draw_rr_pin(inode, draw_state->draw_rr_node[inode].color, g);
674+
draw_rr_pin(inode, color, g);
670675
break;
671676
}
672677
case IPIN: {
673-
draw_rr_pin(inode, draw_state->draw_rr_node[inode].color, g);
674-
if (is_edge_valid_to_draw(inode, prev_rr_node)) {
678+
draw_rr_pin(inode, color, g);
679+
if (edge_visibility.visible) {
680+
g->set_color(color, edge_visibility.alpha);
675681
if (rr_graph.node_type(prev_node) == OPIN) {
676682
draw_pin_to_pin(prev_node, inode, g);
677683
} else {
@@ -684,8 +690,9 @@ void draw_partial_route(const std::vector<RRNodeId>& rr_nodes_to_draw, ezgl::ren
684690
if (draw_state->draw_route_type == GLOBAL)
685691
chanx_track[rr_graph.node_xlow(inode)][rr_graph.node_ylow(inode)]++;
686692

687-
draw_rr_chan(inode, draw_state->draw_rr_node[inode].color, g);
688-
if (is_edge_valid_to_draw(inode, prev_rr_node)) {
693+
draw_rr_chan(inode, color, g);
694+
if (edge_visibility.visible) {
695+
g->set_color(color, edge_visibility.alpha);
689696
switch (prev_type) {
690697
case CHANX: {
691698
draw_chanx_to_chanx_edge(prev_node, inode, switch_type, g);
@@ -713,9 +720,10 @@ void draw_partial_route(const std::vector<RRNodeId>& rr_nodes_to_draw, ezgl::ren
713720
if (draw_state->draw_route_type == GLOBAL)
714721
chany_track[rr_graph.node_xlow(inode)][rr_graph.node_ylow(inode)]++;
715722

716-
draw_rr_chan(inode, draw_state->draw_rr_node[inode].color, g);
723+
draw_rr_chan(inode, color, g);
717724

718-
if (is_edge_valid_to_draw(inode, prev_rr_node)) {
725+
if (edge_visibility.visible) {
726+
g->set_color(color, edge_visibility.alpha);
719727
switch (prev_type) {
720728
case CHANX: {
721729
draw_chanx_to_chany_edge(prev_node, inode,
@@ -1049,12 +1057,14 @@ void draw_crit_path(ezgl::renderer* g) {
10491057
int src_block_layer = get_timing_path_node_layer_num(node);
10501058
int sink_block_layer = get_timing_path_node_layer_num(prev_node);
10511059

1060+
t_draw_layer_display flyline_visibility = get_element_visibility_and_transparency(src_block_layer, sink_block_layer);
1061+
10521062
if (draw_state->show_crit_path == DRAW_CRIT_PATH_FLYLINES
10531063
|| draw_state->show_crit_path
10541064
== DRAW_CRIT_PATH_FLYLINES_DELAYS) {
10551065
// FLylines for critical path are drawn based on the layer visibility of the source and sink
1056-
if (is_flyline_valid_to_draw(src_block_layer, sink_block_layer)) {
1057-
g->set_color(color);
1066+
if (flyline_visibility.visible) {
1067+
g->set_color(color, flyline_visibility.alpha);
10581068
g->set_line_dash(ezgl::line_dash::none);
10591069
g->set_line_width(4);
10601070
draw_flyline_timing_edge(tnode_draw_coord(prev_node),
@@ -1070,10 +1080,10 @@ void draw_crit_path(ezgl::renderer* g) {
10701080
draw_routed_timing_edge_connection(prev_node, node, color, g);
10711081

10721082
// FLylines for critical path are drawn based on the layer visibility of the source and sink
1073-
if (is_flyline_valid_to_draw(src_block_layer, sink_block_layer)) {
1083+
if (flyline_visibility.visible) {
10741084
g->set_line_dash(ezgl::line_dash::asymmetric_5_3);
10751085
g->set_line_width(3);
1076-
g->set_color(color);
1086+
g->set_color(color, flyline_visibility.alpha);
10771087

10781088
draw_flyline_timing_edge((ezgl::point2d)tnode_draw_coord(prev_node),
10791089
(ezgl::point2d)tnode_draw_coord(node), (float)delay,

vpr/src/draw/draw_rr.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,10 @@ void draw_expand_non_configurable_rr_nodes_recurr(RRNodeId from_node,
682682

683683
/* This is a helper function for highlight_rr_nodes(). It determines whether
684684
* a routing resource has been clicked on by computing a bounding box for that
685-
* and checking if the mouse click hit inside its bounding box.
685+
* and checking if the mouse click hit inside its bounding box. The function does not check
686+
* routing resources that are on currently invisible layers (layer view is toggled off) to ensure that
687+
* only resources on visible layers are set to be highlighted. There is no priority based on FPGA layer
688+
* for highlighting routing resources (Does not iterate through nodes by order of layer a node is located on).
686689
*
687690
* It returns the hit RR node's ID (or OPEN if no hit)
688691
*/
@@ -691,16 +694,20 @@ RRNodeId draw_check_rr_node_hit(float click_x, float click_y) {
691694
ezgl::rectangle bound_box;
692695

693696
t_draw_coords* draw_coords = get_draw_coords_vars();
697+
t_draw_state* draw_state = get_draw_state_vars();
694698
auto& device_ctx = g_vpr_ctx.device();
695699
const auto& rr_graph = device_ctx.rr_graph;
696700

697701
for (const RRNodeId& inode : device_ctx.rr_graph.nodes()) {
702+
int layer_num = rr_graph.node_layer(inode);
703+
if (!draw_state->draw_layer_display[layer_num].visible) {
704+
continue; /* Don't check RR nodes on currently invisible layers*/
705+
}
698706
switch (rr_graph.node_type(inode)) {
699707
case IPIN:
700708
case OPIN: {
701709
int i = rr_graph.node_xlow(inode);
702710
int j = rr_graph.node_ylow(inode);
703-
int layer_num = rr_graph.node_layer(inode);
704711
t_physical_tile_type_ptr type = device_ctx.grid.get_physical_type({i, j, layer_num});
705712
int width_offset = device_ctx.grid.get_width_offset({i, j, layer_num});
706713
int height_offset = device_ctx.grid.get_height_offset({i, j, layer_num});

0 commit comments

Comments
 (0)