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 all 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
240 changes: 133 additions & 107 deletions vpr/src/draw/draw_basic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ void draw_congestion(ezgl::renderer* g) {

case e_rr_type::IPIN: //fallthrough
case e_rr_type::OPIN:
draw_rr_pin(inode, color, g);
draw_cluster_pin(inode, color, g);
break;
default:
break;
Expand Down 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,138 +612,168 @@ 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 RR Nodes
for (size_t i = 1; i < rr_nodes_to_draw.size(); ++i) {
RRNodeId inode = rr_nodes_to_draw[i];
e_rr_type 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;
}

if (chany_track.empty()) {
chany_track = vtr::OffsetMatrix<int>({{{0, width - 1}, {1, height - 1}}});
// Skip drawing sources and sinks
if (rr_type == e_rr_type::SINK || rr_type == e_rr_type::SOURCE) {
continue;
}

for (int i = 1; i < width - 1; i++)
for (int j = 0; j < height - 1; j++)
chanx_track[i][j] = (-1);
// Draw intra-cluster nodes
if (!is_inode_inter_cluster) {
draw_rr_intra_cluster_pin(inode, color, g);
continue;
}

// Draw cluster-level IO Pins
if (rr_type == e_rr_type::OPIN || rr_type == e_rr_type::IPIN) {
draw_cluster_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 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 prev_node_inter_cluster = is_inter_cluster_node(rr_graph, prev_node);
int prev_node_layer = rr_graph.node_layer(prev_node);

if (!is_inter_cluster_node(rr_graph, prev_node) || !is_inter_cluster_node(rr_graph, inode)) {
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;

// 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 edges to or from 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 (!inode_inter_cluster && !prev_node_inter_cluster) {
draw_intra_cluster_edge(inode, prev_node, g);
continue;
}

ezgl::color color = draw_state->draw_rr_node[inode].color;

switch (rr_type) {
case e_rr_type::OPIN: {
draw_rr_pin(inode, color, g);
break;
// Default side for pin in case none can be found
e_side pin_side = e_side::TOP;
if (!prev_node_inter_cluster && inode_inter_cluster) {
// draw intra-cluster pin to inter-cluster pin
// node i + 1 is the channel node
if (i + 1 < rr_nodes_to_draw.size()) {
pin_side = get_pin_side(inode, rr_nodes_to_draw[i + 1]);
}
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);
}
}
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);
}
}
}
draw_intra_cluster_pin_to_pin(prev_node, inode, FROM_INTRA_CLUSTER_TO_INTER_CLUSTER, pin_side, g);
continue;
}

break;
if (prev_node_inter_cluster && !inode_inter_cluster) {
// draw inter-cluster pin to intra-cluster pin
// node i - 2 is the channel node
if (i >= 2) {
pin_side = get_pin_side(prev_node, rr_nodes_to_draw[i - 2]);
}
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);
draw_intra_cluster_pin_to_pin(inode, prev_node, FROM_INTER_CLUSTER_TO_INTRA_CLUSTER, pin_side, g);
continue;
}

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);
draw_inter_cluster_rr_edge(inode, prev_node, rr_type, prev_type, 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);
}
}
}
void draw_inter_cluster_rr_edge(RRNodeId inode, RRNodeId prev_node, e_rr_type rr_type, e_rr_type prev_type, ezgl::renderer* g) {
const RRGraphView& rr_graph = g_vpr_ctx.device().rr_graph;
t_edge_size iedge = find_edge(prev_node, inode);
short switch_type = rr_graph.edge_switch(RRNodeId(prev_node), iedge);

break;
switch (rr_type) {
case e_rr_type::IPIN: {
if (prev_type == e_rr_type::OPIN) {
draw_pin_to_pin(prev_node, inode, g);
} else {
draw_pin_to_chan_edge(inode, prev_node, g);
}
default: {
break;
break;
}
case e_rr_type::CHANX: {
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: {
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: {
break;
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions vpr/src/draw/draw_basic.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ void draw_routed_net(ParentNetId net, ezgl::renderer* g);
void draw_partial_route(const std::vector<RRNodeId>& rr_nodes_to_draw,
ezgl::renderer* g);

/** @brief Draws an edge between two rr_nodes, which are both intra-cluster nodes.
* @param inode The current rr_node id
* @param prev_node The previous rr_node id
* @param g The ezgl renderer
*/
void draw_inter_cluster_rr_edge(RRNodeId inode, RRNodeId prev_node, e_rr_type rr_type, e_rr_type prev_type, ezgl::renderer* g);

/**
* @brief Returns the layer number of a timing path node
* @param node
Expand Down
Loading