Skip to content

Flat Routing Visualization #3159

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
Jul 8, 2025
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
1d796a5
created helper function and basic line drawing code
SamuelHo10 Jun 12, 2025
718e85a
updated internal block drawing location
SamuelHo10 Jun 16, 2025
885151a
updated intra logic block drawing
SamuelHo10 Jun 17, 2025
6c43c20
adjusted text position
SamuelHo10 Jun 17, 2025
97f1203
added basic intra cluster routing visualization
SamuelHo10 Jun 18, 2025
b49ac73
Merge remote-tracking branch 'origin' into visualize_flat_routing
SamuelHo10 Jun 19, 2025
c6f7d0d
implemented intra-cluster routing
SamuelHo10 Jun 20, 2025
9a1a3c4
fixed function which calculates max depth
SamuelHo10 Jun 20, 2025
1aa214c
reworked pin and edge drawing code
SamuelHo10 Jun 20, 2025
8577aee
made the intracluster pins clickable
SamuelHo10 Jun 20, 2025
18c377f
fixed pin location assignment bug
SamuelHo10 Jun 21, 2025
571e50d
added arrows
SamuelHo10 Jun 21, 2025
e51cf20
Merge remote-tracking branch 'origin' into visualize_flat_routing
SamuelHo10 Jun 22, 2025
0be7746
format
SamuelHo10 Jun 22, 2025
9970b2e
swapped arrow directions
SamuelHo10 Jun 24, 2025
a958d7e
improved comments and code structure
SamuelHo10 Jun 27, 2025
11d01c0
renamed certain variables for clarity
SamuelHo10 Jun 27, 2025
4d5a522
changed pb name display
SamuelHo10 Jun 27, 2025
ea61183
updated comments and fixed block drawing issue
SamuelHo10 Jul 2, 2025
850a0e6
fixed incorrect pin side issue
SamuelHo10 Jul 3, 2025
4f34f40
coding style changes
SamuelHo10 Jul 3, 2025
5df4c55
build error fix
SamuelHo10 Jul 3, 2025
ec3a442
Merge remote-tracking branch 'origin/master' into visualize_flat_routing
SamuelHo10 Jul 3, 2025
fdc0b5b
Merge remote-tracking branch 'origin/master' into visualize_flat_routing
SamuelHo10 Jul 7, 2025
60ecf8b
Merge remote-tracking branch 'origin/master' into visualize_flat_routing
SamuelHo10 Jul 7, 2025
06bd0a2
updated pb text display
SamuelHo10 Jul 7, 2025
b9f09db
dont display mode if its the same as type name
SamuelHo10 Jul 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion vpr/src/draw/draw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ int get_track_num(int inode, const vtr::OffsetMatrix<int>& 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) {
Expand Down
2 changes: 1 addition & 1 deletion vpr/src/draw/draw.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ ezgl::color to_ezgl_color(vtr::Color<float> 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<RRNodeId> trace_routed_connection_rr_nodes(
ClusterNetId net_id,
int driver_pin,
Expand Down
194 changes: 98 additions & 96 deletions vpr/src/draw/draw_basic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -569,24 +569,20 @@ 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;

std::vector<RRNodeId> rr_nodes_to_draw;
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. */
Expand Down Expand Up @@ -616,133 +612,139 @@ void draw_partial_route(const std::vector<RRNodeId>& rr_nodes_to_draw, ezgl::ren
auto& device_ctx = g_vpr_ctx.device();
const auto& rr_graph = device_ctx.rr_graph;

static vtr::OffsetMatrix<int> chanx_track; /* [1..device_ctx.grid.width() - 2][0..device_ctx.grid.height() - 2] */
static vtr::OffsetMatrix<int> 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<int>({{{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<int>({{{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: {
Expand Down
44 changes: 44 additions & 0 deletions vpr/src/draw/draw_rr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down Expand Up @@ -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: {
Expand Down
1 change: 1 addition & 0 deletions vpr/src/draw/draw_rr.h
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down
Loading