Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
615bd5a
[lib][rr_graph] initial impl for remove node
amin1377 Nov 17, 2025
511f89d
[libs][rr_graph] uniquify remove edges
amin1377 Nov 17, 2025
112a6c0
Merge branch 'rr_graph_interposer_cut' of https://github.com/verilog-…
amin1377 Nov 17, 2025
5bbf3d7
[lib][rr_graph] add comments + shrink rr graph node data structures
amin1377 Nov 17, 2025
dfc2a33
fix a typo
amin1377 Nov 17, 2025
ec0a8e5
[lib][rr_graph] remove node_tilable_track_nums_ from rr graph builder
amin1377 Nov 17, 2025
7817922
[lib][rr_graph] add node_tilable_track_nums_ to rr graph storage
amin1377 Nov 17, 2025
54ff743
[lib][rr_grpah] remove node_tileable_track_nums_ from rr_graph_view
amin1377 Nov 17, 2025
3da38b0
[lib][librrgraph] set tileable to true when reading rr graph from a f…
amin1377 Nov 17, 2025
dda1dd5
[libs][rrgraph] remove redundant function call
amin1377 Nov 17, 2025
de52b91
[vpr] fix instances of rr graph view
amin1377 Nov 17, 2025
4830963
[lib][rr_graph] add remove_node header
amin1377 Nov 17, 2025
3b9f552
[lib][rr_graph] erase node_tilable_track_nums_ when removing a node
amin1377 Nov 17, 2025
5f49e17
Merge branch 'rr_graph_interposer_cut' of https://github.com/verilog-…
amin1377 Nov 17, 2025
99e40a2
Merge branch 'master' of https://github.com/verilog-to-routing/vtr-ve…
amin1377 Nov 20, 2025
ec9b088
Merge branch 'rr_graph_interposer_cut' of https://github.com/verilog-…
amin1377 Nov 20, 2025
e5a0f13
[lib][rr_graph][storage] fix bugs with remove_nodes
amin1377 Nov 20, 2025
513115d
Merge branch 'master' of https://github.com/verilog-to-routing/vtr-ve…
amin1377 Nov 20, 2025
10a876a
Merge branch 'master' of https://github.com/verilog-to-routing/vtr-ve…
amin1377 Nov 21, 2025
52637f2
Merge branch 'master' of https://github.com/verilog-to-routing/vtr-ve…
amin1377 Nov 21, 2025
684c864
[ci] update flat router results based on extracted results from ci
amin1377 Nov 21, 2025
4a05ac1
Merge branch 'master' of https://github.com/verilog-to-routing/vtr-ve…
amin1377 Nov 24, 2025
cf49863
[lib][rr_graph] apply comments for rr_graph_storage
amin1377 Nov 24, 2025
7129eda
[lib][rr_graph] pass vector of ptc nums to set_node_ptc_nums and add …
amin1377 Nov 24, 2025
955502d
[lib][rr_graph] fix node_offset check in add_node_tilable_track_num
amin1377 Nov 24, 2025
3c7b677
[lib][rr_graph] add node_ptc_number_to_string
amin1377 Nov 24, 2025
79694d3
[lib][rr_graph] remove ptc_to_string from rr_graph_builder
amin1377 Nov 24, 2025
6dfc2c3
[lib][rr_graph] add comments
amin1377 Nov 24, 2025
838d5f9
[lib][rr_graph] fix iterator idx
amin1377 Nov 24, 2025
20fde60
fix a typo
amin1377 Nov 24, 2025
d5a5555
[ci] update flat router golden result
amin1377 Nov 24, 2025
167a46c
[lib][rr_graph] remove unlock_storage
amin1377 Nov 24, 2025
5c2a525
Merge branch 'master' of https://github.com/verilog-to-routing/vtr-ve…
amin1377 Nov 28, 2025
851a2cd
[lib][rr_graph] pass required variables to lambda function
amin1377 Nov 28, 2025
6555071
Merge branch 'master' of https://github.com/verilog-to-routing/vtr-ve…
amin1377 Nov 28, 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
67 changes: 12 additions & 55 deletions libs/librrgraph/src/base/rr_graph_builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,6 @@ vtr::vector<RRNodeId, std::vector<RREdgeId>>& RRGraphBuilder::node_in_edge_stora
return node_in_edges_;
}

