Skip to content

Commit 29bfe3c

Browse files
committed
Merge branch 'remove_node' of https://github.com/verilog-to-routing/vtr-verilog-to-routing into add_crr
2 parents 7f0b02e + 3b9f552 commit 29bfe3c

File tree

12 files changed

+652
-155
lines changed

12 files changed

+652
-155
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,3 +160,4 @@ cmake-build-release
160160
# Clangd
161161
#
162162
compile_commands.json
163+
.clangd

doc/src/arch/reference.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,6 @@ Grid Layout Example
589589
590590
.. note:: Exactly one of the ``x`` or ``y`` attributes must be specified.
591591
592-
.. note:: Interposers are experimental and are currently not supported by VPR and using the related tags will not actually result in any changes to the flow.
593592
Defines an interposer cut for modelling 2.5D interposer-based architectures. An interposer cut will cut all connections at location 'loc' along the axis 'dim' Leaving the two sides completely unconnected.
594593
To reconnect the two sides, this tag can have multiple <interdie_wire> tags as children to specify the connection between the two sides.
595594
@@ -2751,7 +2750,7 @@ The number of any additional wires or muxes created by scatter-gather specificat
27512750
Overview of how scatter-gather patterns work. First, connections from a switchblock location are selected according to the specification.
27522751
These selected connection are then muxed and passed through the scatter-gather node, which is typically a wire segment. The scatter-gather node then fans out or scatters in another switchblock location.
27532752
2754-
.. note:: Scatter-Gather patterns are only supported for 3D architectures where the scatter-gather links are unidirectional. They are not currently supported in 2D architectures or with bidirectional sg_links.
2753+
.. note:: Scatter-Gather patterns are only supported for uni-directional 3D and uni-directional 2D architectures. Bidirectional sg_links are not currently supported.
27552754
27562755
When instantiated, a scatter-gather pattern gathers connections from a switchblock and passes the connection through a multiplexer and the scatter-gather node which is typically a wire segment, then scatters or fans out somewhere else in the device. These patterns can be used to define 3D switchblocks. An example is shown below:
27572756

libs/librrgraph/src/base/rr_graph_builder.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,17 @@ class RRGraphBuilder {
348348
inline void alloc_and_load_edges(const t_rr_edge_info_set* rr_edges_to_create) {
349349
node_storage_.alloc_and_load_edges(rr_edges_to_create);
350350
}
351+
352+
/** @brief Removes a given list of RREdgeIds for the RR Graph.
353+
* This method does not preserve the order of edges. If you're
354+
* calling it after partition_edges has been called, you need
355+
* to call it again.
356+
*
357+
* @param rr_edges_to_remove list of RREdgeIds to be removed
358+
*/
359+
inline void remove_edges(std::vector<RREdgeId>& rr_edges_to_remove) {
360+
node_storage_.remove_edges(rr_edges_to_remove);
361+
}
351362

352363
/** @brief Overrides the associated switch for a given edge by
353364
* updating the edge to use the passed in switch. */

libs/librrgraph/src/base/rr_graph_storage.cpp

Lines changed: 138 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
#include "rr_graph_storage.h"
33
#include "physical_types.h"
44
#include "rr_graph_fwd.h"
5+
#include "vtr_assert.h"
56
#include "vtr_error.h"
67
#include "librrgraph_types.h"
8+
#include "vtr_util.h"
79

810
#include <algorithm>
911
#include <cstddef>
@@ -57,6 +59,46 @@ void t_rr_graph_storage::alloc_and_load_edges(const t_rr_edge_info_set* rr_edges
5759
}
5860
}
5961

