diff --git a/vpr/src/draw/draw.cpp b/vpr/src/draw/draw.cpp index 0061fad803..8a63c00285 100644 --- a/vpr/src/draw/draw.cpp +++ b/vpr/src/draw/draw.cpp @@ -658,7 +658,7 @@ int get_track_num(int inode, const vtr::OffsetMatrix& chanx_track, const vt * could be caused by the user clicking on a routing resource, toggled, or * fan-in/fan-out of a highlighted node. */ -bool draw_if_net_highlighted(ClusterNetId inet) { +bool draw_if_net_highlighted(ParentNetId inet) { t_draw_state* draw_state = get_draw_state_vars(); if (draw_state->net_color[inet] != DEFAULT_RR_NODE_COLOR) { diff --git a/vpr/src/draw/draw.h b/vpr/src/draw/draw.h index 6224bf49b9..294e3d37ff 100644 --- a/vpr/src/draw/draw.h +++ b/vpr/src/draw/draw.h @@ -94,7 +94,7 @@ ezgl::color to_ezgl_color(vtr::Color color); /* This helper function determines whether a net has been highlighted. The highlighting * could be caused by the user clicking on a routing resource, toggled, or * fan-in/fan-out of a highlighted node. */ -bool draw_if_net_highlighted(ClusterNetId inet); +bool draw_if_net_highlighted(ParentNetId inet); std::vector trace_routed_connection_rr_nodes( ClusterNetId net_id, int driver_pin, diff --git a/vpr/src/draw/draw_basic.cpp b/vpr/src/draw/draw_basic.cpp index bd0d0495a0..ac312afd39 100644 --- a/vpr/src/draw/draw_basic.cpp +++ b/vpr/src/draw/draw_basic.cpp @@ -569,13 +569,9 @@ void drawroute(enum e_draw_net_type draw_net_type, ezgl::renderer* g) { void draw_routed_net(ParentNetId net_id, ezgl::renderer* g) { auto& route_ctx = g_vpr_ctx.routing(); - auto& cluster_ctx = g_vpr_ctx.clustering(); t_draw_state* draw_state = get_draw_state_vars(); - if (cluster_ctx.clb_nlist.net_is_ignored(convert_to_cluster_net_id(net_id))) /* Don't draw. */ - return; - if (!route_ctx.route_trees[net_id]) // No routing -> Skip. (Allows me to draw partially complete routes) return; @@ -583,10 +579,10 @@ void draw_routed_net(ParentNetId net_id, ezgl::renderer* g) { for (auto& rt_node : route_ctx.route_trees[net_id].value().all_nodes()) { RRNodeId inode = rt_node.inode; - if (draw_if_net_highlighted(convert_to_cluster_net_id(net_id))) { + if (draw_if_net_highlighted(net_id)) { /* If a net has been highlighted, highlight the whole net in * * the same color. */ - draw_state->draw_rr_node[inode].color = draw_state->net_color[convert_to_cluster_net_id(net_id)]; + draw_state->draw_rr_node[inode].color = draw_state->net_color[net_id]; draw_state->draw_rr_node[inode].node_highlighted = true; } else { /* If not highlighted, draw the node in default color. */ @@ -616,133 +612,139 @@ void draw_partial_route(const std::vector& rr_nodes_to_draw, ezgl::ren auto& device_ctx = g_vpr_ctx.device(); const auto& rr_graph = device_ctx.rr_graph; - static vtr::OffsetMatrix chanx_track; /* [1..device_ctx.grid.width() - 2][0..device_ctx.grid.height() - 2] */ - static vtr::OffsetMatrix chany_track; /* [0..device_ctx.grid.width() - 2][1..device_ctx.grid.height() - 2] */ - if (draw_state->draw_route_type == e_route_type::GLOBAL) { - /* Allocate some temporary storage if it's not already available. */ - int width = (int)device_ctx.grid.width(); - int height = (int)device_ctx.grid.height(); - if (chanx_track.empty()) { - chanx_track = vtr::OffsetMatrix({{{1, width - 1}, {0, height - 1}}}); + // Draw Pins + for (size_t i = 1; i < rr_nodes_to_draw.size(); ++i) { + RRNodeId inode = rr_nodes_to_draw[i]; + auto rr_type = rr_graph.node_type(inode); + bool is_inode_inter_cluster = is_inter_cluster_node(rr_graph, inode); + int node_layer = rr_graph.node_layer(inode); + + ezgl::color color = draw_state->draw_rr_node[inode].color; + + // For 3D architectures, draw only visible layers + if (!draw_state->draw_layer_display[node_layer].visible) { + continue; + } + + // Skip drawing sources and sinks + if (rr_type == e_rr_type::SINK || rr_type == e_rr_type::SOURCE) { + continue; } - if (chany_track.empty()) { - chany_track = vtr::OffsetMatrix({{{0, width - 1}, {1, height - 1}}}); + // Draw intra-cluster nodes + if (!is_inode_inter_cluster) { + draw_rr_intrapin(inode, color, g); + continue; } - for (int i = 1; i < width - 1; i++) - for (int j = 0; j < height - 1; j++) - chanx_track[i][j] = (-1); + // Draw IO Pins + if (rr_type == e_rr_type::OPIN || rr_type == e_rr_type::IPIN) { + draw_rr_pin(inode, color, g); + continue; + } - for (int i = 0; i < width - 1; i++) - for (int j = 1; j < height - 1; j++) - chany_track[i][j] = (-1); + // Draw Channels + if (rr_type == e_rr_type::CHANY || rr_type == e_rr_type::CHANX) { + draw_rr_chan(inode, color, g); + continue; + } } + // Draw Edges for (size_t i = 1; i < rr_nodes_to_draw.size(); ++i) { + RRNodeId inode = rr_nodes_to_draw[i]; auto rr_type = rr_graph.node_type(inode); + bool is_inode_inter_cluster = is_inter_cluster_node(rr_graph, inode); + int current_node_layer = rr_graph.node_layer(inode); RRNodeId prev_node = rr_nodes_to_draw[i - 1]; auto prev_type = rr_graph.node_type(RRNodeId(prev_node)); + bool is_prev_node_inter_cluster = is_inter_cluster_node(rr_graph, prev_node); + int prev_node_layer = rr_graph.node_layer(prev_node); + + t_draw_layer_display edge_visibility = get_element_visibility_and_transparency(prev_node_layer, current_node_layer); + ezgl::color color = draw_state->draw_rr_node[inode].color; - if (!is_inter_cluster_node(rr_graph, prev_node) || !is_inter_cluster_node(rr_graph, inode)) { + // For 3D architectures, draw only visible layers + if (!draw_state->draw_layer_display[current_node_layer].visible || !edge_visibility.visible) { continue; } - auto iedge = find_edge(prev_node, inode); - auto switch_type = rr_graph.edge_switch(RRNodeId(prev_node), iedge); + // Skip drawing sources and sinks + if (rr_type == e_rr_type::SINK || rr_type == e_rr_type::SOURCE || prev_type == e_rr_type::SINK || prev_type == e_rr_type::SOURCE) { + continue; + } - int current_node_layer = rr_graph.node_layer(inode); - int prev_node_layer = rr_graph.node_layer(prev_node); - t_draw_layer_display edge_visibility = get_element_visibility_and_transparency(prev_node_layer, current_node_layer); + g->set_color(color, edge_visibility.alpha); - //Don't draw node if the layer of the node is not set to visible on screen - if (!draw_state->draw_layer_display[current_node_layer].visible) { + if (!is_inode_inter_cluster && !is_prev_node_inter_cluster) { + draw_intrapin_to_intrapin(inode, prev_node, g); continue; } - ezgl::color color = draw_state->draw_rr_node[inode].color; + if (!is_inode_inter_cluster || !is_prev_node_inter_cluster) { + draw_intrapin_to_pin(inode, prev_node, g); + continue; + } + + auto iedge = find_edge(prev_node, inode); + auto switch_type = rr_graph.edge_switch(RRNodeId(prev_node), iedge); switch (rr_type) { - case e_rr_type::OPIN: { - draw_rr_pin(inode, color, g); - break; - } case e_rr_type::IPIN: { - draw_rr_pin(inode, color, g); - if (edge_visibility.visible) { - g->set_color(color, edge_visibility.alpha); - if (rr_graph.node_type(prev_node) == e_rr_type::OPIN) { - draw_pin_to_pin(prev_node, inode, g); - } else { - draw_pin_to_chan_edge(inode, prev_node, g); - } + if (rr_graph.node_type(prev_node) == e_rr_type::OPIN) { + draw_pin_to_pin(prev_node, inode, g); + } else { + draw_pin_to_chan_edge(inode, prev_node, g); } break; } case e_rr_type::CHANX: { - if (draw_state->draw_route_type == e_route_type::GLOBAL) - chanx_track[rr_graph.node_xlow(inode)][rr_graph.node_ylow(inode)]++; - - draw_rr_chan(inode, color, g); - if (edge_visibility.visible) { - g->set_color(color, edge_visibility.alpha); - switch (prev_type) { - case e_rr_type::CHANX: { - draw_chanx_to_chanx_edge(prev_node, inode, switch_type, g); - break; - } - case e_rr_type::CHANY: { - draw_chanx_to_chany_edge(inode, prev_node, FROM_Y_TO_X, switch_type, g); - break; - } - case e_rr_type::OPIN: { - draw_pin_to_chan_edge(prev_node, inode, g); - break; - } - default: { - VPR_ERROR(VPR_ERROR_OTHER, - "Unexpected connection from an rr_node of type %d to one of type %d.\n", - prev_type, rr_type); - } + switch (prev_type) { + case e_rr_type::CHANX: { + draw_chanx_to_chanx_edge(prev_node, inode, switch_type, g); + break; + } + case e_rr_type::CHANY: { + draw_chanx_to_chany_edge(inode, prev_node, FROM_Y_TO_X, switch_type, g); + break; + } + case e_rr_type::OPIN: { + draw_pin_to_chan_edge(prev_node, inode, g); + break; + } + default: { + VPR_ERROR(VPR_ERROR_OTHER, + "Unexpected connection from an rr_node of type %d to one of type %d.\n", + prev_type, rr_type); } } - break; } case e_rr_type::CHANY: { - if (draw_state->draw_route_type == e_route_type::GLOBAL) - chany_track[rr_graph.node_xlow(inode)][rr_graph.node_ylow(inode)]++; - - draw_rr_chan(inode, color, g); - - if (edge_visibility.visible) { - g->set_color(color, edge_visibility.alpha); - switch (prev_type) { - case e_rr_type::CHANX: { - draw_chanx_to_chany_edge(prev_node, inode, - FROM_X_TO_Y, switch_type, g); - break; - } - case e_rr_type::CHANY: { - draw_chany_to_chany_edge(RRNodeId(prev_node), RRNodeId(inode), - switch_type, g); - break; - } - case e_rr_type::OPIN: { - draw_pin_to_chan_edge(prev_node, inode, g); + switch (prev_type) { + case e_rr_type::CHANX: { + draw_chanx_to_chany_edge(prev_node, inode, + FROM_X_TO_Y, switch_type, g); + break; + } + case e_rr_type::CHANY: { + draw_chany_to_chany_edge(RRNodeId(prev_node), RRNodeId(inode), + switch_type, g); + break; + } + case e_rr_type::OPIN: { + draw_pin_to_chan_edge(prev_node, inode, g); - break; - } - default: { - VPR_ERROR(VPR_ERROR_OTHER, - "Unexpected connection from an rr_node of type %d to one of type %d.\n", - prev_type, rr_type); - } + break; + } + default: { + VPR_ERROR(VPR_ERROR_OTHER, + "Unexpected connection from an rr_node of type %d to one of type %d.\n", + prev_type, rr_type); } } - break; } default: { diff --git a/vpr/src/draw/draw_rr.cpp b/vpr/src/draw/draw_rr.cpp index 156147c17e..6548949a24 100644 --- a/vpr/src/draw/draw_rr.cpp +++ b/vpr/src/draw/draw_rr.cpp @@ -513,6 +513,26 @@ void draw_rr_edges(RRNodeId inode, ezgl::renderer* g) { } /* End of for each edge loop */ } +void draw_rr_intrapin(RRNodeId inode, const ezgl::color& color, ezgl::renderer* g) { + t_draw_state* draw_state = get_draw_state_vars(); + t_draw_coords* draw_coords = get_draw_coords_vars(); + + if (!draw_state->is_flat) { + return; + } + + auto blk_id_pin_id = get_rr_node_cluster_blk_id_pb_graph_pin(inode); + + ezgl::point2d p = draw_coords->get_absolute_pin_location(blk_id_pin_id.first, blk_id_pin_id.second); + + int transparency_factor = get_rr_node_transparency(inode); + + g->set_color(color, transparency_factor); + g->fill_rectangle( + {p.x - draw_coords->pin_size, p.y - draw_coords->pin_size}, + {p.x + draw_coords->pin_size, p.y + draw_coords->pin_size}); +} + /* 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. */ @@ -683,6 +703,30 @@ RRNodeId draw_check_rr_node_hit(float click_x, float click_y) { if (!draw_state->draw_layer_display[layer_num].visible) { continue; /* Don't check RR nodes on currently invisible layers*/ } + + // Skip Source and Sink Nodes + if (rr_graph.node_type(inode) == e_rr_type::SOURCE + || rr_graph.node_type(inode) == e_rr_type::SINK) { + continue; + } + + // Check for intra cluster nodes + if (!is_inter_cluster_node(rr_graph, inode)) { + + if (!draw_state->is_flat) { + continue; + } + + auto blk_id_pin_id = get_rr_node_cluster_blk_id_pb_graph_pin(inode); + ezgl::point2d p = draw_coords->get_absolute_pin_location(blk_id_pin_id.first, blk_id_pin_id.second); + + if (click_x >= p.x - draw_coords->pin_size && click_x <= p.x + draw_coords->pin_size && click_y >= p.y - draw_coords->pin_size && click_y <= p.y + draw_coords->pin_size) { + hit_node = inode; + return hit_node; + } + + continue; + } switch (rr_graph.node_type(inode)) { case e_rr_type::IPIN: case e_rr_type::OPIN: { diff --git a/vpr/src/draw/draw_rr.h b/vpr/src/draw/draw_rr.h index dd7a305ffc..97eea54e7a 100644 --- a/vpr/src/draw/draw_rr.h +++ b/vpr/src/draw/draw_rr.h @@ -27,6 +27,7 @@ void draw_rr_edges(RRNodeId from_node, ezgl::renderer* g); void draw_rr_chan(RRNodeId inode, const ezgl::color color, ezgl::renderer* g); +void draw_rr_intrapin(RRNodeId inode, const ezgl::color& color, ezgl::renderer* g); /* 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. */ diff --git a/vpr/src/draw/draw_rr_edges.cpp b/vpr/src/draw/draw_rr_edges.cpp index 85deffe765..d07024055d 100644 --- a/vpr/src/draw/draw_rr_edges.cpp +++ b/vpr/src/draw/draw_rr_edges.cpp @@ -279,6 +279,65 @@ void draw_chanx_to_chany_edge(RRNodeId chanx_node, RRNodeId chany_node, enum e_e } } +void draw_intrapin_to_intrapin(RRNodeId inode, RRNodeId prev_node, ezgl::renderer* g) { + t_draw_state* draw_state = get_draw_state_vars(); + t_draw_coords* draw_coords = get_draw_coords_vars(); + + if (!draw_state->is_flat) { + return; + } + + auto blk_id_pin_id1 = get_rr_node_cluster_blk_id_pb_graph_pin(inode); + auto blk_id_pin_id2 = get_rr_node_cluster_blk_id_pb_graph_pin(prev_node); + + ezgl::point2d p2 = draw_coords->get_absolute_pin_location(blk_id_pin_id1.first, blk_id_pin_id1.second); + ezgl::point2d p1 = draw_coords->get_absolute_pin_location(blk_id_pin_id2.first, blk_id_pin_id2.second); + + g->draw_line(p1, p2); + + float xend = p2.x + (p1.x - p2.x) / 10.; + float yend = p2.y + (p1.y - p2.y) / 10.; + draw_triangle_along_line(g, xend, yend, p1.x, p2.x, p1.y, p2.y); +} + +void draw_intrapin_to_pin(RRNodeId inode, RRNodeId prev_node, ezgl::renderer* g) { + t_draw_state* draw_state = get_draw_state_vars(); + t_draw_coords* draw_coords = get_draw_coords_vars(); + + if (!draw_state->is_flat) { + return; + } + const auto& rr_graph = g_vpr_ctx.device().rr_graph; + + bool swapped = false; + if (!is_inter_cluster_node(rr_graph, inode) && is_inter_cluster_node(rr_graph, prev_node)) { + //Swap the nodes so that the inter-cluster node is always the current node + std::swap(inode, prev_node); + swapped = true; + } + + auto blk_id_pin_id = get_rr_node_cluster_blk_id_pb_graph_pin(prev_node); + float x1, y1; + ezgl::point2d p2 = draw_coords->get_absolute_pin_location(blk_id_pin_id.first, blk_id_pin_id.second); + + for (const e_side& pin_side : TOTAL_2D_SIDES) { + if (!rr_graph.is_node_on_specific_side(RRNodeId(inode), pin_side)) { + continue; + } + draw_get_rr_pin_coords(inode, &x1, &y1, pin_side); + ezgl::point2d p1 = {x1, y1}; + + if (!swapped) { + std::swap(p1, p2); + } + + g->draw_line(p1, p2); + float xend = p2.x + (p1.x - p2.x) / 10.; + float yend = p2.y + (p1.y - p2.y) / 10.; + draw_triangle_along_line(g, xend, yend, p1.x, p2.x, p1.y, p2.y); + } +} + void draw_pin_to_pin(RRNodeId opin_node, RRNodeId ipin_node, ezgl::renderer* g) { /* This routine draws an edge from the opin rr node to the ipin rr node */ const auto& device_ctx = g_vpr_ctx.device(); diff --git a/vpr/src/draw/draw_rr_edges.h b/vpr/src/draw/draw_rr_edges.h index 3b51bd0ab6..72339bdf5e 100644 --- a/vpr/src/draw/draw_rr_edges.h +++ b/vpr/src/draw/draw_rr_edges.h @@ -20,6 +20,8 @@ void draw_chany_to_chany_edge(RRNodeId from_node, RRNodeId to_node, short switch_type, ezgl::renderer* g); void draw_chanx_to_chanx_edge(RRNodeId from_node, RRNodeId to_node, short switch_type, ezgl::renderer* g); void draw_chanx_to_chany_edge(RRNodeId chanx_node, RRNodeId chany_node, enum e_edge_dir edge_dir, short switch_type, ezgl::renderer* g); +void draw_intrapin_to_pin(RRNodeId inode, RRNodeId prev_node, ezgl::renderer* g); +void draw_intrapin_to_intrapin(RRNodeId inode, RRNodeId prev_node, ezgl::renderer* g); void draw_pin_to_pin(RRNodeId opin, RRNodeId ipin, ezgl::renderer* g); void draw_pin_to_sink(RRNodeId ipin_node, RRNodeId sink_node, ezgl::renderer* g); void draw_source_to_pin(RRNodeId source_node, RRNodeId opin_node, ezgl::renderer* g); diff --git a/vpr/src/draw/draw_searchbar.cpp b/vpr/src/draw/draw_searchbar.cpp index e80f450af3..e5a1053cb8 100644 --- a/vpr/src/draw/draw_searchbar.cpp +++ b/vpr/src/draw/draw_searchbar.cpp @@ -131,40 +131,59 @@ void draw_highlight_blocks_color(t_logical_block_type_ptr type, /* If an rr_node has been clicked on, it will be highlighted in MAGENTA. * If so, and toggle nets is selected, highlight the whole net in that colour. */ -void highlight_nets(char* message, RRNodeId hit_node, bool is_flat) { +void highlight_net(char* message, RRNodeId hit_node) { auto& cluster_ctx = g_vpr_ctx.clustering(); + auto& atom_ctx = g_vpr_ctx.atom(); auto& route_ctx = g_vpr_ctx.routing(); /* Don't crash if there's no routing */ if (route_ctx.route_trees.empty()) return; + if (route_ctx.is_flat) { + for (auto net_id : atom_ctx.netlist().nets()) { + check_node_highlight_net(message, net_id, hit_node); + } + + } else { + for (auto net_id : cluster_ctx.clb_nlist.nets()) { + check_node_highlight_net(message, net_id, hit_node); + } + } + + application.update_message(message); +} + +void check_node_highlight_net(char* message, ParentNetId parent_id, RRNodeId hit_node) { + auto& route_ctx = g_vpr_ctx.routing(); t_draw_state* draw_state = get_draw_state_vars(); - for (auto net_id : cluster_ctx.clb_nlist.nets()) { - ParentNetId parent_id = get_cluster_net_parent_id(g_vpr_ctx.atom().lookup(), net_id, is_flat); - if (!route_ctx.route_trees[parent_id]) - continue; + if (!route_ctx.route_trees[parent_id]) + return; - for (auto& rt_node : route_ctx.route_trees[parent_id].value().all_nodes()) { - RRNodeId inode = rt_node.inode; - if (draw_state->draw_rr_node[inode].color == ezgl::MAGENTA) { - draw_state->net_color[net_id] = draw_state->draw_rr_node[inode].color; - if (inode == hit_node) { - std::string orig_msg(message); - sprintf(message, "%s || Net: %zu (%s)", orig_msg.c_str(), - size_t(net_id), - cluster_ctx.clb_nlist.net_name(net_id).c_str()); + for (auto& rt_node : route_ctx.route_trees[parent_id].value().all_nodes()) { + RRNodeId inode = rt_node.inode; + if (draw_state->draw_rr_node[inode].color == ezgl::MAGENTA) { + draw_state->net_color[parent_id] = draw_state->draw_rr_node[inode].color; + if (inode == hit_node) { + std::string orig_msg(message); + std::string net_name; + if (!route_ctx.is_flat) { + net_name = g_vpr_ctx.clustering().clb_nlist.net_name(convert_to_cluster_net_id(parent_id)); + } else { + net_name = g_vpr_ctx.atom().netlist().net_name(convert_to_atom_net_id(parent_id)); } - } else if (draw_state->draw_rr_node[inode].color - == ezgl::WHITE) { - // If node is de-selected. - draw_state->net_color[net_id] = ezgl::BLACK; - break; + sprintf(message, "%s || Net: %zu (%s)", orig_msg.c_str(), + size_t(parent_id), + net_name.c_str()); } + } else if (draw_state->draw_rr_node[inode].color + == ezgl::WHITE) { + // If node is de-selected. + draw_state->net_color[parent_id] = ezgl::BLACK; + break; } } - application.update_message(message); } /* If an rr_node has been clicked on, it will be either highlighted in MAGENTA, diff --git a/vpr/src/draw/draw_searchbar.h b/vpr/src/draw/draw_searchbar.h index 7d195dde98..9603d19962 100644 --- a/vpr/src/draw/draw_searchbar.h +++ b/vpr/src/draw/draw_searchbar.h @@ -28,7 +28,10 @@ void draw_highlight_blocks_color(t_logical_block_type_ptr type, ClusterBlockId b /* If an rr_node has been clicked on, it will be highlighted in MAGENTA. * If so, and toggle nets is selected, highlight the whole net in that colour.*/ -void highlight_nets(char* message, RRNodeId hit_node, bool is_flat); +void highlight_net(char* message, RRNodeId hit_node); + +/* Checks if a node is part of a net, and highlights the net if it is. */ +void check_node_highlight_net(char* message, ParentNetId parent_id, RRNodeId hit_node); /* If an rr_node has been clicked on, it will be either highlighted in MAGENTA, * or de-highlighted in WHITE. If highlighted, and toggle_rr is selected, highlight diff --git a/vpr/src/draw/draw_toggle_functions.cpp b/vpr/src/draw/draw_toggle_functions.cpp index 4800ac14e2..f97c286dac 100644 --- a/vpr/src/draw/draw_toggle_functions.cpp +++ b/vpr/src/draw/draw_toggle_functions.cpp @@ -235,7 +235,7 @@ void toggle_blk_internal_cbk(GtkSpinButton* self, ezgl::application* app) { if (new_value < 0) draw_state->show_blk_internal = 0; else if (new_value >= draw_state->max_sub_blk_lvl) - draw_state->show_blk_internal = draw_state->max_sub_blk_lvl - 1; + draw_state->show_blk_internal = draw_state->max_sub_blk_lvl; else draw_state->show_blk_internal = new_value; app->refresh_drawing(); diff --git a/vpr/src/draw/draw_types.cpp b/vpr/src/draw/draw_types.cpp index 0394084364..fd7203aaad 100644 --- a/vpr/src/draw/draw_types.cpp +++ b/vpr/src/draw/draw_types.cpp @@ -151,6 +151,22 @@ ezgl::rectangle t_draw_coords::get_absolute_pb_bbox(const ClusterBlockId clb_ind return result; } +ezgl::point2d t_draw_coords::get_absolute_pin_location(const ClusterBlockId clb_index, const t_pb_graph_pin* pb_graph_pin) { + + t_pb_graph_node* pb_gnode = pb_graph_pin->parent_node; + ezgl::rectangle pb_bbox = this->get_absolute_pb_bbox(clb_index, pb_gnode); + int num_pins = pb_gnode->num_pins(); + + int num_pin = pb_graph_pin->pin_number; + for (int i = 0; i < pb_graph_pin->port->index; ++i) { + num_pin += pb_gnode->pb_type->ports[i].num_pins; + } + + float interval = pb_bbox.width() / (num_pins + 1); + + return ezgl::point2d(interval * (num_pin + 1), -0.01 * this->tile_width) + pb_bbox.top_left(); +} + ezgl::rectangle t_draw_coords::get_absolute_clb_bbox(const ClusterBlockId clb_index, const t_logical_block_type_ptr block_type) { t_draw_state* draw_state = get_draw_state_vars(); const auto& block_locs = draw_state->get_graphics_blk_loc_registry_ref().block_locs(); diff --git a/vpr/src/draw/draw_types.h b/vpr/src/draw/draw_types.h index 56d6d96985..f8d9a2d278 100644 --- a/vpr/src/draw/draw_types.h +++ b/vpr/src/draw/draw_types.h @@ -432,6 +432,11 @@ struct t_draw_coords { */ ezgl::rectangle get_absolute_pb_bbox(const ClusterBlockId clb_index, const t_pb_graph_node* pb_gnode); + /** + * @brief returns a 2D point for the absolute location of the given pb_graph_pin + */ + ezgl::point2d get_absolute_pin_location(const ClusterBlockId clb_index, const t_pb_graph_pin* pb_graph_pin); + ///@brief Returns bounding box for CLB of given idx/type ezgl::rectangle get_absolute_clb_bbox(const ClusterBlockId clb_index, const t_logical_block_type_ptr type); diff --git a/vpr/src/draw/intra_logic_block.cpp b/vpr/src/draw/intra_logic_block.cpp index d30bded969..69ec9d6ac0 100644 --- a/vpr/src/draw/intra_logic_block.cpp +++ b/vpr/src/draw/intra_logic_block.cpp @@ -38,7 +38,7 @@ static void draw_internal_load_coords(int type_descrip_index, t_pb_graph_node* pb_graph_node, float parent_width, float parent_height); static int draw_internal_find_max_lvl(const t_pb_type& pb_type); -static void draw_internal_calc_coords(int type_descrip_index, t_pb_graph_node* pb_graph_node, int num_pb_types, int type_index, int num_pb, int pb_index, float parent_width, float parent_height, float* blk_width, float* blk_height); +static void draw_internal_calc_coords(int type_descrip_index, t_pb_graph_node* pb_graph_node, int num_block, int num_columns, int num_rows, float parent_width, float parent_height, float* blk_width, float* blk_height); std::vector collect_pb_atoms(const t_pb* pb); void collect_pb_atoms_recurr(const t_pb* pb, std::vector& atoms); t_pb* highlight_sub_block_helper(const ClusterBlockId clb_index, t_pb* pb, const ezgl::point2d& local_pt, int max_depth); @@ -237,11 +237,30 @@ static void draw_internal_load_coords(int type_descrip_index, t_pb_graph_node* p /* Find the number of instances for each child pb_type. */ int num_pb = mode.pb_type_children[j].num_pb; + int num_blocks = num_pb * num_children; + + // determine an optimal number of columns + int num_columns = 1; + for (int k = 1; k * k <= num_blocks; ++k) { + if (num_blocks % k == 0) { + num_columns = k; + } + } + int num_rows = num_blocks / num_columns; + + const int MAX_WIDTH_HEIGHT_RATIO = 2; + if (parent_width > parent_height * MAX_WIDTH_HEIGHT_RATIO) { + std::swap(num_columns, num_rows); + } + for (int k = 0; k < num_pb; ++k) { + + int num_block = j * num_pb + k; + /* Compute bound box for block. Don't call if pb_type is root-level pb. */ draw_internal_calc_coords(type_descrip_index, &pb_graph_node->child_pb_graph_nodes[i][j][k], - num_children, j, num_pb, k, + num_block, num_columns, num_rows, parent_width, parent_height, &blk_width, &blk_height); @@ -258,56 +277,53 @@ static void draw_internal_load_coords(int type_descrip_index, t_pb_graph_node* p * are relative to the left and bottom corner of the parent block. */ static void -draw_internal_calc_coords(int type_descrip_index, t_pb_graph_node* pb_graph_node, int num_pb_types, int type_index, int num_pb, int pb_index, float parent_width, float parent_height, float* blk_width, float* blk_height) { - t_draw_state* draw_state = get_draw_state_vars(); - const auto& device_ctx = g_vpr_ctx.device(); - const auto& grid_blocks = draw_state->get_graphics_blk_loc_registry_ref().grid_blocks(); +draw_internal_calc_coords(int type_descrip_index, t_pb_graph_node* pb_graph_node, int num_block, int num_columns, int num_rows, float parent_width, float parent_height, float* blk_width, float* blk_height) { // get the bbox for this pb type ezgl::rectangle& pb_bbox = get_draw_coords_vars()->blk_info.at(type_descrip_index).get_pb_bbox_ref(*pb_graph_node); - const float FRACTION_PARENT_PADDING_X = 0.01; + float tile_width = get_draw_coords_vars()->get_tile_width(); - const float NORMAL_FRACTION_PARENT_HEIGHT = 0.90; - float capacity_divisor = 1; - const float FRACTION_PARENT_PADDING_BOTTOM = 0.01; + const float FRACTION_PARENT_PADDING = 0.005; + const float FRACTION_CHILD_MARGIN = 0.003; + const float FRACTION_TEXT_PADDING = 0.01; + const int MIN_WIDTH_HEIGHT_RATIO = 2; - const float FRACTION_CHILD_MARGIN_X = 0.025; - const float FRACTION_CHILD_MARGIN_Y = 0.04; + float abs_parent_padding = tile_width * FRACTION_PARENT_PADDING; + float abs_text_padding = tile_width * FRACTION_TEXT_PADDING; + float abs_child_margin = tile_width * FRACTION_CHILD_MARGIN; - int capacity = device_ctx.physical_tile_types[type_descrip_index].capacity; - // TODO: this is a hack - should be fixed for the layer_num - const auto& type = device_ctx.grid.get_physical_type({1, 0, 0}); - if (capacity > 1 && device_ctx.grid.width() > 0 && device_ctx.grid.height() > 0 && grid_blocks.get_usage({1, 0, 0}) != 0 - && type_descrip_index == type->index) { - // that should test for io blocks, and setting capacity_divisor > 1 - // will squish every thing down - capacity_divisor = capacity - 1; + // add safety check to ensure that the dimensions will never be below zero + if (parent_width <= 2 * abs_parent_padding || parent_height <= 2 * abs_parent_padding - abs_text_padding) { + abs_parent_padding = 0; + abs_text_padding = 0; } /* Draw all child-level blocks in just most of the space inside their parent block. */ - float parent_drawing_width = parent_width * (1 - FRACTION_PARENT_PADDING_X * 2); - float parent_drawing_height = parent_height * (NORMAL_FRACTION_PARENT_HEIGHT / capacity_divisor); + float parent_drawing_width = parent_width - 2 * abs_parent_padding; + float parent_drawing_height = parent_height - 2 * abs_parent_padding - abs_text_padding; - /* The left and bottom corner (inside the parent block) of the space to draw - * child blocks. - */ - float sub_tile_x = parent_width * FRACTION_PARENT_PADDING_X; - float sub_tile_y = parent_height * FRACTION_PARENT_PADDING_BOTTOM; + if (parent_drawing_height > MIN_WIDTH_HEIGHT_RATIO * parent_drawing_width) { + parent_drawing_height /= 2; + } + + int x_index = num_block % num_columns; + int y_index = num_block / num_columns; - /* Divide parent_drawing_width by the number of child types. */ - float child_width = parent_drawing_width / num_pb_types; - /* Divide parent_drawing_height by the number of instances of the pb_type. */ - float child_height = parent_drawing_height / num_pb; + float child_width = parent_drawing_width / num_columns; + float child_height = parent_drawing_height / num_rows; + + // add safety check to ensure that the dimensions will never be below zero + if (child_width <= abs_child_margin * 2 || child_height <= abs_child_margin * 2) { + abs_child_margin = 0; + } /* The starting point to draw the physical block. */ - double left = child_width * type_index + sub_tile_x + FRACTION_CHILD_MARGIN_X * child_width; - double bot = child_height * pb_index + sub_tile_y + FRACTION_CHILD_MARGIN_Y * child_height; + double left = child_width * x_index + abs_parent_padding + abs_child_margin; + double bot = child_height * y_index + abs_parent_padding + abs_child_margin; - /* Leave some space between different pb_types. */ - child_width *= 1 - FRACTION_CHILD_MARGIN_X * 2; - /* Leave some space between different instances of the same type. */ - child_height *= 1 - FRACTION_CHILD_MARGIN_Y * 2; + child_width -= abs_child_margin * 2; + child_height -= abs_child_margin * 2; /* Endpoint for drawing the pb_type */ double right = left + child_width; @@ -400,7 +416,7 @@ static void draw_internal_pb(const ClusterBlockId clb_index, t_pb* pb, const ezg if (draw_state->draw_block_text) { g->draw_text( ezgl::point2d(abs_bbox.center_x(), - abs_bbox.top() - (abs_bbox.height()) / 15.0), + abs_bbox.top() - draw_coords->get_tile_height() * 0.01), pb_type->name, abs_bbox.width(), abs_bbox.height()); diff --git a/vpr/src/draw/search_bar.cpp b/vpr/src/draw/search_bar.cpp index 17de84c587..74414b6048 100644 --- a/vpr/src/draw/search_bar.cpp +++ b/vpr/src/draw/search_bar.cpp @@ -247,7 +247,7 @@ bool highlight_rr_nodes(RRNodeId hit_node) { } if (draw_state->show_nets) - highlight_nets(message, hit_node, draw_state->is_flat); + highlight_net(message, hit_node); else application.update_message(message); diff --git a/vpr/src/draw/ui_setup.cpp b/vpr/src/draw/ui_setup.cpp index 018f951d37..12e31772f9 100644 --- a/vpr/src/draw/ui_setup.cpp +++ b/vpr/src/draw/ui_setup.cpp @@ -82,7 +82,7 @@ void block_button_setup(ezgl::application* app) { GtkSpinButton* blk_internals_button = GTK_SPIN_BUTTON(app->get_object("ToggleBlkInternals")); g_signal_connect(blk_internals_button, "value-changed", G_CALLBACK(toggle_blk_internal_cbk), app); gtk_spin_button_set_increments(blk_internals_button, 1, 1); - gtk_spin_button_set_range(blk_internals_button, 0., (double)(draw_state->max_sub_blk_lvl - 1)); + gtk_spin_button_set_range(blk_internals_button, 0., (double)(draw_state->max_sub_blk_lvl)); //Toggle Block Pin Util GtkComboBoxText* blk_pin_util = GTK_COMBO_BOX_TEXT(app->get_object("ToggleBlkPinUtil")); diff --git a/vpr/src/util/vpr_utils.cpp b/vpr/src/util/vpr_utils.cpp index a45818da48..b8d012a64b 100644 --- a/vpr/src/util/vpr_utils.cpp +++ b/vpr/src/util/vpr_utils.cpp @@ -858,13 +858,13 @@ t_pb_graph_pin* get_pb_graph_node_pin_from_model_port_pin(const t_model_ports* m } //Retrieves the atom pin associated with a specific CLB and pb_graph_pin +// Warning: Not all pb_graph_pins are associated with an atom pin! AtomPinId find_atom_pin(ClusterBlockId blk_id, const t_pb_graph_pin* pb_gpin) { auto& cluster_ctx = g_vpr_ctx.clustering(); auto& atom_ctx = g_vpr_ctx.atom(); int pb_route_id = pb_gpin->pin_count_in_cluster; AtomNetId atom_net = cluster_ctx.clb_nlist.block_pb(blk_id)->pb_route[pb_route_id].atom_net_id; - VTR_ASSERT(atom_net); AtomPinId atom_pin; @@ -1755,6 +1755,42 @@ RRNodeId get_atom_pin_rr_node_id(AtomPinId atom_pin_id) { return rr_node_id; } +std::pair get_rr_node_cluster_blk_id_pb_graph_pin(RRNodeId rr_node_id) { + auto& device_ctx = g_vpr_ctx.device(); + auto& place_ctx = g_vpr_ctx.placement(); + + VTR_ASSERT(!is_inter_cluster_node(g_vpr_ctx.device().rr_graph, rr_node_id)); + + int pin_physical_num = device_ctx.rr_graph.node_ptc_num(rr_node_id); + int x = device_ctx.rr_graph.node_xlow(rr_node_id); + int y = device_ctx.rr_graph.node_ylow(rr_node_id); + int layer = device_ctx.rr_graph.node_layer(rr_node_id); + + t_physical_tile_type_ptr physical_tile = device_ctx.grid.get_physical_type({x, y, layer}); + + auto [sub_tile, sub_tile_num] = get_sub_tile_from_pin_physical_num(physical_tile, pin_physical_num); + VTR_ASSERT(sub_tile && sub_tile_num >= 0 && sub_tile_num < physical_tile->capacity); + + ClusterBlockId blk_id = place_ctx.grid_blocks().block_at_location({x, y, sub_tile_num, layer}); + VTR_ASSERT(blk_id != ClusterBlockId::INVALID()); + + t_pb_graph_pin* pb_graph_pin = physical_tile->pin_num_to_pb_pin.at(pin_physical_num); + + VTR_ASSERT(pb_graph_pin); + + return {blk_id, pb_graph_pin}; +} + +AtomPinId get_rr_node_atom_pin_id(RRNodeId rr_node_id) { + ClusterBlockId blk_id; + t_pb_graph_pin* pb_graph_pin; + std::tie(blk_id, pb_graph_pin) = get_rr_node_cluster_blk_id_pb_graph_pin(rr_node_id); + + AtomPinId atom_pin_id = find_atom_pin(blk_id, pb_graph_pin); + + return atom_pin_id; +} + bool node_in_same_physical_tile(RRNodeId node_first, RRNodeId node_second) { const auto& device_ctx = g_vpr_ctx.device(); const auto& rr_graph = device_ctx.rr_graph; diff --git a/vpr/src/util/vpr_utils.h b/vpr/src/util/vpr_utils.h index 7fe8e28175..a294e7d286 100644 --- a/vpr/src/util/vpr_utils.h +++ b/vpr/src/util/vpr_utils.h @@ -256,6 +256,22 @@ RRNodeId get_pin_rr_node_id(const RRSpatialLookup& rr_spatial_lookup, */ RRNodeId get_atom_pin_rr_node_id(AtomPinId atom_pin_id); +/** + * @brief Returns the cluster block ID and pb_graph_pin for the given RR node ID. + * **Warning**: This function should be called only if flat-router is enabled, + * since, otherwise, the routing resources inside clusters are not added to the RR graph. + * @param rr_node_id The RR node ID. + */ +std::pair get_rr_node_cluster_blk_id_pb_graph_pin(RRNodeId rr_node_id); + +/** + * @brief Returns the atom pin ID for the given RR node ID. + * **Warning**: This function should be called only if flat-router is enabled, + * since, otherwise, the routing resources inside clusters are not added to the RR graph. Also, not all RRNodes have an AtomPinId associated with them. + * @param rr_node_id The RR node ID. + */ +AtomPinId get_rr_node_atom_pin_id(RRNodeId rr_node_id); + RRNodeId get_class_rr_node_id(const RRSpatialLookup& rr_spatial_lookup, t_physical_tile_type_ptr physical_tile, const int layer,