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

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this drawing rr nodes (not just pins)? Suggest changing the comment.

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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Draw cluster-level 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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 (!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) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To match the structure of the rest of the code and shorten this routine I think this switch statement should be moved into a helper router (maybe called draw_inter_cluster_rr_edge )

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)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd add a comment here: check for inter-cluster nodes

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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a comment describing what the function does. I think it would be best to make it a Doxygen comment so we can choose to build Doxygen comments for more drawing code in the future.

General principle: comment what a function does in the .h file, or (if it is a static function) in its declaration in the .cpp file. Use Doxygen formatting in either case.

/* 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
Loading