62+
void t_rr_graph_storage::remove_edges(std::vector<RREdgeId>& rr_edges_to_remove) {
63+
VTR_ASSERT(!edges_read_);
64+
65+
size_t starting_edge_count = edge_dest_node_.size();
66+
67+
// Sort and make sure all edge indices are unique
68+
vtr::uniquify(rr_edges_to_remove);
69+
VTR_ASSERT_SAFE(std::is_sorted(rr_edges_to_remove.begin(), rr_edges_to_remove.end()));
70+
71+
// Index of the last edge
72+
size_t edge_list_end = edge_dest_node_.size() - 1;
73+
74+
// Iterate backwards through the list of indices we want to remove.
75+
for (auto it = rr_edges_to_remove.rbegin(); it != rr_edges_to_remove.rend(); ++it) {
76+
RREdgeId erase_idx = *it;
77+
78+
// Copy what's at the end of the list to the index we wanted to remove
79+
edge_dest_node_[erase_idx] = edge_dest_node_[RREdgeId(edge_list_end)];
80+
edge_src_node_[erase_idx] = edge_src_node_[RREdgeId(edge_list_end)];
81+
edge_switch_[erase_idx] = edge_switch_[RREdgeId(edge_list_end)];
82+
edge_remapped_[erase_idx] = edge_remapped_[RREdgeId(edge_list_end)];
83+
84+
// At this point we have no copies of what was at erase_idx and two copies of
85+
// what was at the end of the list. If we make the list one element shorter,
86+
// we end up with a list that has removed the element at erase_idx.
87+
edge_list_end--;
88+
89+
}
90+
91+
// We have a new index to the end of the list, call erase on the elements past that index
92+
// to update the std::vector and shrink the actual data structures.
93+
edge_dest_node_.erase(edge_dest_node_.begin() + edge_list_end + 1, edge_dest_node_.end());
94+
edge_src_node_.erase(edge_src_node_.begin() + edge_list_end + 1, edge_src_node_.end());
95+
edge_switch_.erase(edge_switch_.begin() + edge_list_end + 1, edge_switch_.end());
96+
edge_remapped_.erase(edge_remapped_.begin() + edge_list_end + 1, edge_remapped_.end());
97+
98+
VTR_ASSERT(edge_dest_node_.size() == (starting_edge_count - rr_edges_to_remove.size()));
99+
}
100+
101+
60102
void t_rr_graph_storage::assign_first_edges() {
61103
VTR_ASSERT(node_first_edge_.empty());
62104

@@ -68,39 +110,42 @@ void t_rr_graph_storage::assign_first_edges() {
68110
edge_src_node_.end()));
69111

70112
size_t node_id = 0;
71-
size_t first_id = 0;
72-
size_t second_id = 0;
113+
size_t first_edge_id = 0;
114+
size_t second_edge_id = 0;
115+
73116
size_t num_edges = edge_src_node_.size();
74117
VTR_ASSERT(edge_dest_node_.size() == num_edges);
75118
VTR_ASSERT(edge_switch_.size() == num_edges);
76119
VTR_ASSERT(edge_remapped_.size() == num_edges);
120+
77121
while (true) {
78-
VTR_ASSERT(first_id < num_edges);
79-
VTR_ASSERT(second_id < num_edges);
80-
size_t current_node_id = size_t(edge_src_node_[RREdgeId(second_id)]);
122+
VTR_ASSERT(first_edge_id < num_edges);
123+
VTR_ASSERT(second_edge_id < num_edges);
124+
125+
size_t current_node_id = size_t(edge_src_node_[RREdgeId(second_edge_id)]);
81126
if (node_id < current_node_id) {
82127
// All edges belonging to node_id are assigned.
83128
while (node_id < current_node_id) {
84129
// Store any edges belongs to node_id.
85130
VTR_ASSERT(node_id < node_first_edge_.size());
86-
node_first_edge_[RRNodeId(node_id)] = RREdgeId(first_id);
87-
first_id = second_id;
131+
node_first_edge_[RRNodeId(node_id)] = RREdgeId(first_edge_id);
132+
first_edge_id = second_edge_id;
88133
node_id += 1;
89134
}
90135

91136
VTR_ASSERT(node_id == current_node_id);
92-
node_first_edge_[RRNodeId(node_id)] = RREdgeId(second_id);
137+
node_first_edge_[RRNodeId(node_id)] = RREdgeId(second_edge_id);
93138
} else {
94-
second_id += 1;
95-
if (second_id == num_edges) {
139+
second_edge_id += 1;
140+
if (second_edge_id == num_edges) {
96141
break;
97142
}
98143
}
99144
}
100145

101146
// All remaining nodes have no edges, set as such.
102147
for (size_t inode = node_id + 1; inode < node_first_edge_.size(); ++inode) {
103-
node_first_edge_[RRNodeId(inode)] = RREdgeId(second_id);
148+
node_first_edge_[RRNodeId(inode)] = RREdgeId(second_edge_id);
104149
}
105150

106151
VTR_ASSERT_SAFE(verify_first_edges());
@@ -649,6 +694,88 @@ void t_rr_graph_storage::set_virtual_clock_network_root_idx(RRNodeId virtual_clo
649694
}
650695
}
651696