vtr::vector<RRNodeId, std::vector<short>>& RRGraphBuilder::node_ptc_storage() {
return node_tilable_track_nums_;
}

void RRGraphBuilder::add_node_to_all_locs(RRNodeId node) {
e_rr_type node_type = node_storage_.node_type(node);
short node_ptc_num = node_storage_.node_ptc_num(node);
Expand Down Expand Up @@ -76,7 +72,6 @@ RRNodeId RRGraphBuilder::create_node(int layer, int x, int y, e_rr_type type, in
node_side = side;
}
node_storage_.emplace_back();
node_tilable_track_nums_.emplace_back();
RRNodeId new_node = RRNodeId(node_storage_.size() - 1);
node_storage_.set_node_layer(new_node, layer, layer);
node_storage_.set_node_type(new_node, type);
Expand All @@ -102,7 +97,6 @@ void RRGraphBuilder::clear() {
node_lookup_.clear();
node_storage_.clear();
node_in_edges_.clear();
node_tilable_track_nums_.clear();
rr_node_metadata_.clear();
rr_edge_metadata_.clear();
rr_segments_.clear();
Expand Down Expand Up @@ -231,59 +225,17 @@ std::vector<RREdgeId> RRGraphBuilder::node_in_edges(RRNodeId node) const {
return node_in_edges_[node];
}

void RRGraphBuilder::set_node_ptc_nums(RRNodeId node, const std::string& ptc_str) {
VTR_ASSERT(size_t(node) < node_storage_.size());
std::vector<std::string> ptc_tokens = vtr::StringToken(ptc_str).split(",");
VTR_ASSERT(ptc_tokens.size() >= 1);
set_node_ptc_num(node, std::stoi(ptc_tokens[0]));
if (ptc_tokens.size() > 1) {
VTR_ASSERT(size_t(node) < node_tilable_track_nums_.size());
node_tilable_track_nums_[node].resize(ptc_tokens.size());
for (size_t iptc = 0; iptc < ptc_tokens.size(); iptc++) {
node_tilable_track_nums_[node][iptc] = std::stoi(ptc_tokens[iptc]);
}
}
}

std::string RRGraphBuilder::node_ptc_nums_to_string(RRNodeId node) const {
if (node_tilable_track_nums_.empty()) {
return std::to_string(size_t(node_storage_.node_ptc_num(node)));
}
VTR_ASSERT(size_t(node) < node_tilable_track_nums_.size());
if (node_tilable_track_nums_[node].empty()) {
return std::to_string(size_t(node_storage_.node_ptc_num(node)));
}
std::string ret;
for (size_t iptc = 0; iptc < node_tilable_track_nums_[node].size(); iptc++) {
ret += std::to_string(size_t(node_tilable_track_nums_[node][iptc])) + ",";
}
// Remove the last comma
ret.pop_back();
return ret;
void RRGraphBuilder::set_node_ptc_nums(RRNodeId node, const std::vector<int>& ptc_numbers) {
node_storage_.set_node_ptc_nums(node, ptc_numbers);
}

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

void RRGraphBuilder::add_node_track_num(RRNodeId node, vtr::Point<size_t> node_offset, short track_id) {
VTR_ASSERT(size_t(node) < node_storage_.size());
VTR_ASSERT(size_t(node) < node_tilable_track_nums_.size());
VTR_ASSERT_MSG(node_storage_.node_type(node) == e_rr_type::CHANX || node_storage_.node_type(node) == e_rr_type::CHANY, "Track number valid only for CHANX/CHANY RR nodes");

size_t node_length = std::abs(node_storage_.node_xhigh(node) - node_storage_.node_xlow(node))
+ std::abs(node_storage_.node_yhigh(node) - node_storage_.node_ylow(node));
if (node_length + 1 != node_tilable_track_nums_[node].size()) {
node_tilable_track_nums_[node].resize(node_length + 1);
}

size_t offset = node_offset.x() - node_storage_.node_xlow(node) + node_offset.y() - node_storage_.node_ylow(node);
VTR_ASSERT(offset < node_tilable_track_nums_[node].size());

node_tilable_track_nums_[node][offset] = track_id;
size_t node_offset_value = node_offset.x() - node_storage_.node_xlow(node) + node_offset.y() - node_storage_.node_ylow(node);
node_storage_.add_node_tilable_track_num(node, node_offset_value, track_id);
}

void RRGraphBuilder::add_track_node_to_lookup(RRNodeId node) {
Expand All @@ -309,8 +261,13 @@ void RRGraphBuilder::add_track_node_to_lookup(RRNodeId node) {
// Routing channel nodes may have different ptc num
// Find the track ids using the x/y offset
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);
if (node_type == e_rr_type::CHANX) {
ptc = track_nums[x - node_storage_.node_xlow(node)];
} else {
VTR_ASSERT_DEBUG(node_type == e_rr_type::CHANY);
ptc = track_nums[y - node_storage_.node_ylow(node)];
}
node_lookup_.add_node(node, node_storage_.node_layer_low(node), x, y, node_type, ptc);
}
}
Expand Down
44 changes: 2 additions & 42 deletions libs/librrgraph/src/base/rr_graph_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,6 @@ class RRGraphBuilder {

/** @brief Return a writable object for the incoming edge storage */
vtr::vector<RRNodeId, std::vector<RREdgeId>>& node_in_edge_storage();

/** @brief Return a writable object of the node ptc storage (for tileable routing resource graph) */
vtr::vector<RRNodeId, std::vector<short>>& node_ptc_storage();

/** @brief Return the size for rr_node_metadata */
inline size_t rr_node_metadata_size() const {
Expand Down Expand Up @@ -279,11 +276,8 @@ class RRGraphBuilder {
node_storage_.set_node_mux_num(id, new_mux_num);
}

/** @brief Add a list of ptc number in string (split by comma) to a given node. This function is used by rr graph reader only. */
void set_node_ptc_nums(RRNodeId node, const std::string& ptc_str);

/** @brief With a given node, output ptc numbers into a string (use comma as delima). This function is used by rr graph writer only. */
std::string node_ptc_nums_to_string(RRNodeId node) const;
/** @brief Add a list of ptc numbers to a given node. This function is used by rr graph reader only. */
void set_node_ptc_nums(RRNodeId node, const std::vector<int>& ptc_numbers);

/** @brief Identify if a node contains multiple ptc numbers. It is used for tileable RR Graph and mainly used by I/O reader only. */
bool node_contain_multiple_ptc(RRNodeId node) const;
Expand Down Expand Up @@ -407,13 +401,6 @@ class RRGraphBuilder {
return node_storage_.count_rr_switches(arch_switch_inf, arch_switch_fanins);
}

/** @brief Unlock storage; required to modify an routing resource graph after edge is read */
inline void unlock_storage() {
node_storage_.edges_read_ = false;
node_storage_.partitioned_ = false;
node_storage_.clear_node_first_edge();
}

/** @brief Reserve the lists of nodes, edges, switches etc. to be memory efficient.
* This function is mainly used to reserve memory space inside RRGraph,
* when adding a large number of nodes/edge/switches/segments,
Expand All @@ -432,10 +419,6 @@ class RRGraphBuilder {
inline void resize_nodes(size_t size) {
node_storage_.resize(size);
}
/** @brief This function resize node ptc nums. Only used by RR graph I/O reader and writers. */
inline void resize_node_ptc_nums(size_t size) {
node_tilable_track_nums_.resize(size);
}


/** @brief This function resize rr_switch to accommodate size RR Switch. */
Expand Down Expand Up @@ -539,29 +522,6 @@ class RRGraphBuilder {
*/
vtr::vector<RRNodeId, std::vector<RREdgeId>> node_in_edges_;

/**
* @brief Extra ptc number for each routing resource node.
* @note This is required by tileable routing resource graphs. The first index is the node id, and
* the second index is is the relative distance from the starting point of the node.
* @details
* In a tileable routing architecture, routing tracks, e.g., CHANX and CHANY, follow a staggered organization.
* Hence, a routing track may appear in different routing channels, representing different ptc/track id.
* Here is an illustrative example of a X-direction routing track (CHANX) in INC direction, which is organized in staggered way.
*
* Coord(x,y) (1,0) (2,0) (3,0) (4,0) Another track (node)
* ptc=0 ------> ------>
* \ /
* ptc=1 ------> /
* \ /
* ptc=2 ------> /
* \ /
* ptc=3 ------->
* ^ ^
* | |
* starting point ending point
*/
vtr::vector<RRNodeId, std::vector<short>> node_tilable_track_nums_;

/** @warning The Metadata should stay as an independent data structure from the rest of the internal data,
* e.g., node_lookup! */
/* Metadata is an extra data on rr-nodes and edges, respectively, that is not used by vpr
Expand Down
129 changes: 126 additions & 3 deletions libs/librrgraph/src/base/rr_graph_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ void t_rr_graph_storage::alloc_and_load_edges(const t_rr_edge_info_set* rr_edges
void t_rr_graph_storage::remove_edges(std::vector<RREdgeId>& rr_edges_to_remove) {
VTR_ASSERT(!edges_read_);

if (rr_edges_to_remove.empty()) {
return;
}

size_t starting_edge_count = edge_dest_node_.size();

// Sort and make sure all edge indices are unique
Expand Down Expand Up @@ -178,12 +182,12 @@ bool t_rr_graph_storage::verify_first_edges() const {

void t_rr_graph_storage::init_fan_in() {
//Reset all fan-ins to zero
edges_read_ = true;
node_fan_in_.clear();
node_fan_in_.resize(node_storage_.size(), 0);
node_fan_in_.shrink_to_fit();
//Walk the graph and increment fanin on all downstream nodes
for(const auto& edge_id : edge_dest_node_.keys()) {
node_fan_in_[edge_dest_node_[edge_id]] += 1;
for(const auto& [_, dest_node] : edge_dest_node_.pairs()) {
node_fan_in_[dest_node] += 1;
}
}

Expand Down Expand Up @@ -625,6 +629,44 @@ void t_rr_graph_storage::set_node_direction(RRNodeId id, Direction new_direction
node_storage_[id].dir_side_.direction = new_direction;
}

void t_rr_graph_storage::set_node_ptc_nums(RRNodeId node, const std::vector<int>& ptc_numbers) {
VTR_ASSERT(size_t(node) < node_storage_.size());
VTR_ASSERT(!ptc_numbers.empty());
// The default VTR RR graph generator assigns only one PTC number per node, which is
// stored in the node_ptc_ field of rr_graph_storage. However, when the tileable RR
// graph is used, CHANX/CHANY nodes can have multiple PTC numbers.
//
// To satisfy VPR's requirements, we store the PTC number for offset = 0 in the
// node_ptc_ field, and store all PTC numbers assigned to the node in the
// node_tileable_track_nums_ field.
set_node_ptc_num(node, ptc_numbers[0]);
if (ptc_numbers.size() > 1) {
VTR_ASSERT(size_t(node) < node_tilable_track_nums_.size());
node_tilable_track_nums_[node].resize(ptc_numbers.size());
for (size_t iptc = 0; iptc < ptc_numbers.size(); iptc++) {
node_tilable_track_nums_[node][iptc] = ptc_numbers[iptc];
}
}
}

void t_rr_graph_storage::add_node_tilable_track_num(RRNodeId node, size_t node_offset, short track_id) {
VTR_ASSERT(size_t(node) < node_storage_.size());
VTR_ASSERT(size_t(node) < node_tilable_track_nums_.size());
VTR_ASSERT_MSG(node_type(node) == e_rr_type::CHANX || node_type(node) == e_rr_type::CHANY,
"Track number valid only for CHANX/CHANY RR nodes");

size_t node_length = std::abs(node_xhigh(node) - node_xlow(node))
+ std::abs(node_yhigh(node) - node_ylow(node))
+ 1;
VTR_ASSERT(node_offset < node_length);

if (node_length != node_tilable_track_nums_[node].size()) {
node_tilable_track_nums_[node].resize(node_length);
}

node_tilable_track_nums_[node][node_offset] = track_id;
}

void t_rr_graph_storage::add_node_side(RRNodeId id, e_side new_side) {
if (node_type(id) != e_rr_type::IPIN && node_type(id) != e_rr_type::OPIN) {
VTR_LOG_ERROR("Attempted to set RR node 'side' for non-pin type '%s'", node_type_string(id));
Expand All @@ -651,6 +693,87 @@ void t_rr_graph_storage::set_virtual_clock_network_root_idx(RRNodeId virtual_clo
}
}

void t_rr_graph_storage::remove_nodes(std::vector<RRNodeId> nodes_to_remove) {
VTR_ASSERT(!edges_read_);
VTR_ASSERT(!partitioned_);
// To remove the nodes, we first sort them in ascending order. This makes it easy
// to calculate the offset by which other node IDs need to be adjusted.
// For example, after sorting the nodes to be removed, if a node ID falls between
// the first and second element, its ID should be reduced by 1.
// If a node ID is larger than the last element, its ID should be reduced by
// the total number of nodes being removed.
std::sort(nodes_to_remove.begin(), nodes_to_remove.end());

// Iterate over the nodes to be removed and adjust the IDs of nodes
// that fall between them.
for (size_t removal_idx = 0; removal_idx < nodes_to_remove.size(); ++removal_idx) {
size_t start_rr_node_index = size_t(nodes_to_remove[removal_idx]) + 1;
size_t end_rr_node_index = (removal_idx == nodes_to_remove.size() - 1) ? node_storage_.size() : size_t(nodes_to_remove[removal_idx + 1]);
for (size_t node_idx = start_rr_node_index; node_idx < end_rr_node_index; ++node_idx) {
RRNodeId old_node = RRNodeId(node_idx);
// New node index is equal to the old nodex index minus the number of nodes being removed before it.
RRNodeId new_node = RRNodeId(node_idx-(removal_idx+1));
node_storage_[new_node] = node_storage_[old_node];
node_ptc_[new_node] = node_ptc_[old_node];
node_layer_[new_node] = node_layer_[old_node];
node_name_[new_node] = node_name_[old_node];
if (is_tileable_) {
node_bend_start_[new_node] = node_bend_start_[old_node];
node_bend_end_[new_node] = node_bend_end_[old_node];
node_tilable_track_nums_[new_node] = node_tilable_track_nums_[old_node];
}
}
}

// Now that the data structures are adjusted, we can shrink the size of them
size_t num_nodes_to_remove = nodes_to_remove.size();
VTR_ASSERT(num_nodes_to_remove <= node_storage_.size());
node_storage_.erase(node_storage_.end()-num_nodes_to_remove, node_storage_.end());
node_ptc_.erase(node_ptc_.end()-num_nodes_to_remove, node_ptc_.end());
node_layer_.erase(node_layer_.end()-num_nodes_to_remove, node_layer_.end());
// After shifting the IDs of nodes that are not removed to the left, the last
// `num_nodes_to_remove` node IDs become invalid (their names have already been
// updated for other nodes). Therefore, the corresponding entries in `node_name_`
// must be removed.
for (size_t node_index = node_name_.size()-num_nodes_to_remove; node_index < node_name_.size(); ++node_index) {
RRNodeId node = RRNodeId(node_index);
node_name_.erase(node);
}
if (is_tileable_) {
node_bend_start_.erase(node_bend_start_.end()-num_nodes_to_remove, node_bend_start_.end());
node_bend_end_.erase(node_bend_end_.end()-num_nodes_to_remove, node_bend_end_.end());
node_tilable_track_nums_.erase(node_tilable_track_nums_.end()-num_nodes_to_remove, node_tilable_track_nums_.end());
}

std::vector<RREdgeId> removed_edges;
// This function iterates over edge_src_node_ and edge_dest_node_ to remove
// entries where either endpoint of an edge is in the nodes_to_remove list.
// It also updates the node IDs of the remaining edges, since node IDs have
// been shifted.
auto adjust_edges = [&nodes_to_remove, &removed_edges](vtr::vector<RREdgeId, RRNodeId>& edge_nodes) {
for (auto [edge_id, node] : edge_nodes.pairs()) {
// Find insertion point in the sorted vector
auto node_it = std::lower_bound(nodes_to_remove.begin(), nodes_to_remove.end(), node);

if (node_it != nodes_to_remove.end() && *node_it == node) {
// Node exists in nodes_to_remove, mark edge for removal
removed_edges.push_back(edge_id);
} else {
// If the node is not in the nodes_to_remove list, update the node ID of the edge
// by finding how many nodes are there in nodes_to_remove before the node.
size_t node_offset = std::distance(nodes_to_remove.begin(), node_it);
size_t new_node_index = size_t(node) - node_offset;
edge_nodes[edge_id] = RRNodeId(new_node_index);
}
}
};

adjust_edges(edge_src_node_);
adjust_edges(edge_dest_node_);

remove_edges(removed_edges);
}

int t_rr_graph_view::node_ptc_num(RRNodeId id) const {
return node_ptc_[id].ptc_.pin_num;
}
Expand Down
Loading