1
-
2
- /* ***************************************************************************
3
- * This file include most-utilized functions that manipulate on the
4
- * RRGraph object
5
- ***************************************************************************/
6
1
#include < queue>
7
2
#include < random>
8
3
9
4
#include " rr_graph_utils.h"
10
-
11
5
#include " vpr_error.h"
12
-
13
6
#include " rr_graph_obj.h"
7
+ #include " rr_graph_builder.h"
8
+
9
+ /*
10
+ * @brief Walk backwards from origin SINK, and insert all cluster-edge IPINs to which origin is connected to sink_ipins
11
+ *
12
+ * @param rr_graph
13
+ * @param fanins A vector where, at each node index, is a vector of edges which are fanins of that node
14
+ * @param sink_ipins The set in which cluster-edge IPINs will be collected; should be empty
15
+ * @param curr The current node in recursion; originally, should be the same as origin
16
+ * @param origin The SINK whose cluster-edge IPINs are to be collected
17
+ */
18
+ static void rr_walk_cluster_recursive (const RRGraphView& rr_graph,
19
+ const vtr::vector<RRNodeId, std::vector<RREdgeId>>& fanins,
20
+ std::unordered_set<RRNodeId>& sink_ipins,
21
+ const RRNodeId curr,
22
+ const RRNodeId origin);
23
+
24
+ static void rr_walk_cluster_recursive (const RRGraphView& rr_graph,
25
+ const vtr::vector<RRNodeId, std::vector<RREdgeId>>& fanins,
26
+ std::unordered_set<RRNodeId>& sink_ipins,
27
+ const RRNodeId curr,
28
+ const RRNodeId origin) {
29
+ // Make sure SINK in the same cluster as origin
30
+ int curr_x = rr_graph.node_xlow (curr);
31
+ int curr_y = rr_graph.node_ylow (curr);
32
+ if ((curr_x < rr_graph.node_xlow (origin)) || (curr_x > rr_graph.node_xhigh (origin)) || (curr_y < rr_graph.node_ylow (origin)) || (curr_y > rr_graph.node_yhigh (origin)))
33
+ return ;
34
+
35
+ VTR_ASSERT_SAFE (rr_graph.node_type (origin) == e_rr_type::SINK);
36
+
37
+ // We want to go "backward" to the cluster IPINs connected to the origin node
38
+ const std::vector<RREdgeId>& incoming_edges = fanins[curr];
39
+ for (RREdgeId edge : incoming_edges) {
40
+ RRNodeId parent = rr_graph.edge_src_node (edge);
41
+ VTR_ASSERT_SAFE (parent != RRNodeId::INVALID ());
42
+
43
+ if (rr_graph.node_type (parent) != e_rr_type::IPIN) {
44
+ if (rr_graph.node_type (parent) != e_rr_type::CHANX && rr_graph.node_type (parent) != e_rr_type::CHANY)
45
+ return ;
46
+
47
+ // If the parent node isn't in the origin's cluster, the current node is a "cluster-edge" pin,
48
+ // so add it to sink_ipins
49
+ sink_ipins.insert (curr);
50
+ return ;
51
+ }
52
+
53
+ // If the parent node is intra-cluster, keep going "backward"
54
+ rr_walk_cluster_recursive (rr_graph, fanins, sink_ipins, parent, origin);
55
+ }
56
+ }
14
57
15
- /* ***************************************************************************
16
- * Find the switches interconnecting two nodes
17
- * Return a vector of switch ids
18
- ***************************************************************************/
19
58
std::vector<RRSwitchId> find_rr_graph_switches (const RRGraph& rr_graph,
20
59
const RRNodeId& from_node,
21
60
const RRNodeId& to_node) {
@@ -37,9 +76,6 @@ std::vector<RRSwitchId> find_rr_graph_switches(const RRGraph& rr_graph,
37
76
}
38
77
39
78
int seg_index_of_cblock (const RRGraphView& rr_graph, t_rr_type from_rr_type, int to_node) {
40
- /* Returns the segment number (distance along the channel) of the connection *
41
- * box from from_rr_type (CHANX or CHANY) to to_node (IPIN). */
42
-
43
79
if (from_rr_type == CHANX)
44
80
return (rr_graph.node_xlow (RRNodeId (to_node)));
45
81
else
@@ -48,13 +84,6 @@ int seg_index_of_cblock(const RRGraphView& rr_graph, t_rr_type from_rr_type, int
48
84
}
49
85
50
86
int seg_index_of_sblock (const RRGraphView& rr_graph, int from_node, int to_node) {
51
- /* Returns the segment number (distance along the channel) of the switch box *
52
- * box from from_node (CHANX or CHANY) to to_node (CHANX or CHANY). The *
53
- * switch box on the left side of a CHANX segment at (i,j) has seg_index = *
54
- * i-1, while the switch box on the right side of that segment has seg_index *
55
- * = i. CHANY stuff works similarly. Hence the range of values returned is *
56
- * 0 to device_ctx.grid.width()-1 (if from_node is a CHANX) or 0 to device_ctx.grid.height()-1 (if from_node is a CHANY). */
57
-
58
87
t_rr_type from_rr_type, to_rr_type;
59
88
60
89
from_rr_type = rr_graph.node_type (RRNodeId (from_node));
@@ -117,6 +146,97 @@ vtr::vector<RRNodeId, std::vector<RREdgeId>> get_fan_in_list(const RRGraphView&
117
146
return node_fan_in_list;
118
147
}
119
148
149
+ void rr_set_sink_locs (const RRGraphView& rr_graph, RRGraphBuilder& rr_graph_builder, const DeviceGrid& grid) {
150
+ const vtr::vector<RRNodeId, std::vector<RREdgeId>> node_fanins = get_fan_in_list (rr_graph);
151
+
152
+ // Keep track of offsets for SINKs for each tile type, to avoid repeated calculations
153
+ std::unordered_map<t_physical_tile_type_ptr, std::unordered_map<int , vtr::Point <int >>> physical_type_offsets;
154
+
155
+ // Iterate over all SINK nodes
156
+ for (size_t node = 0 ; node < rr_graph.num_nodes (); ++node) {
157
+ auto node_id = RRNodeId (node);
158
+
159
+ if (rr_graph.node_type ((RRNodeId)node_id) != e_rr_type::SINK)
160
+ continue ;
161
+
162
+ int node_xlow = rr_graph.node_xlow (node_id);
163
+ int node_ylow = rr_graph.node_ylow (node_id);
164
+ int node_xhigh = rr_graph.node_xhigh (node_id);
165
+ int node_yhigh = rr_graph.node_yhigh (node_id);
166
+
167
+ // Skip "0x0" nodes; either the tile is 1x1, or we have seen the node on a previous call of this function
168
+ // and its new location has already been set
169
+ if ((node_xhigh - node_xlow) == 0 && (node_yhigh - node_ylow) == 0 )
170
+ continue ;
171
+
172
+ int node_layer = rr_graph.node_layer (node_id);
173
+ int node_ptc = rr_graph.node_ptc_num (node_id);
174
+
175
+ t_physical_tile_loc tile_loc = {node_xlow, node_ylow, node_layer};
176
+ t_physical_tile_type_ptr tile_type = grid.get_physical_type (tile_loc);
177
+ vtr::Rect <int > tile_bb = grid.get_tile_bb (tile_loc);
178
+
179
+ // See if we have encountered this tile type/ptc combo before, and used saved offset if so
180
+ vtr::Point <int > new_loc (-1 , -1 );
181
+ if ((physical_type_offsets.find (tile_type) != physical_type_offsets.end ()) && (physical_type_offsets[tile_type].find (node_ptc) != physical_type_offsets[tile_type].end ())) {
182
+ new_loc = tile_bb.bottom_left () + physical_type_offsets[tile_type].at (node_ptc);
183
+ } else { /* We have not seen this tile type/ptc combo before */
184
+ // The IPINs of the current SINK node
185
+ std::unordered_set<RRNodeId> sink_ipins = {};
186
+ rr_walk_cluster_recursive (rr_graph, node_fanins, sink_ipins, node_id, node_id);
187
+
188
+ /* Set SINK locations as average of collected IPINs */
189
+
190
+ if (sink_ipins.empty ())
191
+ continue ;
192
+
193
+ // Use float so that we can take average later
194
+ std::vector<float > x_coords;
195
+ std::vector<float > y_coords;
196
+
197
+ // Add coordinates of each "cluster-edge" pin to vectors
198
+ for (const auto & pin : sink_ipins) {
199
+ int pin_x = rr_graph.node_xlow (pin);
200
+ int pin_y = rr_graph.node_ylow (pin);
201
+
202
+ VTR_ASSERT_SAFE (pin_x == rr_graph.node_xhigh (pin));
203
+ VTR_ASSERT_SAFE (pin_y == rr_graph.node_yhigh (pin));
204
+
205
+ x_coords.push_back ((float )pin_x);
206
+ y_coords.push_back ((float )pin_y);
207
+ }
208
+
209
+ new_loc = {(int )round (std::accumulate (x_coords.begin (), x_coords.end (), 0 .f ) / (double )x_coords.size ()),
210
+ (int )round (std::accumulate (y_coords.begin (), y_coords.end (), 0 .f ) / (double )y_coords.size ())};
211
+
212
+ // Save offset for this tile/ptc combo
213
+ if (physical_type_offsets.find (tile_type) == physical_type_offsets.end ())
214
+ physical_type_offsets[tile_type] = {};
215
+
216
+ physical_type_offsets[tile_type].insert ({node_ptc, new_loc - tile_bb.bottom_left ()});
217
+ }
218
+
219
+ // Remove old locations from lookup
220
+ VTR_ASSERT (rr_graph_builder.node_lookup ().find_node (node_layer, new_loc.x (), new_loc.y (), SINK, node_ptc) != RRNodeId::INVALID ());
221
+
222
+ for (int x = tile_bb.xmin (); x <= tile_bb.xmax (); ++x) {
223
+ for (int y = tile_bb.ymin (); y <= tile_bb.ymax (); ++y) {
224
+ if (x == new_loc.x () && y == new_loc.y ()) /* The new sink location */
225
+ continue ;
226
+
227
+ if (rr_graph_builder.node_lookup ().find_node (node_layer, x, y, SINK, node_ptc) == RRNodeId::INVALID ()) /* Already removed */
228
+ continue ;
229
+
230
+ bool removed_successfully = rr_graph_builder.node_lookup ().remove_node (node_id, node_layer, x, y, SINK, node_ptc);
231
+ VTR_ASSERT (removed_successfully);
232
+ }
233
+ }
234
+
235
+ // Set new coordinates
236
+ rr_graph_builder.set_node_coordinates (node_id, (short )new_loc.x (), (short )new_loc.y (), (short )new_loc.x (), (short )new_loc.y ());
237
+ }
238
+ }
239
+
120
240
bool inter_layer_connections_limited_to_opin (const RRGraphView& rr_graph) {
121
241
bool limited_to_opin = true ;
122
242
for (const auto & from_node : rr_graph.nodes ()) {
0 commit comments