Skip to content

Commit

Permalink
Merge pull request #2639 from nedsels/improve_map_lookahead
Browse files Browse the repository at this point in the history
Improve SINK Node Locations
  • Loading branch information
vaughnbetz authored Jul 23, 2024
2 parents fca017a + bca753e commit 3f2b9e8
Show file tree
Hide file tree
Showing 34 changed files with 1,006 additions and 571 deletions.
10 changes: 10 additions & 0 deletions doc/src/api/vpr/grid.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
========
Grid
========

DeviceGrid
-------

.. doxygenclass:: DeviceGrid
:project: vpr
:members:
1 change: 1 addition & 0 deletions doc/src/api/vpr/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ VPR API
:maxdepth: 1

contexts
grid
mapping
netlist
route_tree
Expand Down
6 changes: 6 additions & 0 deletions doc/src/api/vpr/rr_graph.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,9 @@ RRSpatialLookup
:project: librrgraph
:members:

rr_graph_utils
---------------

.. doxygenfile:: rr_graph_utils.h
:project: librrgraph
:sections: briefdescription detaileddescription func prototype user-defined public-func
35 changes: 35 additions & 0 deletions doc/src/api/vprinternals/router_lookahead.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
==============
Router Lookahead
==============

e_router_lookahead
----------
.. doxygenenum:: e_router_lookahead
:project: vpr


RouterLookahead
----------
.. doxygenclass:: RouterLookahead
:project: vpr
:members:

MapLookahead
----------
.. doxygenclass:: MapLookahead
:project: vpr

make_router_lookahead
----------
.. doxygenfunction:: make_router_lookahead
:project: vpr

get_cached_router_lookahead
----------
.. doxygenfunction:: get_cached_router_lookahead
:project: vpr

invalidate_router_lookahead_cache
----------
.. doxygenfunction:: invalidate_router_lookahead_cache
:project: vpr
3 changes: 2 additions & 1 deletion doc/src/api/vprinternals/vpr_router.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ VPR Router
.. toctree::
:maxdepth: 1

router_heap
router_heap
router_lookahead
13 changes: 13 additions & 0 deletions libs/libarchfpga/src/device_grid.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <cmath>
#include "vtr_ndmatrix.h"
#include "physical_types.h"
#include "vtr_geometry.h"

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

///@brief Returns a rectangle which represents the bounding box of the tile at the given location.
inline vtr::Rect<int> get_tile_bb(const t_physical_tile_loc& tile_loc) const {
t_physical_tile_type_ptr tile_type = get_physical_type(tile_loc);

int tile_xlow = tile_loc.x - get_width_offset(tile_loc);
int tile_ylow = tile_loc.y - get_height_offset(tile_loc);
int tile_xhigh = tile_xlow + tile_type->width - 1;
int tile_yhigh = tile_ylow + tile_type->height - 1;

return {{tile_xlow, tile_ylow}, {tile_xhigh, tile_yhigh}};
}

