Skip to content

Commit 3f2b9e8

Browse files
authored
Merge pull request #2639 from nedsels/improve_map_lookahead
Improve SINK Node Locations
2 parents fca017a + bca753e commit 3f2b9e8

File tree

34 files changed

+1006
-571
lines changed

34 files changed

+1006
-571
lines changed

doc/src/api/vpr/grid.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
========
2+
Grid
3+
========
4+
5+
DeviceGrid
6+
-------
7+
8+
.. doxygenclass:: DeviceGrid
9+
:project: vpr
10+
:members:

doc/src/api/vpr/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ VPR API
77
:maxdepth: 1
88

99
contexts
10+
grid
1011
mapping
1112
netlist
1213
route_tree

doc/src/api/vpr/rr_graph.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,9 @@ RRSpatialLookup
3535
:project: librrgraph
3636
:members:
3737

38+
rr_graph_utils
39+
---------------
40+
41+
.. doxygenfile:: rr_graph_utils.h
42+
:project: librrgraph
43+
:sections: briefdescription detaileddescription func prototype user-defined public-func
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
==============
2+
Router Lookahead
3+
==============
4+
5+
e_router_lookahead
6+
----------
7+
.. doxygenenum:: e_router_lookahead
8+
:project: vpr
9+
10+
11+
RouterLookahead
12+
----------
13+
.. doxygenclass:: RouterLookahead
14+
:project: vpr
15+
:members:
16+
17+
MapLookahead
18+
----------
19+
.. doxygenclass:: MapLookahead
20+
:project: vpr
21+
22+
make_router_lookahead
23+
----------
24+
.. doxygenfunction:: make_router_lookahead
25+
:project: vpr
26+
27+
get_cached_router_lookahead
28+
----------
29+
.. doxygenfunction:: get_cached_router_lookahead
30+
:project: vpr
31+
32+
invalidate_router_lookahead_cache
33+
----------
34+
.. doxygenfunction:: invalidate_router_lookahead_cache
35+
:project: vpr

doc/src/api/vprinternals/vpr_router.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ VPR Router
77
.. toctree::
88
:maxdepth: 1
99

10-
router_heap
10+
router_heap
11+
router_lookahead

libs/libarchfpga/src/device_grid.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <cmath>
77
#include "vtr_ndmatrix.h"
88
#include "physical_types.h"
9+
#include "vtr_geometry.h"
910

1011
/**
1112
* @brief s_grid_tile is the minimum tile of the fpga
@@ -73,6 +74,18 @@ class DeviceGrid {
7374
return grid_[tile_loc.layer_num][tile_loc.x][tile_loc.y].height_offset;
7475
}
7576

77+
///@brief Returns a rectangle which represents the bounding box of the tile at the given location.
78+
inline vtr::Rect<int> get_tile_bb(const t_physical_tile_loc& tile_loc) const {
79+
t_physical_tile_type_ptr tile_type = get_physical_type(tile_loc);
80+
81+
int tile_xlow = tile_loc.x - get_width_offset(tile_loc);
82+
int tile_ylow = tile_loc.y - get_height_offset(tile_loc);
83+
int tile_xhigh = tile_xlow + tile_type->width - 1;
84+
int tile_yhigh = tile_ylow + tile_type->height - 1;
85+
86+
return {{tile_xlow, tile_ylow}, {tile_xhigh, tile_yhigh}};
87+
}
88+
7689
///@brief Return the metadata of the tile at the specified location
7790
inline const t_metadata_dict* get_metadata(const t_physical_tile_loc& tile_loc) const {
7891
return grid_[tile_loc.layer_num][tile_loc.x][tile_loc.y].meta;

libs/librrgraph/src/base/check_rr_graph.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "physical_types_util.h"
1010

1111
#include "describe_rr_node.h"
12+
#include "rr_graph_utils.h"
1213

1314
/*********************** Subroutines local to this module *******************/
1415

@@ -389,16 +390,29 @@ void check_rr_node(const RRGraphView& rr_graph,
389390

390391
switch (rr_type) {
391392
case SOURCE:
392-
case SINK:
393393
if (type == nullptr) {
394394
VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
395395
"in check_rr_node: node %d (type %d) is at an illegal clb location (%d, %d).\n", inode, rr_type, xlow, ylow);
396396
}
397+
397398
if (xlow != (xhigh - type->width + 1) || ylow != (yhigh - type->height + 1)) {
398399
VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
399400
"in check_rr_node: node %d (type %d) has endpoints (%d,%d) and (%d,%d)\n", inode, rr_type, xlow, ylow, xhigh, yhigh);
400401
}
401402
break;
403+
case SINK: {
404+
if (type == nullptr) {
405+
VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
406+
"in check_rr_node: node %d (type %d) is at an illegal clb location (%d, %d).\n", inode, rr_type, xlow, ylow);
407+
}
408+
409+
vtr::Rect<int> tile_bb = grid.get_tile_bb({xlow, ylow, layer_num});
410+
if (xlow < tile_bb.xmin() || ylow < tile_bb.ymin() || xhigh > tile_bb.xmax() || yhigh > tile_bb.ymax()) {
411+
VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
412+
"in check_rr_node: node %d (type %d) has endpoints (%d,%d) and (%d,%d), which is outside the bounds of the grid tile containing it.\n", inode, rr_type, xlow, ylow, xhigh, yhigh);
413+
}
414+
break;
415+
}
402416
case IPIN:
403417
case OPIN:
404418
if (type == nullptr) {

libs/librrgraph/src/base/rr_graph_utils.cpp

Lines changed: 141 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,60 @@
1-
2-
/****************************************************************************
3-
* This file include most-utilized functions that manipulate on the
4-
* RRGraph object
5-
***************************************************************************/
61
#include <queue>
72
#include <random>
83

94
#include "rr_graph_utils.h"
10-
115
#include "vpr_error.h"
12-
136
#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+
}
1457

15-
/****************************************************************************
16-
* Find the switches interconnecting two nodes
17-
* Return a vector of switch ids
18-
***************************************************************************/
1958
std::vector<RRSwitchId> find_rr_graph_switches(const RRGraph& rr_graph,
2059
const RRNodeId& from_node,
2160
const RRNodeId& to_node) {
@@ -37,9 +76,6 @@ std::vector<RRSwitchId> find_rr_graph_switches(const RRGraph& rr_graph,
3776
}
3877

3978
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-
4379
if (from_rr_type == CHANX)
4480
return (rr_graph.node_xlow(RRNodeId(to_node)));
4581
else
@@ -48,13 +84,6 @@ int seg_index_of_cblock(const RRGraphView& rr_graph, t_rr_type from_rr_type, int
4884
}
4985

5086
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-
5887
t_rr_type from_rr_type, to_rr_type;
5988

6089
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&
117146
return node_fan_in_list;
118147
}
119148

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+
120240
bool inter_layer_connections_limited_to_opin(const RRGraphView& rr_graph) {
121241
bool limited_to_opin = true;
122242
for (const auto& from_node : rr_graph.nodes()) {

0 commit comments

Comments
 (0)