Skip to content

Conversation

@amin1377
Copy link
Contributor

This PR depends on PR #3342. Please wait until that PR is merged.

In this PR, node_tilable_track_nums_ is moved into the RR graph storage instead of residing in the RR graph builder, since this data structure (when using a tileable RR graph) needs to remain valid for the entire lifetime of the RR graph.

Additionally, a method is added to facilitate removing nodes from the RR graph.

@github-actions github-actions bot added VPR VPR FPGA Placement & Routing Tool docs Documentation lang-cpp C/C++ code labels Nov 17, 2025
@AmirhosseinPoolad
Copy link
Contributor

What's the use case of removing nodes?

@amin1377
Copy link
Contributor Author

What's the use case of removing nodes?

For the custom RR graph, in the other PR there are channel nodes, particularly around the perimeter of the device, that don’t have any fan-in. We need to remove these nodes after the graph is created. I considered not adding them in the first place, but that’s difficult to determine before the edges are added.

As we discussed earlier, I’m trying to break the custom RR graph PR into multiple smaller PRs to make the review process easier.

@amin1377 amin1377 changed the title [WIP] Move node_tilable_track_nums_ to rr_graph_storage and add remove_node Move node_tilable_track_nums_ to rr_graph_storage and add remove_node Nov 20, 2025
@github-actions github-actions bot added the libarchfpga Library for handling FPGA Architecture descriptions label Nov 20, 2025
Copy link
Contributor

@AmirhosseinPoolad AmirhosseinPoolad left a comment

Choose a reason for hiding this comment

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

Thanks for the PR Amin. Had some comments.

Comment on lines 267 to +270
if (e_rr_type::CHANX == node_type || e_rr_type::CHANY == node_type) {
ptc = (node_type == e_rr_type::CHANX) ? node_tilable_track_nums_[node][x - node_storage_.node_xlow(node)] :
node_tilable_track_nums_[node][y - node_storage_.node_ylow(node)];
const std::vector<short>& track_nums = node_storage_.node_tilable_track_nums(node);
ptc = (node_type == e_rr_type::CHANX) ? track_nums[x - node_storage_.node_xlow(node)] :
track_nums[y - node_storage_.node_ylow(node)];
Copy link
Contributor

Choose a reason for hiding this comment

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

I really don't like the way the ternary operator is used here. We have an assertion at the beginning of this function is CHANX or CHANY, so I think we could do something like:

ptc_num = undefined
if (chanx) ptc_num = something
else if (chany) ptc_num = something_else
add_node


void t_rr_graph_storage::init_fan_in() {
//Reset all fan-ins to zero
edges_read_ = true;
Copy link
Contributor

Choose a reason for hiding this comment

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

I agree that this method shouldn't set this flag, but I think I need a couple more eyes to look at this.

Comment on lines 189 to 191
for(const auto& edge_id : edge_dest_node_.keys()) {
node_fan_in_[edge_dest_node_[edge_id]] += 1;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you change this code to use .pairs() instead? Something like:

for (const auto& [edge_id, edge_destination_node] : edge_dest_node_.pairs())

Looks much nicer imo.

Comment on lines +708 to +726
void set_node_ptc_nums(RRNodeId node, const std::string& ptc_str);
void add_node_tilable_track_num(RRNodeId node, size_t node_offset, short track_id);

void emplace_back_node_tilable_track_num();

bool node_contain_multiple_ptc(RRNodeId node) const {
if (node_tilable_track_nums_.empty()) {
return false;
} else {
return node_tilable_track_nums_[node].size() > 1;
}
}

std::string node_ptc_nums_to_string(RRNodeId node) const;

const std::vector<short>& node_tilable_track_nums(RRNodeId node) const {
return node_tilable_track_nums_[node];
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Doxygen for all of these

Comment on lines +86 to +89
if (graph_type == e_graph_type::UNIDIR_TILEABLE) {
rr_graph_builder->set_tileable(true);
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Does this fix a bug?

Comment on lines +756 to +757
for (size_t edge_index = 0; edge_index < edge_nodes.size(); ++edge_index) {
RREdgeId edge_id = RREdgeId(edge_index);
Copy link
Contributor

Choose a reason for hiding this comment

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

use all_edges() instead.

}

std::vector<RREdgeId> removed_edges;
auto adjust_edges = [&](vtr::vector<RREdgeId, RRNodeId>& edge_nodes) {
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 explaining what this lambda does.

// Node exists in sorted_nodes, mark edge for removal
removed_edges.push_back(edge_id);
} else {
size_t node_offset = std::distance(sorted_nodes.begin(), node_it);
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure what's going on here. A comment would be nice.

Comment on lines +740 to +750
/**
* @brief Removes a given list of RRNodes from the RR Graph
* This method should be called before partition_edges has been called.
* If init_fan_in has been called, you need to call it again after removing the nodes.
* @note This a very expensive method, so should be called only when necessary. It is better
* to not add nodes in the first place, instead of relying on this method to remove nodes.
*
* @param nodes list of RRNodes to be removed
*/
void remove_nodes(const std::vector<RRNodeId>& nodes);

Copy link
Contributor

Choose a reason for hiding this comment

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

From what I can understand, this function is O(|V| + |E|logk) where k is the number of nodes you want to remove. You should add that to the doxygen.

Comment on lines +774 to +775
adjust_edges(edge_src_node_);
adjust_edges(edge_dest_node_);
Copy link
Contributor

Choose a reason for hiding this comment

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

What about edge_switch_ and edge_remapped_?

Copy link
Contributor

@AmirhosseinPoolad AmirhosseinPoolad left a comment

Choose a reason for hiding this comment

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

Misclicked, didn't mean to approve. Sorry!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Documentation lang-cpp C/C++ code libarchfpga Library for handling FPGA Architecture descriptions VPR VPR FPGA Placement & Routing Tool

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants