put GSB builder online

This commit is contained in:
tangxifan 2020-02-11 16:37:14 -07:00
parent e2e115e6f3
commit 1372f748f1
6 changed files with 494 additions and 1 deletions

View File

@ -0,0 +1,395 @@
/********************************************************************
* This file includes functions that are used to annotate device-level
* information, in particular the routing resource graph
*******************************************************************/
/* Headers from vtrutil library */
#include "vtr_time.h"
#include "vtr_assert.h"
#include "vtr_log.h"
/* Headers from openfpgautil library */
#include "openfpga_side_manager.h"
/* Headers from vpr library */
#include "rr_graph_obj_util.h"
#include "annotate_rr_gsb.h"
/* begin namespace openfpga */
namespace openfpga {
/* Build a RRChan Object with the given channel type and coorindators */
static
RRChan build_one_rr_chan(const DeviceContext& vpr_device_ctx,
const t_rr_type& chan_type,
vtr::Point<size_t>& chan_coord) {
std::vector<RRNodeId> chan_rr_nodes;
/* Create a rr_chan object and check if it is unique in the graph */
RRChan rr_chan;
/* Fill the information */
rr_chan.set_type(chan_type);
/* Collect rr_nodes for this channel */
chan_rr_nodes = find_rr_graph_chan_nodes(vpr_device_ctx.rr_graph,
chan_coord.x(), chan_coord.y(),
chan_type);
/* Fill the rr_chan */
for (const RRNodeId& chan_rr_node : chan_rr_nodes) {
rr_chan.add_node(vpr_device_ctx.rr_graph, chan_rr_node,
vpr_device_ctx.rr_graph.node_segment(chan_rr_node));
}
return rr_chan;
}
/* Build a General Switch Block (GSB)
* which includes:
* [I] A Switch Box subckt consists of following ports:
* 1. Channel Y [x][y] inputs
* 2. Channel X [x+1][y] inputs
* 3. Channel Y [x][y-1] outputs
* 4. Channel X [x][y] outputs
* 5. Grid[x][y+1] Right side outputs pins
* 6. Grid[x+1][y+1] Left side output pins
* 7. Grid[x+1][y+1] Bottom side output pins
* 8. Grid[x+1][y] Top side output pins
* 9. Grid[x+1][y] Left side output pins
* 10. Grid[x][y] Right side output pins
* 11. Grid[x][y] Top side output pins
* 12. Grid[x][y+1] Bottom side output pins
*
* -------------- --------------
* | | CBY | |
* | Grid | ChanY | Grid |
* | [x][y+1] | [x][y+1] | [x+1][y+1] |
* | | | |
* -------------- --------------
* ----------
* ChanX & CBX | Switch | ChanX
* [x][y] | Box | [x+1][y]
* | [x][y] |
* ----------
* -------------- --------------
* | | | |
* | Grid | ChanY | Grid |
* | [x][y] | [x][y] | [x+1][y] |
* | | | |
* -------------- --------------
* For channels chanY with INC_DIRECTION on the top side, they should be marked as outputs
* For channels chanY with DEC_DIRECTION on the top side, they should be marked as inputs
* For channels chanY with INC_DIRECTION on the bottom side, they should be marked as inputs
* For channels chanY with DEC_DIRECTION on the bottom side, they should be marked as outputs
* For channels chanX with INC_DIRECTION on the left side, they should be marked as inputs
* For channels chanX with DEC_DIRECTION on the left side, they should be marked as outputs
* For channels chanX with INC_DIRECTION on the right side, they should be marked as outputs
* For channels chanX with DEC_DIRECTION on the right side, they should be marked as inputs
*
* [II] A X-direction Connection Block [x][y]
* The connection block shares the same routing channel[x][y] with the Switch Block
* We just need to fill the ipin nodes at TOP and BOTTOM sides
* as well as properly fill the ipin_grid_side information
* [III] A Y-direction Connection Block [x][y+1]
* The connection block shares the same routing channel[x][y+1] with the Switch Block
* We just need to fill the ipin nodes at LEFT and RIGHT sides
* as well as properly fill the ipin_grid_side information
*/
static
RRGSB build_rr_gsb(const DeviceContext& vpr_device_ctx,
const vtr::Point<size_t>& gsb_range,
const vtr::Point<size_t>& gsb_coord) {
/* Create an object to return */
RRGSB rr_gsb;
VTR_ASSERT(gsb_coord.x() <= gsb_range.x());
VTR_ASSERT(gsb_coord.y() <= gsb_range.y());
/* Coordinator initialization */
rr_gsb.set_coordinate(gsb_coord.x(), gsb_coord.y());
/* Basic information*/
rr_gsb.init_num_sides(4); /* Fixed number of sides */
/* Find all rr_nodes of channels */
/* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */
for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) {
/* Local variables inside this for loop */
SideManager side_manager(side);
vtr::Point<size_t> coordinate = rr_gsb.get_side_block_coordinate(side_manager.get_side());
RRChan rr_chan;
std::vector<std::vector<RRNodeId>> temp_opin_rr_nodes(2);
enum e_side opin_grid_side[2] = {NUM_SIDES, NUM_SIDES};
enum PORTS chan_dir_to_port_dir_mapping[2] = {OUT_PORT, IN_PORT}; /* 0: INC_DIRECTION => ?; 1: DEC_DIRECTION => ? */
switch (side) {
case TOP: /* TOP = 0 */
/* For the border, we should take special care */
if (gsb_coord.y() == gsb_range.y()) {
rr_gsb.clear_one_side(side_manager.get_side());
break;
}
/* Routing channels*/
/* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */
/* Create a rr_chan object and check if it is unique in the graph */
rr_chan = build_one_rr_chan(vpr_device_ctx, CHANY, coordinate);
chan_dir_to_port_dir_mapping[0] = OUT_PORT; /* INC_DIRECTION => OUT_PORT */
chan_dir_to_port_dir_mapping[1] = IN_PORT; /* DEC_DIRECTION => IN_PORT */
/* Build the Switch block: opin and opin_grid_side */
/* Assign grid side of OPIN */
/* Grid[x][y+1] RIGHT side outputs pins */
opin_grid_side[0] = RIGHT;
/* Grid[x+1][y+1] left side outputs pins */
opin_grid_side[1] = LEFT;
/* Include Grid[x][y+1] RIGHT side outputs pins */
temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes(vpr_device_ctx.rr_graph, vpr_device_ctx.grid,
gsb_coord.x(), gsb_coord.y() + 1, OPIN, opin_grid_side[0]);
/* Include Grid[x+1][y+1] Left side output pins */
temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes(vpr_device_ctx.rr_graph, vpr_device_ctx.grid,
gsb_coord.x() + 1, gsb_coord.y() + 1, OPIN, opin_grid_side[1]);
break;
case RIGHT: /* RIGHT = 1 */
/* For the border, we should take special care */
if (gsb_coord.x() == gsb_range.x()) {
rr_gsb.clear_one_side(side_manager.get_side());
break;
}
/* Routing channels*/
/* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */
/* Collect rr_nodes for Tracks for top: chany[x][y+1] */
/* Create a rr_chan object and check if it is unique in the graph */
rr_chan = build_one_rr_chan(vpr_device_ctx, CHANX, coordinate);
chan_dir_to_port_dir_mapping[0] = OUT_PORT; /* INC_DIRECTION => OUT_PORT */
chan_dir_to_port_dir_mapping[1] = IN_PORT; /* DEC_DIRECTION => IN_PORT */
/* Build the Switch block: opin and opin_grid_side */
/* Assign grid side of OPIN */
/* Grid[x+1][y+1] BOTTOM side outputs pins */
opin_grid_side[0] = BOTTOM;
/* Grid[x+1][y] TOP side outputs pins */
opin_grid_side[1] = TOP;
/* include Grid[x+1][y+1] Bottom side output pins */
temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes(vpr_device_ctx.rr_graph, vpr_device_ctx.grid,
gsb_coord.x() + 1, gsb_coord.y() + 1, OPIN, opin_grid_side[0]);
/* include Grid[x+1][y] Top side output pins */
temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes(vpr_device_ctx.rr_graph, vpr_device_ctx.grid,
gsb_coord.x() + 1, gsb_coord.y(), OPIN, opin_grid_side[1]);
break;
case BOTTOM: /* BOTTOM = 2*/
/* For the border, we should take special care */
if (gsb_coord.y() == 0) {
rr_gsb.clear_one_side(side_manager.get_side());
break;
}
/* Routing channels*/
/* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */
/* Collect rr_nodes for Tracks for bottom: chany[x][y] */
/* Create a rr_chan object and check if it is unique in the graph */
rr_chan = build_one_rr_chan(vpr_device_ctx, CHANY, coordinate);
chan_dir_to_port_dir_mapping[0] = IN_PORT; /* INC_DIRECTION => IN_PORT */
chan_dir_to_port_dir_mapping[1] = OUT_PORT; /* DEC_DIRECTION => OUT_PORT */
/* Build the Switch block: opin and opin_grid_side */
/* Assign grid side of OPIN */
/* Grid[x+1][y] LEFT side outputs pins */
opin_grid_side[0] = LEFT;
/* Grid[x][y] RIGHT side outputs pins */
opin_grid_side[1] = RIGHT;
/* include Grid[x+1][y] Left side output pins */
temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes(vpr_device_ctx.rr_graph, vpr_device_ctx.grid,
gsb_coord.x() + 1, gsb_coord.y(), OPIN, opin_grid_side[0]);
/* include Grid[x][y] Right side output pins */
temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes(vpr_device_ctx.rr_graph, vpr_device_ctx.grid,
gsb_coord.x(), gsb_coord.y(), OPIN, opin_grid_side[1]);
break;
case LEFT: /* LEFT = 3 */
/* For the border, we should take special care */
if (gsb_coord.x() == 0) {
rr_gsb.clear_one_side(side_manager.get_side());
break;
}
/* Routing channels*/
/* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */
/* Collect rr_nodes for Tracks for left: chanx[x][y] */
/* Create a rr_chan object and check if it is unique in the graph */
rr_chan = build_one_rr_chan(vpr_device_ctx, CHANX, coordinate);
chan_dir_to_port_dir_mapping[0] = IN_PORT; /* INC_DIRECTION => IN_PORT */
chan_dir_to_port_dir_mapping[1] = OUT_PORT; /* DEC_DIRECTION => OUT_PORT */
/* Build the Switch block: opin and opin_grid_side */
/* Grid[x][y+1] BOTTOM side outputs pins */
opin_grid_side[0] = BOTTOM;
/* Grid[x][y] TOP side outputs pins */
opin_grid_side[1] = TOP;
/* include Grid[x][y+1] Bottom side outputs pins */
temp_opin_rr_nodes[0] = find_rr_graph_grid_nodes(vpr_device_ctx.rr_graph, vpr_device_ctx.grid,
gsb_coord.x(), gsb_coord.y() + 1, OPIN, opin_grid_side[0]);
/* include Grid[x][y] Top side output pins */
temp_opin_rr_nodes[1] = find_rr_graph_grid_nodes(vpr_device_ctx.rr_graph, vpr_device_ctx.grid,
gsb_coord.x(), gsb_coord.y(), OPIN, opin_grid_side[1]);
break;
default:
VTR_LOG_ERROR("Invalid side index!\n");
exit(1);
}
/* Organize a vector of port direction */
if (0 < rr_chan.get_chan_width()) {
std::vector<enum PORTS> rr_chan_dir;
rr_chan_dir.resize(rr_chan.get_chan_width());
for (size_t itrack = 0; itrack < rr_chan.get_chan_width(); ++itrack) {
/* Identify the directionality, record it in rr_node_direction */
if (INC_DIRECTION == vpr_device_ctx.rr_graph.node_direction(rr_chan.get_node(itrack))) {
rr_chan_dir[itrack] = chan_dir_to_port_dir_mapping[0];
} else {
VTR_ASSERT(DEC_DIRECTION == vpr_device_ctx.rr_graph.node_direction(rr_chan.get_node(itrack)));
rr_chan_dir[itrack] = chan_dir_to_port_dir_mapping[1];
}
}
/* Fill chan_rr_nodes */
rr_gsb.add_chan_node(side_manager.get_side(), rr_chan, rr_chan_dir);
}
/* Fill opin_rr_nodes */
/* Copy from temp_opin_rr_node to opin_rr_node */
for (const RRNodeId& inode : temp_opin_rr_nodes[0]) {
/* Grid[x+1][y+1] Bottom side outputs pins */
rr_gsb.add_opin_node(inode, side_manager.get_side());
}
for (const RRNodeId& inode : temp_opin_rr_nodes[1]) {
/* Grid[x+1][y] TOP side outputs pins */
rr_gsb.add_opin_node(inode, side_manager.get_side());
}
/* Clean ipin_rr_nodes */
/* We do not have any IPIN for a Switch Block */
rr_gsb.clear_ipin_nodes(side_manager.get_side());
/* Clear the temp data */
temp_opin_rr_nodes[0].clear();
temp_opin_rr_nodes[1].clear();
opin_grid_side[0] = NUM_SIDES;
opin_grid_side[1] = NUM_SIDES;
}
/* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */
for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) {
/* Local variables inside this for loop */
SideManager side_manager(side);
size_t ix;
size_t iy;
enum e_side chan_side;
std::vector<RRNodeId> temp_ipin_rr_nodes;
enum e_side ipin_rr_node_grid_side;
switch (side) {
case TOP: /* TOP = 0 */
/* For the bording, we should take special care */
/* Check if left side chan width is 0 or not */
chan_side = LEFT;
/* Build the connection block: ipin and ipin_grid_side */
/* BOTTOM side INPUT Pins of Grid[x][y+1] */
ix = rr_gsb.get_sb_x();
iy = rr_gsb.get_sb_y() + 1;
ipin_rr_node_grid_side = BOTTOM;
break;
case RIGHT: /* RIGHT = 1 */
/* For the bording, we should take special care */
/* Check if TOP side chan width is 0 or not */
chan_side = TOP;
/* Build the connection block: ipin and ipin_grid_side */
/* LEFT side INPUT Pins of Grid[x+1][y+1] */
ix = rr_gsb.get_sb_x() + 1;
iy = rr_gsb.get_sb_y() + 1;
ipin_rr_node_grid_side = LEFT;
break;
case BOTTOM: /* BOTTOM = 2*/
/* For the bording, we should take special care */
/* Check if left side chan width is 0 or not */
chan_side = LEFT;
/* Build the connection block: ipin and ipin_grid_side */
/* TOP side INPUT Pins of Grid[x][y] */
ix = rr_gsb.get_sb_x();
iy = rr_gsb.get_sb_y();
ipin_rr_node_grid_side = TOP;
break;
case LEFT: /* LEFT = 3 */
/* For the bording, we should take special care */
/* Check if left side chan width is 0 or not */
chan_side = TOP;
/* Build the connection block: ipin and ipin_grid_side */
/* RIGHT side INPUT Pins of Grid[x][y+1] */
ix = rr_gsb.get_sb_x();
iy = rr_gsb.get_sb_y() + 1;
ipin_rr_node_grid_side = RIGHT;
break;
default:
VTR_LOG_ERROR("Invalid side index!\n");
exit(1);
}
/* If there is no channel at this side, we skip ipin_node annotation */
if (0 == rr_gsb.get_chan_width(chan_side)) {
continue;
}
/* Collect IPIN rr_nodes*/
temp_ipin_rr_nodes = find_rr_graph_grid_nodes(vpr_device_ctx.rr_graph, vpr_device_ctx.grid,
ix, iy, IPIN, ipin_rr_node_grid_side);
/* Fill the ipin nodes of RRGSB */
for (const RRNodeId& inode : temp_ipin_rr_nodes) {
rr_gsb.add_ipin_node(inode, side_manager.get_side());
}
/* Clear the temp data */
temp_ipin_rr_nodes.clear();
}
return rr_gsb;
}
/********************************************************************
* Build the annotation for the routing resource graph
* by collecting the nodes to the General Switch Block context
*******************************************************************/
void annotate_device_rr_gsb(const DeviceContext& vpr_device_ctx,
DeviceRRGSB& device_rr_gsb,
const bool& verbose_output) {
vtr::ScopedStartFinishTimer timer("Build General Switch Block(GSB) annotation on top of routing resource graph");
/* Note that the GSB array is smaller than the grids by 1 column and 1 row!!! */
vtr::Point<size_t> gsb_range(vpr_device_ctx.grid.width() - 1, vpr_device_ctx.grid.height() - 1);
device_rr_gsb.reserve(gsb_range);
VTR_LOGV(verbose_output,
"Start annotation GSB up to [%lu][%lu]\n",
gsb_range.x(), gsb_range.y());
size_t gsb_cnt = 0;
/* For each switch block, determine the size of array */
for (size_t ix = 0; ix < gsb_range.x(); ++ix) {
for (size_t iy = 0; iy < gsb_range.y(); ++iy) {
/* Here we give the builder the fringe coordinates so that it can handle the GSBs at the borderside correctly */
const RRGSB& rr_gsb = build_rr_gsb(vpr_device_ctx,
vtr::Point<size_t>(vpr_device_ctx.grid.width() - 2, vpr_device_ctx.grid.height() - 2),
vtr::Point<size_t>(ix, iy));
/* TODO: sort drive_rr_nodes should be done when building the tileable rr_graph? */
//sort_rr_gsb_drive_rr_nodes(rr_gsb);
/* Add to device_rr_gsb */
vtr::Point<size_t> gsb_coordinate = rr_gsb.get_sb_coordinate();
device_rr_gsb.add_rr_gsb(gsb_coordinate, rr_gsb);
gsb_cnt++; /* Update counter */
/* Print info */
VTR_LOG("[%lu%] Backannotated GSB[%lu][%lu]\r",
100 * gsb_cnt / (gsb_range.x() * gsb_range.y()),
ix, iy);
}
}
/* Report number of unique mirrors */
VTR_LOG("Backannotated %d General Switch Blocks (GSBs).\n",
gsb_range.x() * gsb_range.y());
}
} /* end namespace openfpga */

