Skip to content

Commit 08f357f

Browse files
authored
Merge pull request #3347 from verilog-to-routing/remove_node
Move node_tilable_track_nums_ to rr_graph_storage and add remove_node
2 parents 3a6bccc + 6555071 commit 08f357f

File tree

13 files changed

+266
-122
lines changed

13 files changed

+266
-122
lines changed

libs/librrgraph/src/base/rr_graph_builder.cpp

Lines changed: 12 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,6 @@ vtr::vector<RRNodeId, std::vector<RREdgeId>>& RRGraphBuilder::node_in_edge_stora
3131
return node_in_edges_;
3232
}
3333

34-
vtr::vector<RRNodeId, std::vector<short>>& RRGraphBuilder::node_ptc_storage() {
35-
return node_tilable_track_nums_;
36-
}
37-
3834
void RRGraphBuilder::add_node_to_all_locs(RRNodeId node) {
3935
e_rr_type node_type = node_storage_.node_type(node);
4036
short node_ptc_num = node_storage_.node_ptc_num(node);
@@ -76,7 +72,6 @@ RRNodeId RRGraphBuilder::create_node(int layer, int x, int y, e_rr_type type, in
7672
node_side = side;
7773
}
7874
node_storage_.emplace_back();
79-
node_tilable_track_nums_.emplace_back();
8075
RRNodeId new_node = RRNodeId(node_storage_.size() - 1);
8176
node_storage_.set_node_layer(new_node, layer, layer);
8277
node_storage_.set_node_type(new_node, type);
@@ -102,7 +97,6 @@ void RRGraphBuilder::clear() {
10297
node_lookup_.clear();
10398
node_storage_.clear();
10499
node_in_edges_.clear();
105-
node_tilable_track_nums_.clear();
106100
rr_node_metadata_.clear();
107101
rr_edge_metadata_.clear();
108102
rr_segments_.clear();
@@ -231,59 +225,17 @@ std::vector<RREdgeId> RRGraphBuilder::node_in_edges(RRNodeId node) const {
231225
return node_in_edges_[node];
232226
}
233227

234-
void RRGraphBuilder::set_node_ptc_nums(RRNodeId node, const std::string& ptc_str) {
235-
VTR_ASSERT(size_t(node) < node_storage_.size());
236-
std::vector<std::string> ptc_tokens = vtr::StringToken(ptc_str).split(",");
237-
VTR_ASSERT(ptc_tokens.size() >= 1);
238-
set_node_ptc_num(node, std::stoi(ptc_tokens[0]));
239-
if (ptc_tokens.size() > 1) {
240-
VTR_ASSERT(size_t(node) < node_tilable_track_nums_.size());
241-
node_tilable_track_nums_[node].resize(ptc_tokens.size());
242-
for (size_t iptc = 0; iptc < ptc_tokens.size(); iptc++) {
243-
node_tilable_track_nums_[node][iptc] = std::stoi(ptc_tokens[iptc]);
244-
}
245-
}
246-
}
247-
248-
std::string RRGraphBuilder::node_ptc_nums_to_string(RRNodeId node) const {
249-
if (node_tilable_track_nums_.empty()) {
250-
return std::to_string(size_t(node_storage_.node_ptc_num(node)));
251-
}
252-
VTR_ASSERT(size_t(node) < node_tilable_track_nums_.size());
253-
if (node_tilable_track_nums_[node].empty()) {
254-
return std::to_string(size_t(node_storage_.node_ptc_num(node)));
255-
}
256-
std::string ret;
257-
for (size_t iptc = 0; iptc < node_tilable_track_nums_[node].size(); iptc++) {
258-
ret += std::to_string(size_t(node_tilable_track_nums_[node][iptc])) + ",";
259-
}
260-
// Remove the last comma
261-
ret.pop_back();
262-
return ret;
228+
void RRGraphBuilder::set_node_ptc_nums(RRNodeId node, const std::vector<int>& ptc_numbers) {
229+
node_storage_.set_node_ptc_nums(node, ptc_numbers);
263230
}
264231

265232
bool RRGraphBuilder::node_contain_multiple_ptc(RRNodeId node) const {
266-
if (node_tilable_track_nums_.empty()) {
267-
return false;
268-
}
269-
return node_tilable_track_nums_[node].size() > 1;
233+
return node_storage_.node_contain_multiple_ptc(node);
270234
}
271235

272236
void RRGraphBuilder::add_node_track_num(RRNodeId node, vtr::Point<size_t> node_offset, short track_id) {
273-
VTR_ASSERT(size_t(node) < node_storage_.size());
274-
VTR_ASSERT(size_t(node) < node_tilable_track_nums_.size());
275-
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");
276-
277-
size_t node_length = std::abs(node_storage_.node_xhigh(node) - node_storage_.node_xlow(node))
278-
+ std::abs(node_storage_.node_yhigh(node) - node_storage_.node_ylow(node));
279-
if (node_length + 1 != node_tilable_track_nums_[node].size()) {
280-
node_tilable_track_nums_[node].resize(node_length + 1);
281-
}
282-
283-
size_t offset = node_offset.x() - node_storage_.node_xlow(node) + node_offset.y() - node_storage_.node_ylow(node);
284-
VTR_ASSERT(offset < node_tilable_track_nums_[node].size());
285-
286-
node_tilable_track_nums_[node][offset] = track_id;
237+
size_t node_offset_value = node_offset.x() - node_storage_.node_xlow(node) + node_offset.y() - node_storage_.node_ylow(node);
238+
node_storage_.add_node_tilable_track_num(node, node_offset_value, track_id);
287239
}
288240

289241
void RRGraphBuilder::add_track_node_to_lookup(RRNodeId node) {
@@ -309,8 +261,13 @@ void RRGraphBuilder::add_track_node_to_lookup(RRNodeId node) {
309261
// Routing channel nodes may have different ptc num
310262
// Find the track ids using the x/y offset
311263
if (e_rr_type::CHANX == node_type || e_rr_type::CHANY == node_type) {
312-
ptc = (node_type == e_rr_type::CHANX) ? node_tilable_track_nums_[node][x - node_storage_.node_xlow(node)] :
313-
node_tilable_track_nums_[node][y - node_storage_.node_ylow(node)];
264+
const std::vector<short>& track_nums = node_storage_.node_tilable_track_nums(node);
265+
if (node_type == e_rr_type::CHANX) {
266+
ptc = track_nums[x - node_storage_.node_xlow(node)];
267+
} else {
268+
VTR_ASSERT_DEBUG(node_type == e_rr_type::CHANY);
269+
ptc = track_nums[y - node_storage_.node_ylow(node)];
270+
}
314271
node_lookup_.add_node(node, node_storage_.node_layer_low(node), x, y, node_type, ptc);
315272
}
316273
}

libs/librrgraph/src/base/rr_graph_builder.h

Lines changed: 2 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,6 @@ class RRGraphBuilder {
5050

5151
/** @brief Return a writable object for the incoming edge storage */
5252
vtr::vector<RRNodeId, std::vector<RREdgeId>>& node_in_edge_storage();
53-
54-
/** @brief Return a writable object of the node ptc storage (for tileable routing resource graph) */
55-
vtr::vector<RRNodeId, std::vector<short>>& node_ptc_storage();
5653

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

282-
/** @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. */
283-
void set_node_ptc_nums(RRNodeId node, const std::string& ptc_str);
284-
285-
/** @brief With a given node, output ptc numbers into a string (use comma as delima). This function is used by rr graph writer only. */
286-
std::string node_ptc_nums_to_string(RRNodeId node) const;
279+
/** @brief Add a list of ptc numbers to a given node. This function is used by rr graph reader only. */
280+
void set_node_ptc_nums(RRNodeId node, const std::vector<int>& ptc_numbers);
287281

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

410-
/** @brief Unlock storage; required to modify an routing resource graph after edge is read */
411-
inline void unlock_storage() {
412-
node_storage_.edges_read_ = false;
413-
node_storage_.partitioned_ = false;
414-
node_storage_.clear_node_first_edge();
415-
}
416-
417404
/** @brief Reserve the lists of nodes, edges, switches etc. to be memory efficient.
418405
* This function is mainly used to reserve memory space inside RRGraph,
419406
* when adding a large number of nodes/edge/switches/segments,
@@ -432,10 +419,6 @@ class RRGraphBuilder {
432419
inline void resize_nodes(size_t size) {
433420
node_storage_.resize(size);
434421
}
435-
/** @brief This function resize node ptc nums. Only used by RR graph I/O reader and writers. */
436-
inline void resize_node_ptc_nums(size_t size) {
437-
node_tilable_track_nums_.resize(size);
438-
}
439422

440423

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

542-
/**
543-
* @brief Extra ptc number for each routing resource node.
544-
* @note This is required by tileable routing resource graphs. The first index is the node id, and
545-
* the second index is is the relative distance from the starting point of the node.
546-
* @details
547-
* In a tileable routing architecture, routing tracks, e.g., CHANX and CHANY, follow a staggered organization.
548-
* Hence, a routing track may appear in different routing channels, representing different ptc/track id.
549-
* Here is an illustrative example of a X-direction routing track (CHANX) in INC direction, which is organized in staggered way.
550-
*
551-
* Coord(x,y) (1,0) (2,0) (3,0) (4,0) Another track (node)
552-
* ptc=0 ------> ------>
553-
* \ /
554-
* ptc=1 ------> /
555-
* \ /
556-
* ptc=2 ------> /
557-
* \ /
558-
* ptc=3 ------->
559-
* ^ ^
560-
* | |
561-
* starting point ending point
562-
*/
563-
vtr::vector<RRNodeId, std::vector<short>> node_tilable_track_nums_;
564-
565525
/** @warning The Metadata should stay as an independent data structure from the rest of the internal data,
566526
* e.g., node_lookup! */
567527
/* Metadata is an extra data on rr-nodes and edges, respectively, that is not used by vpr

libs/librrgraph/src/base/rr_graph_storage.cpp

Lines changed: 126 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ void t_rr_graph_storage::alloc_and_load_edges(const t_rr_edge_info_set* rr_edges
6363
void t_rr_graph_storage::remove_edges(std::vector<RREdgeId>& rr_edges_to_remove) {
6464
VTR_ASSERT(!edges_read_);
6565

66+
if (rr_edges_to_remove.empty()) {
67+
return;
68+
}
69+
6670
size_t starting_edge_count = edge_dest_node_.size();
6771

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

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

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

632+
void t_rr_graph_storage::set_node_ptc_nums(RRNodeId node, const std::vector<int>& ptc_numbers) {
633+
VTR_ASSERT(size_t(node) < node_storage_.size());
634+
VTR_ASSERT(!ptc_numbers.empty());
635+
// The default VTR RR graph generator assigns only one PTC number per node, which is
636+
// stored in the node_ptc_ field of rr_graph_storage. However, when the tileable RR
637+
// graph is used, CHANX/CHANY nodes can have multiple PTC numbers.
638+
//
639+
// To satisfy VPR's requirements, we store the PTC number for offset = 0 in the
640+
// node_ptc_ field, and store all PTC numbers assigned to the node in the
641+
// node_tileable_track_nums_ field.
642+
set_node_ptc_num(node, ptc_numbers[0]);
643+
if (ptc_numbers.size() > 1) {
644+
VTR_ASSERT(size_t(node) < node_tilable_track_nums_.size());
645+
node_tilable_track_nums_[node].resize(ptc_numbers.size());
646+
for (size_t iptc = 0; iptc < ptc_numbers.size(); iptc++) {
647+
node_tilable_track_nums_[node][iptc] = ptc_numbers[iptc];
648+
}
649+
}
650+
}
651+
652+
void t_rr_graph_storage::add_node_tilable_track_num(RRNodeId node, size_t node_offset, short track_id) {
653+
VTR_ASSERT(size_t(node) < node_storage_.size());
654+
VTR_ASSERT(size_t(node) < node_tilable_track_nums_.size());
655+
VTR_ASSERT_MSG(node_type(node) == e_rr_type::CHANX || node_type(node) == e_rr_type::CHANY,
656+
"Track number valid only for CHANX/CHANY RR nodes");
657+
658+
size_t node_length = std::abs(node_xhigh(node) - node_xlow(node))
659+
+ std::abs(node_yhigh(node) - node_ylow(node))
660+
+ 1;
661+
VTR_ASSERT(node_offset < node_length);
662+
663+
if (node_length != node_tilable_track_nums_[node].size()) {
664+
node_tilable_track_nums_[node].resize(node_length);
665+
}
666+
667+
node_tilable_track_nums_[node][node_offset] = track_id;
668+
}
669+
628670
void t_rr_graph_storage::add_node_side(RRNodeId id, e_side new_side) {
629671
if (node_type(id) != e_rr_type::IPIN && node_type(id) != e_rr_type::OPIN) {
630672
VTR_LOG_ERROR("Attempted to set RR node 'side' for non-pin type '%s'", node_type_string(id));
@@ -651,6 +693,87 @@ void t_rr_graph_storage::set_virtual_clock_network_root_idx(RRNodeId virtual_clo
651693
}
652694
}
653695

696+
void t_rr_graph_storage::remove_nodes(std::vector<RRNodeId> nodes_to_remove) {
697+
VTR_ASSERT(!edges_read_);
698+
VTR_ASSERT(!partitioned_);
699+
// To remove the nodes, we first sort them in ascending order. This makes it easy
700+
// to calculate the offset by which other node IDs need to be adjusted.
701+
// For example, after sorting the nodes to be removed, if a node ID falls between
702+
// the first and second element, its ID should be reduced by 1.
703+
// If a node ID is larger than the last element, its ID should be reduced by
704+
// the total number of nodes being removed.
705+
std::sort(nodes_to_remove.begin(), nodes_to_remove.end());
706+
707+
// Iterate over the nodes to be removed and adjust the IDs of nodes
708+
// that fall between them.
709+
for (size_t removal_idx = 0; removal_idx < nodes_to_remove.size(); ++removal_idx) {
710+
size_t start_rr_node_index = size_t(nodes_to_remove[removal_idx]) + 1;
711+
size_t end_rr_node_index = (removal_idx == nodes_to_remove.size() - 1) ? node_storage_.size() : size_t(nodes_to_remove[removal_idx + 1]);
712+
for (size_t node_idx = start_rr_node_index; node_idx < end_rr_node_index; ++node_idx) {
713+
RRNodeId old_node = RRNodeId(node_idx);
714+
// New node index is equal to the old nodex index minus the number of nodes being removed before it.
715+
RRNodeId new_node = RRNodeId(node_idx-(removal_idx+1));
716+
node_storage_[new_node] = node_storage_[old_node];
717+
node_ptc_[new_node] = node_ptc_[old_node];
718+
node_layer_[new_node] = node_layer_[old_node];
719+
node_name_[new_node] = node_name_[old_node];
720+
if (is_tileable_) {
721+
node_bend_start_[new_node] = node_bend_start_[old_node];
722+
node_bend_end_[new_node] = node_bend_end_[old_node];
723+
node_tilable_track_nums_[new_node] = node_tilable_track_nums_[old_node];
724+
}
725+
}
726+
}
727+
728+
// Now that the data structures are adjusted, we can shrink the size of them
729+
size_t num_nodes_to_remove = nodes_to_remove.size();
730+
VTR_ASSERT(num_nodes_to_remove <= node_storage_.size());
731+
node_storage_.erase(node_storage_.end()-num_nodes_to_remove, node_storage_.end());
732+
node_ptc_.erase(node_ptc_.end()-num_nodes_to_remove, node_ptc_.end());
733+
node_layer_.erase(node_layer_.end()-num_nodes_to_remove, node_layer_.end());
734+
// After shifting the IDs of nodes that are not removed to the left, the last
735+
// `num_nodes_to_remove` node IDs become invalid (their names have already been
736+
// updated for other nodes). Therefore, the corresponding entries in `node_name_`
737+
// must be removed.
738+
for (size_t node_index = node_name_.size()-num_nodes_to_remove; node_index < node_name_.size(); ++node_index) {
739+
RRNodeId node = RRNodeId(node_index);
740+
node_name_.erase(node);
741+
}
742+
if (is_tileable_) {
743+
node_bend_start_.erase(node_bend_start_.end()-num_nodes_to_remove, node_bend_start_.end());
744+
node_bend_end_.erase(node_bend_end_.end()-num_nodes_to_remove, node_bend_end_.end());
745+
node_tilable_track_nums_.erase(node_tilable_track_nums_.end()-num_nodes_to_remove, node_tilable_track_nums_.end());
746+
}
747+
748+
std::vector<RREdgeId> removed_edges;
749+
// This function iterates over edge_src_node_ and edge_dest_node_ to remove
750+
// entries where either endpoint of an edge is in the nodes_to_remove list.
751+
// It also updates the node IDs of the remaining edges, since node IDs have
752+
// been shifted.
753+
auto adjust_edges = [&nodes_to_remove, &removed_edges](vtr::vector<RREdgeId, RRNodeId>& edge_nodes) {
754+
for (auto [edge_id, node] : edge_nodes.pairs()) {
755+
// Find insertion point in the sorted vector
756+
auto node_it = std::lower_bound(nodes_to_remove.begin(), nodes_to_remove.end(), node);
757+
758+
if (node_it != nodes_to_remove.end() && *node_it == node) {
759+
// Node exists in nodes_to_remove, mark edge for removal
760+
removed_edges.push_back(edge_id);
761+
} else {
762+
// If the node is not in the nodes_to_remove list, update the node ID of the edge
763+
// by finding how many nodes are there in nodes_to_remove before the node.
764+
size_t node_offset = std::distance(nodes_to_remove.begin(), node_it);
765+
size_t new_node_index = size_t(node) - node_offset;
766+
edge_nodes[edge_id] = RRNodeId(new_node_index);
767+
}
768+
}
769+
};
770+
771+
adjust_edges(edge_src_node_);
772+
adjust_edges(edge_dest_node_);
773+
774+
remove_edges(removed_edges);
775+
}
776+
654777
int t_rr_graph_view::node_ptc_num(RRNodeId id) const {
655778
return node_ptc_[id].ptc_.pin_num;
656779
}

0 commit comments

Comments
 (0)