697+
void t_rr_graph_storage::remove_nodes(const std::vector<RRNodeId>& nodes) {
698+
// To remove the nodes, we first sort them in ascending order. This makes it easy
699+
// to calculate the offset by which other node IDs need to be adjusted.
700+
// For example, after sorting the nodes to be removed, if a node ID falls between
701+
// the first and second element, its ID should be reduced by 1.
702+
// If a node ID is larger than the last element, its ID should be reduced by
703+
// the total number of nodes being removed.
704+
std::vector<RRNodeId> sorted_nodes = nodes;
705+
std::sort(sorted_nodes.begin(), sorted_nodes.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 i = 0; i < sorted_nodes.size(); ++i) {
710+
size_t start_rr_node_index = size_t(sorted_nodes[i]) + 1;
711+
size_t end_rr_node_index = (i == sorted_nodes.size() - 1) ? sorted_nodes.size() : size_t(sorted_nodes[i + 1]);
712+
for (size_t j = start_rr_node_index; j < end_rr_node_index; ++j) {
713+
RRNodeId old_node = RRNodeId(j);
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(j-(i+1));
716+
node_storage_[new_node] = node_storage_[old_node];
717+
node_ptc_[new_node] = node_ptc_[old_node];
718+
node_first_edge_[new_node] = node_first_edge_[old_node];
719+
node_fan_in_[new_node] = node_fan_in_[old_node];
720+
node_layer_[new_node] = node_layer_[old_node];
721+
node_name_[new_node] = node_name_[old_node];
722+
if (is_tileable_) {
723+
node_bend_start_[new_node] = node_bend_start_[old_node];
724+
node_bend_end_[new_node] = node_bend_end_[old_node];
725+
node_tilable_track_nums_[new_node] = node_tilable_track_nums_[old_node];
726+
}
727+
}
728+
}
729+
730+
// Now that the data structures are adjusted, we can shrink the size of them
731+
size_t num_nodes_to_remove = sorted_nodes.size();
732+
VTR_ASSERT(num_nodes_to_remove <= node_storage_.size());
733+
node_storage_.erase(node_storage_.end()-num_nodes_to_remove, node_storage_.end());
734+
node_ptc_.erase(node_ptc_.end()-num_nodes_to_remove, node_ptc_.end());
735+
node_first_edge_.erase(node_first_edge_.end()-num_nodes_to_remove, node_first_edge_.end());
736+
node_fan_in_.erase(node_fan_in_.end()-num_nodes_to_remove, node_fan_in_.end());
737+
node_layer_.erase(node_layer_.end()-num_nodes_to_remove, node_layer_.end());
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+
auto adjust_edges = [&](vtr::vector<RREdgeId, RRNodeId>& edge_nodes) {
750+
for (size_t edge_index = 0; edge_index < edge_nodes.size(); ++edge_index) {
751+
RREdgeId edge_id = RREdgeId(edge_index);
752+
RRNodeId node = edge_nodes[edge_id];
753+
754+
// Find insertion point in the sorted vector
755+
auto node_it = std::lower_bound(sorted_nodes.begin(), sorted_nodes.end(), node);
756+
757+
if (node_it != sorted_nodes.end() && *node_it == node) {
758+
// Node exists in sorted_nodes, mark edge for removal
759+
removed_edges.push_back(edge_id);
760+
} else {
761+
size_t node_offset;
762+
if (node_it == sorted_nodes.end()) {
763+
node_offset = sorted_nodes.size();
764+
} else {
765+
node_offset = std::distance(sorted_nodes.begin(), node_it) + 1;
766+
}
767+
size_t new_node_index = size_t(node) - node_offset;
768+
edge_nodes[edge_id] = RRNodeId(new_node_index);
769+
}
770+
}
771+
};
772+
773+
adjust_edges(edge_src_node_);
774+
adjust_edges(edge_dest_node_);
775+
776+
remove_edges(removed_edges);
777+
}
778+
652779
int t_rr_graph_view::node_ptc_num(RRNodeId id) const {
653780
return node_ptc_[id].ptc_.pin_num;
654781
}

libs/librrgraph/src/base/rr_graph_storage.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,14 @@ class t_rr_graph_storage {
400400
return vtr::StrongIdRange<RREdgeId>(first_edge(id), last_edge(id));
401401
}
402402