View File

@ -0,0 +1,24 @@
#ifndef ANNOTATE_RR_GSB_H
#define ANNOTATE_RR_GSB_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include "vpr_context.h"
#include "openfpga_context.h"
#include "device_rr_gsb.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
void annotate_device_rr_gsb(const DeviceContext& vpr_device_ctx,
DeviceRRGSB& device_rr_gsb,
const bool& verbose_output);
} /* end namespace openfpga */
#endif

View File

@ -7,6 +7,7 @@
#include "vpr_pb_type_annotation.h"
#include "vpr_clustering_annotation.h"
#include "vpr_routing_annotation.h"
#include "device_rr_gsb.h"
/********************************************************************
* This file includes the declaration of the date structure
@ -42,22 +43,32 @@ class OpenfpgaContext : public Context {
const openfpga::VprNetlistAnnotation& vpr_netlist_annotation() const { return vpr_netlist_annotation_; }
const openfpga::VprClusteringAnnotation& vpr_clustering_annotation() const { return vpr_clustering_annotation_; }
const openfpga::VprRoutingAnnotation& vpr_routing_annotation() const { return vpr_routing_annotation_; }
const openfpga::DeviceRRGSB& device_rr_gsb() const { return device_rr_gsb_; }
public: /* Public mutators */
openfpga::Arch& mutable_arch() { return arch_; }
openfpga::VprPbTypeAnnotation& mutable_vpr_pb_type_annotation() { return vpr_pb_type_annotation_; }
openfpga::VprNetlistAnnotation& mutable_vpr_netlist_annotation() { return vpr_netlist_annotation_; }
openfpga::VprClusteringAnnotation& mutable_vpr_clustering_annotation() { return vpr_clustering_annotation_; }
openfpga::VprRoutingAnnotation& mutable_vpr_routing_annotation() { return vpr_routing_annotation_; }
openfpga::DeviceRRGSB& mutable_device_rr_gsb() { return device_rr_gsb_; }
private: /* Internal data */
/* Data structure to store information from read_openfpga_arch library */
openfpga::Arch arch_;
/* Annotation to pb_type of VPR */
openfpga::VprPbTypeAnnotation vpr_pb_type_annotation_;
/* Naming fix to netlist */
openfpga::VprNetlistAnnotation vpr_netlist_annotation_;
/* TODO: Pin net fix to cluster results */
openfpga::VprClusteringAnnotation vpr_clustering_annotation_;
/* Routing results annotation */
openfpga::VprRoutingAnnotation vpr_routing_annotation_;
/* Device-level annotation */
openfpga::DeviceRRGSB device_rr_gsb_;
};
#endif