///@brief Return the metadata of the tile at the specified location
inline const t_metadata_dict* get_metadata(const t_physical_tile_loc& tile_loc) const {
return grid_[tile_loc.layer_num][tile_loc.x][tile_loc.y].meta;
Expand Down
16 changes: 15 additions & 1 deletion libs/librrgraph/src/base/check_rr_graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "physical_types_util.h"

#include "describe_rr_node.h"
#include "rr_graph_utils.h"

/*********************** Subroutines local to this module *******************/

Expand Down Expand Up @@ -389,16 +390,29 @@ void check_rr_node(const RRGraphView& rr_graph,

switch (rr_type) {
case SOURCE:
case SINK:
if (type == nullptr) {
VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
"in check_rr_node: node %d (type %d) is at an illegal clb location (%d, %d).\n", inode, rr_type, xlow, ylow);
}

if (xlow != (xhigh - type->width + 1) || ylow != (yhigh - type->height + 1)) {
VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
"in check_rr_node: node %d (type %d) has endpoints (%d,%d) and (%d,%d)\n", inode, rr_type, xlow, ylow, xhigh, yhigh);
}
break;
case SINK: {
if (type == nullptr) {
VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
"in check_rr_node: node %d (type %d) is at an illegal clb location (%d, %d).\n", inode, rr_type, xlow, ylow);
}

vtr::Rect<int> tile_bb = grid.get_tile_bb({xlow, ylow, layer_num});
if (xlow < tile_bb.xmin() || ylow < tile_bb.ymin() || xhigh > tile_bb.xmax() || yhigh > tile_bb.ymax()) {
VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
"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);
}
break;
}
case IPIN:
case OPIN:
if (type == nullptr) {
Expand Down
162 changes: 141 additions & 21 deletions libs/librrgraph/src/base/rr_graph_utils.cpp
Original file line number Diff line number Diff line change
@@ -1,21 +1,60 @@

/****************************************************************************
* This file include most-utilized functions that manipulate on the
* RRGraph object
***************************************************************************/
#include <queue>
#include <random>

#include "rr_graph_utils.h"

#include "vpr_error.h"

#include "rr_graph_obj.h"
#include "rr_graph_builder.h"

/*
* @brief Walk backwards from origin SINK, and insert all cluster-edge IPINs to which origin is connected to sink_ipins
*
* @param rr_graph
* @param fanins A vector where, at each node index, is a vector of edges which are fanins of that node
* @param sink_ipins The set in which cluster-edge IPINs will be collected; should be empty
* @param curr The current node in recursion; originally, should be the same as origin
* @param origin The SINK whose cluster-edge IPINs are to be collected
*/
static void rr_walk_cluster_recursive(const RRGraphView& rr_graph,
const vtr::vector<RRNodeId, std::vector<RREdgeId>>& fanins,
std::unordered_set<RRNodeId>& sink_ipins,
const RRNodeId curr,
const RRNodeId origin);

static void rr_walk_cluster_recursive(const RRGraphView& rr_graph,
const vtr::vector<RRNodeId, std::vector<RREdgeId>>& fanins,
std::unordered_set<RRNodeId>& sink_ipins,
const RRNodeId curr,
const RRNodeId origin) {
// Make sure SINK in the same cluster as origin
int curr_x = rr_graph.node_xlow(curr);
int curr_y = rr_graph.node_ylow(curr);
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)))
return;

VTR_ASSERT_SAFE(rr_graph.node_type(origin) == e_rr_type::SINK);

// We want to go "backward" to the cluster IPINs connected to the origin node
const std::vector<RREdgeId>& incoming_edges = fanins[curr];
for (RREdgeId edge : incoming_edges) {
RRNodeId parent = rr_graph.edge_src_node(edge);
VTR_ASSERT_SAFE(parent != RRNodeId::INVALID());

if (rr_graph.node_type(parent) != e_rr_type::IPIN) {
if (rr_graph.node_type(parent) != e_rr_type::CHANX && rr_graph.node_type(parent) != e_rr_type::CHANY)
return;

// If the parent node isn't in the origin's cluster, the current node is a "cluster-edge" pin,
// so add it to sink_ipins
sink_ipins.insert(curr);
return;
}

// If the parent node is intra-cluster, keep going "backward"
rr_walk_cluster_recursive(rr_graph, fanins, sink_ipins, parent, origin);
}
}