403+
/** @brief Returns a range of all edges in the RR Graph.
404+
* This method does not depend on the edges begin correctly
405+
* sorted and can be used before partition_edges is called.
406+
*/
407+
inline vtr::StrongIdRange<RREdgeId> all_edges() const {
408+
return vtr::StrongIdRange<RREdgeId>(RREdgeId(0), RREdgeId(edge_src_node_.size()));
409+
}
410+
403411
/** @brief Retrieve the RREdgeId for iedge'th edge in RRNodeId.
404412
*
405413
* This method should generally not be used, and instead first_edge and
@@ -700,6 +708,8 @@ class t_rr_graph_storage {
700708
void set_node_ptc_nums(RRNodeId node, const std::string& ptc_str);
701709
void add_node_tilable_track_num(RRNodeId node, size_t node_offset, short track_id);
702710

711+
void emplace_back_node_tilable_track_num();
712+
703713
bool node_contain_multiple_ptc(RRNodeId node) const {
704714
if (node_tilable_track_nums_.empty()) {
705715
return false;
@@ -727,6 +737,16 @@ class t_rr_graph_storage {
727737
*/
728738
void set_virtual_clock_network_root_idx(RRNodeId virtual_clock_network_root_idx);
729739

740+
/**
741+
* @brief Removes a given list of RRNodes from the RR Graph
742+
* This method should be called after partition_edges has been called.
743+
* @note This a very expensive method, so should be called only when necessary. It is better
744+
* to not add nodes in the first place, instead of relying on this method to remove nodes.
745+
*
746+
* @param nodes list of RRNodes to be removed
747+
*/
748+
void remove_nodes(const std::vector<RRNodeId>& nodes);
749+
730750
/****************
731751
* Edge methods *
732752
****************/
@@ -799,6 +819,15 @@ class t_rr_graph_storage {
799819
/** @brief Adds a batch of edges.*/
800820
void alloc_and_load_edges(const t_rr_edge_info_set* rr_edges_to_create);
801821

822+
/** @brief Removes a given list of RREdgeIds for the RR Graph.
823+
* This method does not preserve the order of edges. If you're
824+
* calling it after partition_edges has been called, you need
825+
* to call it again.
826+
*
827+
* @param rr_edges_to_remove list of RREdgeIds to be removed
828+
*/
829+
void remove_edges(std::vector<RREdgeId>& rr_edges_to_remove);
830+
802831
/* Edge finalization methods */
803832

804833
/** @brief Counts the number of rr switches needed based on fan in to support mux
@@ -988,7 +1017,11 @@ class t_rr_graph_storage {
9881017
* | |
9891018
* starting point ending point
9901019
*/
1020+
<<<<<<< HEAD
9911021
vtr::vector<RRNodeId, std::vector<short>> node_tilable_track_nums_;
1022+
=======
1023+
vtr::vector<RRNodeId, std::vector<short>> node_tilable_track_nums_;
1024+
>>>>>>> 3b9f5526e6ecfe4cf370548812205ffcd2f31db2
9921025

9931026
/** @brief
9941027
* This array stores the first edge of each RRNodeId. Not that the length

libs/librrgraph/src/base/rr_graph_view.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,5 +126,3 @@ bool RRGraphView::validate_in_edges() const {
126126
}
127127
return true;
128128
}
129-
130-

libs/librrgraph/src/base/rr_graph_view.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,11 @@
6565
#include "metadata_storage.h"
6666
#include "rr_node.h"
6767
#include "physical_types.h"
68+
#include "rr_node_types.h"
6869
#include "rr_spatial_lookup.h"
6970
#include "vtr_geometry.h"
7071
#include "rr_graph_utils.h"
72+
#include "vtr_range.h"
7173

7274
class RRGraphView {
7375
/* -- Constructors -- */
@@ -583,14 +585,25 @@ class RRGraphView {
583585
* @example
584586
* RRGraphView rr_graph; // A dummy rr_graph for a short example
585587
* RRNodeId node; // A dummy node for a short example
586-
* for (RREdgeId edge : rr_graph.edges(node)) {
588+
* for (t_edge_size edge : rr_graph.edges(node)) {
587589
* // Do something with the edge
588590
* }
591+
*
592+
* @note Iterating on the range returned by this function will not give you an RREdgeId, but instead gives you the index among a node's outgoing edges
589593
*/
590594
inline edge_idx_range edges(const RRNodeId& id) const {
591595
return vtr::make_range(edge_idx_iterator(0), edge_idx_iterator(num_edges(id)));
592596
}
593597

598+
/** @brief Returns a range of all edges in the RR Graph.
599+
* This method does not depend on the edges begin correctly
600+
* sorted and can be used before partition_edges is called.
601+
*/
602+
inline vtr::StrongIdRange<RREdgeId> all_edges() const {
603+
return node_storage_.all_edges();
604+
}
605+
606+
594607
/**
595608
* @brief Return ID range for outgoing edges.
596609
*/

0 commit comments

Comments
 (0)