@@ -63,6 +63,10 @@ void t_rr_graph_storage::alloc_and_load_edges(const t_rr_edge_info_set* rr_edges
6363void 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
179183void 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+
628670void 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+
654777int t_rr_graph_view::node_ptc_num (RRNodeId id) const {
655778 return node_ptc_[id].ptc_ .pin_num ;
656779}
0 commit comments