View File

@ -12,6 +12,7 @@
#include "annotate_pb_types.h"
#include "annotate_pb_graph.h"
#include "annotate_routing.h"
#include "annotate_rr_gsb.h"
#include "openfpga_link_arch.h"
/* Include global variables of VPR */
@ -60,6 +61,14 @@ void link_arch(OpenfpgaContext& openfpga_context,
annotate_rr_node_nets(g_vpr_ctx.device(), g_vpr_ctx.clustering(), g_vpr_ctx.routing(),
openfpga_context.mutable_vpr_routing_annotation(),
cmd_context.option_enable(cmd, opt_verbose));
/* Build the routing graph annotation
* - RRGSB
* - DeviceRRGSB
*/
annotate_device_rr_gsb(g_vpr_ctx.device(),
openfpga_context.mutable_device_rr_gsb(),
cmd_context.option_enable(cmd, opt_verbose));
}
} /* end namespace openfpga */

View File

@ -32,7 +32,7 @@ std::vector<RRSwitchId> find_rr_graph_switches(const RRGraph& rr_graph,
/*********************************************************************
* Like the RRGraph.find_node() but returns all matching nodes,
* rather than just the first. This is particularly useful for getting all instances
* of a specific IPIN/OPIN at a specific gird tile (x,y) location.
* of a specific IPIN/OPIN at a specific grid tile (x,y) location.
**********************************************************************/
std::vector<RRNodeId> find_rr_graph_nodes(const RRGraph& rr_graph,
const int& x,
@ -63,6 +63,9 @@ std::vector<RRNodeId> find_rr_graph_nodes(const RRGraph& rr_graph,
return indices;
}
/*********************************************************************
* Find a list of rr nodes in a routing channel at (x,y)
**********************************************************************/
std::vector<RRNodeId> find_rr_graph_chan_nodes(const RRGraph& rr_graph,
const int& x,
const int& y,
@ -81,3 +84,46 @@ std::vector<RRNodeId> find_rr_graph_chan_nodes(const RRGraph& rr_graph,
return indices;
}
/*********************************************************************
* Find a list of rr_nodes that locate at a side of a grid
**********************************************************************/
std::vector<RRNodeId> find_rr_graph_grid_nodes(const RRGraph& rr_graph,
const DeviceGrid& device_grid,
const int& x,
const int& y,
const t_rr_type& rr_type,
const e_side& side) {
std::vector<RRNodeId> indices;
VTR_ASSERT(rr_type == IPIN || rr_type == OPIN);
/* Ensure that (x, y) is a valid location in grids */
VTR_ASSERT(size_t(x) <= device_grid.width() && size_t(y) <= device_grid.height());
/* Ensure we have a valid side */
VTR_ASSERT(side != NUM_SIDES);
/* Find all the pins on the side of the grid */
int width_offset = device_grid[x][y].width_offset;
int height_offset = device_grid[x][y].height_offset;
for (int pin = 0; pin < device_grid[x][y].type->num_pins; ++pin) {
/* Skip those pins have been ignored during rr_graph build-up */
if (true == device_grid[x][y].type->is_ignored_pin[pin]) {
continue;
}
if (false == device_grid[x][y].type->pinloc[width_offset][height_offset][side][pin]) {
/* Not the pin on this side, we skip */
continue;
}
/* Try to find the rr node */
RRNodeId rr_node_index = rr_graph.find_node(x, y, rr_type, pin, side);
if (rr_node_index != RRNodeId::INVALID()) {
indices.push_back(rr_node_index);
}
}
return indices;
}

View File

@ -6,6 +6,7 @@
*/
#include <vector>
#include "rr_graph_obj.h"
#include "device_grid.h"
/* Get node-to-node switches in a RRGraph */
std::vector<RRSwitchId> find_rr_graph_switches(const RRGraph& rr_graph,
@ -23,5 +24,12 @@ std::vector<RRNodeId> find_rr_graph_chan_nodes(const RRGraph& rr_graph,
const int& y,
const t_rr_type& rr_type);
std::vector<RRNodeId> find_rr_graph_grid_nodes(const RRGraph& rr_graph,
const DeviceGrid& device_grid,
const int& x,
const int& y,
const t_rr_type& rr_type,
const e_side& side);
#endif