/****************************************************************************
* Find the switches interconnecting two nodes
* Return a vector of switch ids
***************************************************************************/
std::vector<RRSwitchId> find_rr_graph_switches(const RRGraph& rr_graph,
const RRNodeId& from_node,
const RRNodeId& to_node) {
Expand All @@ -37,9 +76,6 @@ std::vector<RRSwitchId> find_rr_graph_switches(const RRGraph& rr_graph,
}

int seg_index_of_cblock(const RRGraphView& rr_graph, t_rr_type from_rr_type, int to_node) {
/* Returns the segment number (distance along the channel) of the connection *
* box from from_rr_type (CHANX or CHANY) to to_node (IPIN). */

if (from_rr_type == CHANX)
return (rr_graph.node_xlow(RRNodeId(to_node)));
else
Expand All @@ -48,13 +84,6 @@ int seg_index_of_cblock(const RRGraphView& rr_graph, t_rr_type from_rr_type, int
}

int seg_index_of_sblock(const RRGraphView& rr_graph, int from_node, int to_node) {
/* Returns the segment number (distance along the channel) of the switch box *
* box from from_node (CHANX or CHANY) to to_node (CHANX or CHANY). The *
* switch box on the left side of a CHANX segment at (i,j) has seg_index = *
* i-1, while the switch box on the right side of that segment has seg_index *
* = i. CHANY stuff works similarly. Hence the range of values returned is *
* 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). */

t_rr_type from_rr_type, to_rr_type;

from_rr_type = rr_graph.node_type(RRNodeId(from_node));
Expand Down Expand Up @@ -117,6 +146,97 @@ vtr::vector<RRNodeId, std::vector<RREdgeId>> get_fan_in_list(const RRGraphView&
return node_fan_in_list;
}

void rr_set_sink_locs(const RRGraphView& rr_graph, RRGraphBuilder& rr_graph_builder, const DeviceGrid& grid) {
const vtr::vector<RRNodeId, std::vector<RREdgeId>> node_fanins = get_fan_in_list(rr_graph);

// Keep track of offsets for SINKs for each tile type, to avoid repeated calculations
std::unordered_map<t_physical_tile_type_ptr, std::unordered_map<int, vtr::Point<int>>> physical_type_offsets;

// Iterate over all SINK nodes
for (size_t node = 0; node < rr_graph.num_nodes(); ++node) {
auto node_id = RRNodeId(node);

if (rr_graph.node_type((RRNodeId)node_id) != e_rr_type::SINK)
continue;

int node_xlow = rr_graph.node_xlow(node_id);
int node_ylow = rr_graph.node_ylow(node_id);
int node_xhigh = rr_graph.node_xhigh(node_id);
int node_yhigh = rr_graph.node_yhigh(node_id);

// Skip "0x0" nodes; either the tile is 1x1, or we have seen the node on a previous call of this function
// and its new location has already been set
if ((node_xhigh - node_xlow) == 0 && (node_yhigh - node_ylow) == 0)
continue;

int node_layer = rr_graph.node_layer(node_id);
int node_ptc = rr_graph.node_ptc_num(node_id);

t_physical_tile_loc tile_loc = {node_xlow, node_ylow, node_layer};
t_physical_tile_type_ptr tile_type = grid.get_physical_type(tile_loc);
vtr::Rect<int> tile_bb = grid.get_tile_bb(tile_loc);

// See if we have encountered this tile type/ptc combo before, and used saved offset if so
vtr::Point<int> new_loc(-1, -1);
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())) {
new_loc = tile_bb.bottom_left() + physical_type_offsets[tile_type].at(node_ptc);
} else { /* We have not seen this tile type/ptc combo before */
// The IPINs of the current SINK node
std::unordered_set<RRNodeId> sink_ipins = {};
rr_walk_cluster_recursive(rr_graph, node_fanins, sink_ipins, node_id, node_id);

/* Set SINK locations as average of collected IPINs */

if (sink_ipins.empty())
continue;

// Use float so that we can take average later
std::vector<float> x_coords;
std::vector<float> y_coords;

// Add coordinates of each "cluster-edge" pin to vectors
for (const auto& pin : sink_ipins) {
int pin_x = rr_graph.node_xlow(pin);
int pin_y = rr_graph.node_ylow(pin);

VTR_ASSERT_SAFE(pin_x == rr_graph.node_xhigh(pin));
VTR_ASSERT_SAFE(pin_y == rr_graph.node_yhigh(pin));

x_coords.push_back((float)pin_x);
y_coords.push_back((float)pin_y);
}

new_loc = {(int)round(std::accumulate(x_coords.begin(), x_coords.end(), 0.f) / (double)x_coords.size()),
(int)round(std::accumulate(y_coords.begin(), y_coords.end(), 0.f) / (double)y_coords.size())};

// Save offset for this tile/ptc combo
if (physical_type_offsets.find(tile_type) == physical_type_offsets.end())
physical_type_offsets[tile_type] = {};

physical_type_offsets[tile_type].insert({node_ptc, new_loc - tile_bb.bottom_left()});
}

// Remove old locations from lookup
VTR_ASSERT(rr_graph_builder.node_lookup().find_node(node_layer, new_loc.x(), new_loc.y(), SINK, node_ptc) != RRNodeId::INVALID());

for (int x = tile_bb.xmin(); x <= tile_bb.xmax(); ++x) {
for (int y = tile_bb.ymin(); y <= tile_bb.ymax(); ++y) {
if (x == new_loc.x() && y == new_loc.y()) /* The new sink location */
continue;

if (rr_graph_builder.node_lookup().find_node(node_layer, x, y, SINK, node_ptc) == RRNodeId::INVALID()) /* Already removed */
continue;

bool removed_successfully = rr_graph_builder.node_lookup().remove_node(node_id, node_layer, x, y, SINK, node_ptc);
VTR_ASSERT(removed_successfully);
}
}

// Set new coordinates
rr_graph_builder.set_node_coordinates(node_id, (short)new_loc.x(), (short)new_loc.y(), (short)new_loc.x(), (short)new_loc.y());
}
}

bool inter_layer_connections_limited_to_opin(const RRGraphView& rr_graph) {
bool limited_to_opin = true;
for (const auto& from_node : rr_graph.nodes()) {
Expand Down
Loading

0 comments on commit 3f2b9e8

Please sign in to comment.