keep debugging rr_graph builder
This commit is contained in:
parent
15167c9bfb
commit
6881863506
|
@ -65,24 +65,10 @@ short RRGraph::node_ylow(const RRNodeId& node) const {
|
|||
}
|
||||
|
||||
short RRGraph::node_xhigh(const RRNodeId& node) const {
|
||||
/* Special for SOURCE and SINK node, we always return the xlow
|
||||
* This is due to the convention in creating RRGraph
|
||||
* so that we can guarantee unique SOURCE/SINK nodes searching
|
||||
if ( (SOURCE == node_type(node))
|
||||
|| (SINK == node_type(node)) ) {
|
||||
return node_bounding_box(node).xmin();
|
||||
}
|
||||
*/
|
||||
return node_bounding_box(node).xmax();
|
||||
}
|
||||
|
||||
short RRGraph::node_yhigh(const RRNodeId& node) const {
|
||||
/*
|
||||
if ( (SOURCE == node_type(node))
|
||||
|| (SINK == node_type(node)) ) {
|
||||
return node_bounding_box(node).ymin();
|
||||
}
|
||||
*/
|
||||
return node_bounding_box(node).ymax();
|
||||
}
|
||||
|
||||
|
@ -966,6 +952,12 @@ void RRGraph::remove_edge(const RREdgeId& edge) {
|
|||
set_dirty();
|
||||
}
|
||||
|
||||
void RRGraph::set_node_type(const RRNodeId& node, const t_rr_type& type) {
|
||||
VTR_ASSERT(valid_node_id(node));
|
||||
|
||||
node_types_[node] = type;
|
||||
}
|
||||
|
||||
void RRGraph::set_node_xlow(const RRNodeId& node, const short& xlow) {
|
||||
VTR_ASSERT(valid_node_id(node));
|
||||
|
||||
|
@ -1228,30 +1220,9 @@ void RRGraph::build_fast_node_lookup() const {
|
|||
/* Special for SOURCE and SINK, we should annotate in the look-up
|
||||
* for all the (x,y) upto (xhigh, yhigh)
|
||||
*/
|
||||
std::vector<size_t> xlows;
|
||||
std::vector<size_t> ylows;
|
||||
size_t x = node_xlow(node);
|
||||
size_t y = node_ylow(node);
|
||||
|
||||
/*
|
||||
if ( (SOURCE == node_type(node))
|
||||
|| (SINK == node_type(node))
|
||||
|| (CHANX == node_type(node))
|
||||
|| (CHANY == node_type(node)) ) {
|
||||
xlows.resize(node_bounding_boxes_[node].xmax() - node_bounding_boxes_[node].xmin() + 1);
|
||||
ylows.resize(node_bounding_boxes_[node].ymax() - node_bounding_boxes_[node].ymin() + 1);
|
||||
std::iota(xlows.begin(), xlows.end(), node_xlow(node));
|
||||
std::iota(ylows.begin(), ylows.end(), node_ylow(node));
|
||||
VTR_ASSERT(size_t(node_bounding_boxes_[node].xmax()) == xlows.back());
|
||||
VTR_ASSERT(size_t(node_bounding_boxes_[node].ymax()) == ylows.back());
|
||||
} else {
|
||||
*/
|
||||
xlows.push_back(node_xlow(node));
|
||||
ylows.push_back(node_ylow(node));
|
||||
/*
|
||||
}
|
||||
*/
|
||||
|
||||
for (size_t x : xlows) {
|
||||
for (size_t y : ylows) {
|
||||
size_t itype = node_type(node);
|
||||
|
||||
size_t ptc = node_ptc_num(node);
|
||||
|
@ -1273,8 +1244,6 @@ void RRGraph::build_fast_node_lookup() const {
|
|||
//Save node in lookup
|
||||
node_lookup_[x][y][itype][ptc][iside] = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RRGraph::invalidate_fast_node_lookup() const {
|
||||
|
|
|
@ -646,6 +646,8 @@ class RRGraph {
|
|||
void remove_edge(const RREdgeId& edge);
|
||||
|
||||
/* Set node-level information */
|
||||
void set_node_type(const RRNodeId& node, const t_rr_type& type);
|
||||
|
||||
void set_node_xlow(const RRNodeId& node, const short& xlow);
|
||||
void set_node_ylow(const RRNodeId& node, const short& ylow);
|
||||
void set_node_xhigh(const RRNodeId& node, const short& xhigh);
|
||||
|
|
|
@ -153,8 +153,7 @@ static int get_opin_direct_connections(int x,
|
|||
const int num_directs,
|
||||
const t_clb_to_clb_directs* clb_to_clb_directs);
|
||||
|
||||
static void alloc_and_load_rr_graph(const int num_nodes,
|
||||
RRGraph& rr_graph,
|
||||
static void alloc_and_load_rr_graph(RRGraph& rr_graph,
|
||||
const int num_seg_types,
|
||||
const t_chan_details& chan_details_x,
|
||||
const t_chan_details& chan_details_y,
|
||||
|
@ -599,11 +598,20 @@ static void build_rr_graph(const t_graph_type graph_type,
|
|||
int num_rr_nodes = 0;
|
||||
|
||||
/* Xifan Tang -
|
||||
* We create all the nodes in the RRGraph object here
|
||||
* Reuse the legacy rr_node indice because it has many out-of-law exceptions during the graph building
|
||||
* which is not allowed by RRGraph object
|
||||
*/
|
||||
device_ctx.rr_graph = alloc_and_load_rr_node_indices(max_chan_width, grid,
|
||||
t_rr_node_indices L_rr_node_indices = alloc_and_load_rr_node_indices(max_chan_width, grid,
|
||||
&num_rr_nodes, chan_details_x, chan_details_y);
|
||||
|
||||
/* Allocate the nodes in RR Graph */
|
||||
device_ctx.rr_graph.reserve_nodes(num_rr_nodes);
|
||||
for (int i = 0; i < num_rr_nodes; ++i) {
|
||||
/* Give a fake node type, will be corrected later in the builder */
|
||||
device_ctx.rr_graph.create_node(SOURCE);
|
||||
}
|
||||
|
||||
|
||||
/* The number of segments are in general small, reserve segments may not bring
|
||||
* significant memory efficiency */
|
||||
device_ctx.rr_graph.reserve_segments(segment_inf.size());
|
||||
|
@ -723,11 +731,11 @@ static void build_rr_graph(const t_graph_type graph_type,
|
|||
device_ctx.rr_graph.create_switch(temp_rr_switch);
|
||||
}
|
||||
|
||||
alloc_and_load_rr_graph(device_ctx.rr_graph.nodes().size(), device_ctx.rr_graph, segment_inf.size(),
|
||||
alloc_and_load_rr_graph(device_ctx.rr_graph, segment_inf.size(),
|
||||
chan_details_x, chan_details_y,
|
||||
track_to_pin_lookup, opin_to_track_map,
|
||||
switch_block_conn, sb_conn_map, grid, Fs, unidir_sb_pattern,
|
||||
Fc_out, Fc_xofs, Fc_yofs, device_ctx.rr_node_indices,
|
||||
Fc_out, Fc_xofs, Fc_yofs, L_rr_node_indices,
|
||||
max_chan_width,
|
||||
nodes_per_chan,
|
||||
wire_to_arch_ipin_switch,
|
||||
|
@ -820,6 +828,8 @@ static void build_rr_graph(const t_graph_type graph_type,
|
|||
if (clb_to_clb_directs != nullptr) {
|
||||
free(clb_to_clb_directs);
|
||||
}
|
||||
|
||||
L_rr_node_indices.clear();
|
||||
}
|
||||
|
||||
/* Allocates and loads the global rr_switch_inf array based on the global
|
||||
|
@ -1292,8 +1302,7 @@ static void free_type_track_to_pin_map(t_track_to_pin_lookup& track_to_pin_map,
|
|||
|
||||
/* Does the actual work of allocating the rr_graph and filling all the *
|
||||
* appropriate values. Everything up to this was just a prelude! */
|
||||
static void alloc_and_load_rr_graph(const int num_nodes,
|
||||
RRGraph& rr_graph,
|
||||
static void alloc_and_load_rr_graph(RRGraph& rr_graph,
|
||||
const int num_seg_types,
|
||||
const t_chan_details& chan_details_x,
|
||||
const t_chan_details& chan_details_y,
|
||||
|
@ -1463,12 +1472,12 @@ static void build_bidir_rr_opins(const int i,
|
|||
total_pin_Fc += Fc[pin_index][iseg];
|
||||
}
|
||||
|
||||
RRNodeId node_index = rr_graph.find_node(i, j, OPIN, pin_index, side);
|
||||
RRNodeId node_index = RRNodeId(get_rr_node_index(L_rr_node_indices, i, j, OPIN, pin_index, side));
|
||||
VTR_ASSERT(true == rr_graph.valid_node_id(node_index));
|
||||
|
||||
if (total_pin_Fc > 0) {
|
||||
get_bidir_opin_connections(i, j, pin_index,
|
||||
node_index, rr_edges_to_create, opin_to_track_map, rr_graph,
|
||||
node_index, rr_edges_to_create, opin_to_track_map, L_rr_node_indices,
|
||||
chan_details_x,
|
||||
chan_details_y);
|
||||
}
|
||||
|
@ -1540,7 +1549,7 @@ static void build_rr_sinks_sources(const int i,
|
|||
for (int iclass = 0; iclass < num_class; ++iclass) {
|
||||
RRNodeId inode = RRNodeId::INVALID();
|
||||
if (class_inf[iclass].type == DRIVER) { /* SOURCE */
|
||||
inode = rr_graph.find_node(i, j, SOURCE, iclass);
|
||||
inode = RRNodeId(get_rr_node_index(L_rr_node_indices, i, j, SOURCE, iclass));
|
||||
|
||||
//Retrieve all the physical OPINs associated with this source, this includes
|
||||
//those at different grid tiles of this block
|
||||
|
@ -1549,7 +1558,7 @@ static void build_rr_sinks_sources(const int i,
|
|||
for (int height_offset = 0; height_offset < type->height; ++height_offset) {
|
||||
for (int ipin = 0; ipin < class_inf[iclass].num_pins; ++ipin) {
|
||||
int pin_num = class_inf[iclass].pinlist[ipin];
|
||||
auto physical_pins = find_rr_graph_nodes(rr_graph, i + width_offset, j + height_offset, OPIN, pin_num);
|
||||
auto physical_pins = get_rr_graph_node_indices(L_rr_node_indices, i + width_offset, j + height_offset, OPIN, pin_num);
|
||||
opin_nodes.insert(opin_nodes.end(), physical_pins.begin(), physical_pins.end());
|
||||
}
|
||||
}
|
||||
|
@ -1560,10 +1569,11 @@ static void build_rr_sinks_sources(const int i,
|
|||
rr_edges_to_create.emplace_back(inode, opin_nodes[iedge], delayless_switch);
|
||||
}
|
||||
|
||||
rr_graph.set_node_type(inode, SOURCE);
|
||||
rr_graph.set_node_cost_index(inode, SOURCE_COST_INDEX);
|
||||
} else { /* SINK */
|
||||
VTR_ASSERT(class_inf[iclass].type == RECEIVER);
|
||||
inode = rr_graph.find_node(i, j, SINK, iclass);
|
||||
inode = get_rr_graph_node_index(L_rr_node_indices, i, j, SINK, iclass);
|
||||
|
||||
/* NOTE: To allow route throughs through clbs, change the lines below to *
|
||||
* make an edge from the input SINK to the output SOURCE. Do for just the *
|
||||
|
@ -1572,7 +1582,8 @@ static void build_rr_sinks_sources(const int i,
|
|||
* base cost of OPINs and/or SOURCES so they aren't used excessively. */
|
||||
|
||||
/* Initialize to unconnected */
|
||||
rr_graph.set_node_cost_index(RRNodeId(inode), SINK_COST_INDEX);
|
||||
rr_graph.set_node_type(inode, SINK);
|
||||
rr_graph.set_node_cost_index(inode, SINK_COST_INDEX);
|
||||
}
|
||||
|
||||
/* Things common to both SOURCEs and SINKs. */
|
||||
|
@ -1597,24 +1608,29 @@ static void build_rr_sinks_sources(const int i,
|
|||
|
||||
if (class_inf[iclass].type == RECEIVER) {
|
||||
//Connect the input pin to the sink
|
||||
inode = rr_graph.find_node(i + width_offset, j + height_offset, IPIN, ipin, side);
|
||||
inode = RRNodeId(get_rr_node_index(L_rr_node_indices, i + width_offset, j + height_offset, IPIN, ipin, side));
|
||||
|
||||
RRNodeId to_node = rr_graph.find_node(i, j, SINK, iclass);
|
||||
RRNodeId to_node = RRNodeId(get_rr_node_index(L_rr_node_indices, i, j, SINK, iclass));
|
||||
|
||||
VTR_ASSERT(true == rr_graph.valid_node_id(inode));
|
||||
VTR_ASSERT(true == rr_graph.valid_node_id(to_node));
|
||||
|
||||
//Add info about the edge to be created
|
||||
rr_edges_to_create.emplace_back(inode, to_node, delayless_switch);
|
||||
|
||||
VTR_ASSERT(true == rr_graph.valid_node_id(inode));
|
||||
rr_graph.set_node_type(inode, IPIN);
|
||||
rr_graph.set_node_cost_index(inode, IPIN_COST_INDEX);
|
||||
|
||||
} else {
|
||||
VTR_ASSERT(class_inf[iclass].type == DRIVER);
|
||||
//Initialize the output pin
|
||||
// Note that we leave it's out-going edges unconnected (they will be hooked up to global routing later)
|
||||
inode = rr_graph.find_node(i + width_offset, j + height_offset, OPIN, ipin, side);
|
||||
inode = RRNodeId(get_rr_node_index(L_rr_node_indices, i + width_offset, j + height_offset, OPIN, ipin, side));
|
||||
VTR_ASSERT(true == rr_graph.valid_node_id(inode));
|
||||
|
||||
//Initially left unconnected
|
||||
|
||||
rr_graph.set_node_type(inode, OPIN);
|
||||
rr_graph.set_node_cost_index(inode, OPIN_COST_INDEX);
|
||||
}
|
||||
|
||||
|
@ -1731,7 +1747,7 @@ static void build_rr_chan(const int x_coord,
|
|||
from_seg_details = chan_details_x[start][y_coord].data();
|
||||
}
|
||||
|
||||
RRNodeId node = rr_graph.find_node(x_coord, y_coord, chan_type, track);
|
||||
RRNodeId node = get_rr_graph_node_index(L_rr_node_indices, x_coord, y_coord, chan_type, track);
|
||||
|
||||
if (node == RRNodeId::INVALID()) {
|
||||
continue;
|
||||
|
@ -1740,7 +1756,7 @@ static void build_rr_chan(const int x_coord,
|
|||
/* Add the edges from this track to all it's connected pins into the list */
|
||||
int num_edges = 0;
|
||||
num_edges += get_track_to_pins(start, chan_coord, track, tracks_per_chan, node, rr_edges_to_create,
|
||||
rr_graph, track_to_pin_lookup, seg_details, chan_type, seg_dimension,
|
||||
L_rr_node_indices, rr_graph, track_to_pin_lookup, seg_details, chan_type, seg_dimension,
|
||||
wire_to_ipin_switch, directionality);
|
||||
|
||||
/* get edges going from the current track into channel segments which are perpendicular to it */
|
||||
|
@ -1758,7 +1774,7 @@ static void build_rr_chan(const int x_coord,
|
|||
Fs_per_side, sblock_pattern, node, rr_edges_to_create,
|
||||
from_seg_details, to_seg_details, opposite_chan_details,
|
||||
directionality,
|
||||
rr_graph,
|
||||
L_rr_node_indices, rr_graph,
|
||||
switch_block_conn, sb_conn_map);
|
||||
}
|
||||
}
|
||||
|
@ -1776,7 +1792,7 @@ static void build_rr_chan(const int x_coord,
|
|||
Fs_per_side, sblock_pattern, node, rr_edges_to_create,
|
||||
from_seg_details, to_seg_details, opposite_chan_details,
|
||||
directionality,
|
||||
rr_graph,
|
||||
L_rr_node_indices, rr_graph,
|
||||
switch_block_conn, sb_conn_map);
|
||||
}
|
||||
}
|
||||
|
@ -1806,13 +1822,14 @@ static void build_rr_chan(const int x_coord,
|
|||
Fs_per_side, sblock_pattern, node, rr_edges_to_create,
|
||||
from_seg_details, to_seg_details, from_chan_details,
|
||||
directionality,
|
||||
rr_graph,
|
||||
L_rr_node_indices, rr_graph,
|
||||
switch_block_conn, sb_conn_map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Edge arrays have now been built up. Do everything else. */
|
||||
rr_graph.set_node_type(node, chan_type); /* GLOBAL routing handled elsewhere */
|
||||
rr_graph.set_node_cost_index(node, cost_index_offset + seg_details[track].index());
|
||||
rr_graph.set_node_capacity(node, 1); /* GLOBAL routing handled elsewhere */
|
||||
|
||||
|
@ -1869,7 +1886,7 @@ void alloc_and_load_edges(RRGraph& rr_graph,
|
|||
//Note that we do this in bulk instead of via add_edge() to reduce
|
||||
//memory fragmentation
|
||||
|
||||
rr_graph.reserve_edges(edge_count + rr_graph.edges().size());
|
||||
//rr_graph.reserve_edges(edge_count + rr_graph.edges().size());
|
||||
|
||||
for (auto itr = edge_range.first; itr != edge_range.second; ++itr) {
|
||||
VTR_ASSERT(itr->from_node == inode);
|
||||
|
@ -2702,12 +2719,8 @@ static void build_unidir_rr_opins(const int i, const int j,
|
|||
continue;
|
||||
}
|
||||
|
||||
RRNodeId opin_node_index = rr_graph.find_node(i, j, OPIN, pin_index, side);
|
||||
//if (false == rr_graph.valid_node_id(opin_node_index)) continue; //No valid from node
|
||||
|
||||
if (1 == type->pinloc[width_offset][height_offset][side][pin_index]) {
|
||||
VTR_ASSERT(true == rr_graph.valid_node_id(opin_node_index));
|
||||
}
|
||||
RRNodeId opin_node_index = get_rr_graph_node_index(L_rr_node_indices, i, j, OPIN, pin_index, side);
|
||||
if (false == rr_graph.valid_node_id(opin_node_index)) continue; //No valid from node
|
||||
|
||||
for (int iseg = 0; iseg < num_seg_types; iseg++) {
|
||||
/* get Fc for this segment type */
|
||||
|
@ -2760,7 +2773,7 @@ static void build_unidir_rr_opins(const int i, const int j,
|
|||
opin_node_index,
|
||||
rr_edges_to_create,
|
||||
Fc_ofs, max_len, max_chan_width,
|
||||
rr_graph, &clipped);
|
||||
L_rr_node_indices, &clipped);
|
||||
if (clipped) {
|
||||
*Fc_clipped = true;
|
||||
}
|
||||
|
@ -3007,7 +3020,7 @@ static int get_opin_direct_connections(int x,
|
|||
}
|
||||
} else {
|
||||
//No side specified, get all candidates
|
||||
inodes = find_rr_graph_nodes(rr_graph, x + directs[i].x_offset, y + directs[i].y_offset,
|
||||
inodes = get_rr_graph_node_indices(L_rr_node_indices, x + directs[i].x_offset, y + directs[i].y_offset,
|
||||
IPIN, ipin);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,14 +31,15 @@ static void load_chan_rr_indices(const int max_chan_width,
|
|||
const int num_chans,
|
||||
const t_rr_type type,
|
||||
const t_chan_details& chan_details,
|
||||
RRGraph& rr_graph,
|
||||
t_rr_node_indices& indices,
|
||||
int* index);
|
||||
|
||||
static void load_block_rr_indices(const DeviceGrid& grid,
|
||||
RRGraph& rr_graph,
|
||||
t_rr_node_indices& indices,
|
||||
int* index);
|
||||
|
||||
static int get_bidir_track_to_chan_seg(const std::vector<int> conn_tracks,
|
||||
const t_rr_node_indices& L_rr_node_indices,
|
||||
const RRGraph& rr_graph,
|
||||
const int to_chan,
|
||||
const int to_seg,
|
||||
|
@ -64,6 +65,7 @@ static int get_unidir_track_to_chan_seg(const int from_track,
|
|||
const int Fs_per_side,
|
||||
t_sblock_pattern& sblock_pattern,
|
||||
const int switch_override,
|
||||
const t_rr_node_indices& L_rr_node_indices,
|
||||
const RRGraph& rr_graph,
|
||||
const t_chan_seg_details* seg_details,
|
||||
bool* Fs_clipped,
|
||||
|
@ -77,6 +79,7 @@ static int get_track_to_chan_seg(const int from_track,
|
|||
const e_side from_side,
|
||||
const e_side to_side,
|
||||
const int swtich_override,
|
||||
const t_rr_node_indices& L_rr_node_indices,
|
||||
const RRGraph& rr_graph,
|
||||
t_sb_connection_map* sb_conn_map,
|
||||
const RRNodeId& from_rr_node,
|
||||
|
@ -667,7 +670,7 @@ int get_bidir_opin_connections(const int i,
|
|||
const RRNodeId& from_rr_node,
|
||||
t_rr_edge_info_set& rr_edges_to_create,
|
||||
const t_pin_to_track_lookup& opin_to_track_map,
|
||||
const RRGraph& rr_graph,
|
||||
const t_rr_node_indices& L_rr_node_indices,
|
||||
const t_chan_details& chan_details_x,
|
||||
const t_chan_details& chan_details_y) {
|
||||
int num_conn, tr_i, tr_j, chan, seg;
|
||||
|
@ -731,7 +734,7 @@ int get_bidir_opin_connections(const int i,
|
|||
/* Only connect to wire if there is a CB */
|
||||
if (is_cblock(chan, seg, to_track, seg_details)) {
|
||||
to_switch = seg_details[to_track].arch_wire_switch();
|
||||
to_node = rr_graph.find_node(tr_i, tr_j, to_type, to_track);
|
||||
to_node = RRNodeId(get_rr_node_index(L_rr_node_indices, tr_i, tr_j, to_type, to_track));
|
||||
|
||||
if (to_node == RRNodeId::INVALID()) {
|
||||
continue;
|
||||
|
@ -757,7 +760,7 @@ int get_unidir_opin_connections(const int chan,
|
|||
vtr::NdMatrix<int, 3>& Fc_ofs,
|
||||
const int max_len,
|
||||
const int max_chan_width,
|
||||
const RRGraph& rr_graph,
|
||||
const t_rr_node_indices& L_rr_node_indices,
|
||||
bool* Fc_clipped) {
|
||||
/* Gets a linked list of Fc nodes of specified seg_type_index to connect
|
||||
* to in given chan seg. Fc_ofs is used for the opin staggering pattern. */
|
||||
|
@ -809,8 +812,8 @@ int get_unidir_opin_connections(const int chan,
|
|||
dec_track = dec_muxes[dec_mux];
|
||||
|
||||
/* Figure the inodes of those muxes */
|
||||
inc_inode_index = rr_graph.find_node(x, y, chan_type, inc_track);
|
||||
dec_inode_index = rr_graph.find_node(x, y, chan_type, dec_track);
|
||||
inc_inode_index = get_rr_graph_node_index(L_rr_node_indices, x, y, chan_type, inc_track);
|
||||
dec_inode_index = get_rr_graph_node_index(L_rr_node_indices, x, y, chan_type, dec_track);
|
||||
|
||||
if (inc_inode_index == RRNodeId::INVALID() || dec_inode_index == RRNodeId::INVALID()) {
|
||||
continue;
|
||||
|
@ -1059,8 +1062,20 @@ static void load_chan_rr_indices(const int max_chan_width,
|
|||
const int num_chans,
|
||||
const t_rr_type type,
|
||||
const t_chan_details& chan_details,
|
||||
RRGraph& rr_graph,
|
||||
t_rr_node_indices& indices,
|
||||
int* index) {
|
||||
VTR_ASSERT(indices[type].size() == size_t(num_chans));
|
||||
for (int chan = 0; chan < num_chans - 1; ++chan) {
|
||||
VTR_ASSERT(indices[type][chan].size() == size_t(chan_len));
|
||||
|
||||
for (int seg = 1; seg < chan_len - 1; ++seg) {
|
||||
VTR_ASSERT(indices[type][chan][seg].size() == NUM_SIDES);
|
||||
|
||||
/* Alloc the track inode lookup list */
|
||||
//Since channels have no side, we just use the first side
|
||||
indices[type][chan][seg][0].resize(max_chan_width, OPEN);
|
||||
}
|
||||
}
|
||||
|
||||
for (int chan = 0; chan < num_chans - 1; ++chan) {
|
||||
for (int seg = 1; seg < chan_len - 1; ++seg) {
|
||||
|
@ -1069,34 +1084,32 @@ static void load_chan_rr_indices(const int max_chan_width,
|
|||
int y = (type == CHANX ? chan : seg);
|
||||
const t_chan_seg_details* seg_details = chan_details[x][y].data();
|
||||
|
||||
for (int track = 0; track < num_chans - 1; ++track) {
|
||||
for (unsigned track = 0; track < indices[type][chan][seg][0].size(); ++track) {
|
||||
if (seg_details[track].length() <= 0)
|
||||
continue;
|
||||
|
||||
int start = get_seg_start(seg_details, track, chan, seg);
|
||||
|
||||
/* We give a fake coordinator here, to ease the downstream builder */
|
||||
short xlow = chan;
|
||||
short ylow = start;
|
||||
if (CHANX == type) {
|
||||
std::swap(xlow, ylow);
|
||||
}
|
||||
RRNodeId node = rr_graph.find_node(xlow, ylow, type, track);
|
||||
if (false == rr_graph.valid_node_id(node)) {
|
||||
/* If the start of the wire doesn't have a inode,
|
||||
* assign one to it. */
|
||||
int inode = indices[type][chan][start][0][track];
|
||||
if (OPEN == inode) {
|
||||
inode = *index;
|
||||
++(*index);
|
||||
|
||||
RRNodeId new_node = rr_graph.create_node(type);
|
||||
rr_graph.set_node_bounding_box(new_node, vtr::Rect<short>(xlow, ylow, xlow, ylow));
|
||||
rr_graph.set_node_track_num(new_node, track);
|
||||
|
||||
(*index)++;
|
||||
indices[type][chan][start][0][track] = inode;
|
||||
}
|
||||
|
||||
/* Assign inode of start of wire to current position */
|
||||
indices[type][chan][seg][0][track] = inode;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void load_block_rr_indices(const DeviceGrid& grid,
|
||||
RRGraph& rr_graph,
|
||||
t_rr_node_indices& indices,
|
||||
int* index) {
|
||||
//Walk through the grid assigning indices to SOURCE/SINK IPIN/OPIN
|
||||
for (size_t x = 0; x < grid.width(); x++) {
|
||||
|
@ -1110,14 +1123,12 @@ static void load_block_rr_indices(const DeviceGrid& grid,
|
|||
for (int iclass = 0; iclass < type->num_class; ++iclass) {
|
||||
auto class_type = type->class_inf[iclass].type;
|
||||
if (class_type == DRIVER) {
|
||||
RRNodeId node = rr_graph.create_node(SOURCE);
|
||||
rr_graph.set_node_bounding_box(node, vtr::Rect<short>(x, y, x, y));
|
||||
rr_graph.set_node_class_num(node, iclass);
|
||||
indices[SOURCE][x][y][0].push_back(*index);
|
||||
indices[SINK][x][y][0].push_back(OPEN);
|
||||
} else {
|
||||
VTR_ASSERT(class_type == RECEIVER);
|
||||
RRNodeId node = rr_graph.create_node(SINK);
|
||||
rr_graph.set_node_bounding_box(node, vtr::Rect<short>(x, y, x, y));
|
||||
rr_graph.set_node_class_num(node, iclass);
|
||||
indices[SINK][x][y][0].push_back(*index);
|
||||
indices[SOURCE][x][y][0].push_back(OPEN);
|
||||
}
|
||||
++(*index);
|
||||
}
|
||||
|
@ -1134,23 +1145,34 @@ static void load_block_rr_indices(const DeviceGrid& grid,
|
|||
auto class_type = type->class_inf[iclass].type;
|
||||
|
||||
if (class_type == DRIVER) {
|
||||
RRNodeId node = rr_graph.create_node(OPIN);
|
||||
rr_graph.set_node_bounding_box(node, vtr::Rect<short>(x_tile, y_tile, x_tile, y_tile));
|
||||
rr_graph.set_node_pin_num(node, ipin);
|
||||
rr_graph.set_node_side(node, side);
|
||||
indices[OPIN][x_tile][y_tile][side].push_back(*index);
|
||||
indices[IPIN][x_tile][y_tile][side].push_back(OPEN);
|
||||
} else {
|
||||
VTR_ASSERT(class_type == RECEIVER);
|
||||
RRNodeId node = rr_graph.create_node(IPIN);
|
||||
rr_graph.set_node_bounding_box(node, vtr::Rect<short>(x_tile, y_tile, x_tile, y_tile));
|
||||
rr_graph.set_node_pin_num(node, ipin);
|
||||
rr_graph.set_node_side(node, side);
|
||||
indices[IPIN][x_tile][y_tile][side].push_back(*index);
|
||||
indices[OPIN][x_tile][y_tile][side].push_back(OPEN);
|
||||
}
|
||||
++(*index);
|
||||
|
||||
} else {
|
||||
indices[IPIN][x_tile][y_tile][side].push_back(OPEN);
|
||||
indices[OPIN][x_tile][y_tile][side].push_back(OPEN);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//Sanity check
|
||||
for (int width_offset = 0; width_offset < type->width; ++width_offset) {
|
||||
int x_tile = x + width_offset;
|
||||
for (int height_offset = 0; height_offset < type->height; ++height_offset) {
|
||||
int y_tile = y + height_offset;
|
||||
for (e_side side : SIDES) {
|
||||
VTR_ASSERT(indices[IPIN][x_tile][y_tile][side].size() == size_t(type->num_pins));
|
||||
VTR_ASSERT(indices[OPIN][x_tile][y_tile][side].size() == size_t(type->num_pins));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1169,46 +1191,56 @@ static void load_block_rr_indices(const DeviceGrid& grid,
|
|||
int root_x = x - width_offset;
|
||||
int root_y = y - height_offset;
|
||||
|
||||
//Process each block from it's root location
|
||||
auto type = grid[x][y].type;
|
||||
|
||||
//Assign indicies for SINKs and SOURCEs
|
||||
// Note that SINKS/SOURCES have no side, so we always use side 0
|
||||
for (int iclass = 0; iclass < type->num_class; ++iclass) {
|
||||
auto class_type = type->class_inf[iclass].type;
|
||||
if (class_type == DRIVER) {
|
||||
RRNodeId node = rr_graph.find_node(root_x, root_y, SOURCE, iclass);
|
||||
/* Update the internal look-up so that we can find the SOURCE/SINK node using their offset coordinates */
|
||||
rr_graph.set_node_bounding_box(node, vtr::Rect<short>(root_x, root_y, x, y));
|
||||
} else {
|
||||
VTR_ASSERT(class_type == RECEIVER);
|
||||
RRNodeId node = rr_graph.find_node(root_x, root_y, SINK, iclass);
|
||||
/* Update the internal look-up so that we can find the SOURCE/SINK node using their offset coordinates */
|
||||
rr_graph.set_node_bounding_box(node, vtr::Rect<short>(root_x, root_y, x, y));
|
||||
}
|
||||
}
|
||||
indices[SOURCE][x][y] = indices[SOURCE][root_x][root_y];
|
||||
indices[SINK][x][y] = indices[SINK][root_x][root_y];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RRGraph alloc_and_load_rr_node_indices(const int max_chan_width,
|
||||
t_rr_node_indices alloc_and_load_rr_node_indices(const int max_chan_width,
|
||||
const DeviceGrid& grid,
|
||||
int* index,
|
||||
const t_chan_details& chan_details_x,
|
||||
const t_chan_details& chan_details_y) {
|
||||
/* Allocates and loads all the nodes in a RRGraph object */
|
||||
RRGraph rr_graph;
|
||||
/* Allocates and loads all the structures needed for fast lookups of the *
|
||||
* index of an rr_node. rr_node_indices is a matrix containing the index *
|
||||
* of the *first* rr_node at a given (i,j) location. */
|
||||
|
||||
t_rr_node_indices indices;
|
||||
|
||||
/* Alloc the lookup table */
|
||||
indices.resize(NUM_RR_TYPES);
|
||||
for (t_rr_type rr_type : RR_TYPES) {
|
||||
if (rr_type == CHANX) {
|
||||
indices[rr_type].resize(grid.height());
|
||||
for (size_t y = 0; y < grid.height(); ++y) {
|
||||
indices[rr_type][y].resize(grid.width());
|
||||
for (size_t x = 0; x < grid.width(); ++x) {
|
||||
indices[rr_type][y][x].resize(NUM_SIDES);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
indices[rr_type].resize(grid.width());
|
||||
for (size_t x = 0; x < grid.width(); ++x) {
|
||||
indices[rr_type][x].resize(grid.height());
|
||||
for (size_t y = 0; y < grid.height(); ++y) {
|
||||
indices[rr_type][x][y].resize(NUM_SIDES);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Assign indices for block nodes */
|
||||
load_block_rr_indices(grid, rr_graph, index);
|
||||
load_block_rr_indices(grid, indices, index);
|
||||
|
||||
/* Load the data for x and y channels */
|
||||
load_chan_rr_indices(max_chan_width, grid.width(), grid.height(),
|
||||
CHANX, chan_details_x, rr_graph, index);
|
||||
CHANX, chan_details_x, indices, index);
|
||||
load_chan_rr_indices(max_chan_width, grid.height(), grid.width(),
|
||||
CHANY, chan_details_y, rr_graph, index);
|
||||
return rr_graph;
|
||||
CHANY, chan_details_y, indices, index);
|
||||
return indices;
|
||||
}
|
||||
|
||||
std::vector<int> get_rr_node_chan_wires_at_location(const t_rr_node_indices& L_rr_node_indices,
|
||||
|
@ -1225,6 +1257,44 @@ std::vector<int> get_rr_node_chan_wires_at_location(const t_rr_node_indices& L_r
|
|||
return L_rr_node_indices[rr_type][x][y][SIDES[0]];
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A wrapper for the old function to return a vector of RRNodeId
|
||||
*******************************************************************/
|
||||
std::vector<RRNodeId> get_rr_graph_node_indices(const t_rr_node_indices& L_rr_node_indices,
|
||||
int x,
|
||||
int y,
|
||||
t_rr_type rr_type,
|
||||
int ptc) {
|
||||
/*
|
||||
* Like get_rr_node_index() 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.
|
||||
*/
|
||||
std::vector<RRNodeId> indices;
|
||||
|
||||
if (rr_type == IPIN || rr_type == OPIN) {
|
||||
//For pins we need to look at all the sides of the current grid tile
|
||||
|
||||
for (e_side side : SIDES) {
|
||||
int rr_node_index = get_rr_node_index(L_rr_node_indices, x, y, rr_type, ptc, side);
|
||||
|
||||
if (rr_node_index >= 0) {
|
||||
indices.push_back(RRNodeId(rr_node_index));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//Sides do not effect non-pins so there should only be one per ptc
|
||||
int rr_node_index = get_rr_node_index(L_rr_node_indices, x, y, rr_type, ptc);
|
||||
|
||||
if (rr_node_index != OPEN) {
|
||||
indices.push_back(RRNodeId(rr_node_index));
|
||||
}
|
||||
}
|
||||
|
||||
return indices;
|
||||
}
|
||||
|
||||
|
||||
std::vector<int> get_rr_node_indices(const t_rr_node_indices& L_rr_node_indices,
|
||||
int x,
|
||||
int y,
|
||||
|
@ -1259,6 +1329,15 @@ std::vector<int> get_rr_node_indices(const t_rr_node_indices& L_rr_node_indices,
|
|||
return indices;
|
||||
}
|
||||
|
||||
RRNodeId get_rr_graph_node_index(const t_rr_node_indices& L_rr_node_indices,
|
||||
int x,
|
||||
int y,
|
||||
t_rr_type rr_type,
|
||||
int ptc,
|
||||
e_side side) {
|
||||
return RRNodeId(get_rr_node_index(L_rr_node_indices, x, y, rr_type, ptc, side));
|
||||
}
|
||||
|
||||
int get_rr_node_index(const t_rr_node_indices& L_rr_node_indices,
|
||||
int x,
|
||||
int y,
|
||||
|
@ -1398,6 +1477,7 @@ int get_track_to_pins(int seg,
|
|||
int tracks_per_chan,
|
||||
const RRNodeId& from_rr_node,
|
||||
t_rr_edge_info_set& rr_edges_to_create,
|
||||
const t_rr_node_indices& L_rr_node_indices,
|
||||
const RRGraph& rr_graph,
|
||||
const t_track_to_pin_lookup& track_to_pin_lookup,
|
||||
const t_chan_seg_details* seg_details,
|
||||
|
@ -1456,7 +1536,7 @@ int get_track_to_pins(int seg,
|
|||
|
||||
/* Check there is a connection and Fc map isn't wrong */
|
||||
/*int to_node = get_rr_node_index(L_rr_node_indices, x + width_offset, y + height_offset, IPIN, ipin, side);*/
|
||||
RRNodeId to_node = rr_graph.find_node(x, y, IPIN, ipin, side);
|
||||
RRNodeId to_node = RRNodeId(get_rr_node_index(L_rr_node_indices, x, y, IPIN, ipin, side));
|
||||
if (rr_graph.valid_node_id(to_node)) {
|
||||
rr_edges_to_create.emplace_back(from_rr_node, to_node, wire_to_ipin_switch);
|
||||
++num_conn;
|
||||
|
@ -1503,6 +1583,7 @@ int get_track_to_tracks(const int from_chan,
|
|||
const t_chan_seg_details* to_seg_details,
|
||||
const t_chan_details& to_chan_details,
|
||||
const enum e_directionality directionality,
|
||||
const t_rr_node_indices& L_rr_node_indices,
|
||||
const RRGraph& rr_graph,
|
||||
const vtr::NdMatrix<std::vector<int>, 3>& switch_block_conn,
|
||||
t_sb_connection_map* sb_conn_map) {
|
||||
|
@ -1636,7 +1717,7 @@ int get_track_to_tracks(const int from_chan,
|
|||
num_conn += get_track_to_chan_seg(from_track, to_chan, to_seg,
|
||||
to_type, from_side_a, to_side,
|
||||
switch_override,
|
||||
rr_graph,
|
||||
L_rr_node_indices, rr_graph,
|
||||
sb_conn_map, from_rr_node, rr_edges_to_create);
|
||||
}
|
||||
} else {
|
||||
|
@ -1645,7 +1726,7 @@ int get_track_to_tracks(const int from_chan,
|
|||
* switchbox, so we follow through regardless of whether the current segment has an SB */
|
||||
conn_tracks = switch_block_conn[from_side_a][to_side][from_track];
|
||||
num_conn += get_bidir_track_to_chan_seg(conn_tracks,
|
||||
rr_graph, to_chan, to_seg, to_sb, to_type,
|
||||
L_rr_node_indices, rr_graph, to_chan, to_seg, to_sb, to_type,
|
||||
to_seg_details, from_is_sblock, from_switch,
|
||||
switch_override,
|
||||
directionality, from_rr_node, rr_edges_to_create);
|
||||
|
@ -1660,7 +1741,7 @@ int get_track_to_tracks(const int from_chan,
|
|||
from_side_a, to_side, Fs_per_side,
|
||||
sblock_pattern,
|
||||
switch_override,
|
||||
rr_graph, to_seg_details,
|
||||
L_rr_node_indices, rr_graph, to_seg_details,
|
||||
&Fs_clipped, from_rr_node, rr_edges_to_create);
|
||||
}
|
||||
}
|
||||
|
@ -1675,7 +1756,7 @@ int get_track_to_tracks(const int from_chan,
|
|||
num_conn += get_track_to_chan_seg(from_track, to_chan, to_seg,
|
||||
to_type, from_side_b, to_side,
|
||||
switch_override,
|
||||
rr_graph,
|
||||
L_rr_node_indices, rr_graph,
|
||||
sb_conn_map, from_rr_node, rr_edges_to_create);
|
||||
}
|
||||
} else {
|
||||
|
@ -1684,7 +1765,7 @@ int get_track_to_tracks(const int from_chan,
|
|||
* switchbox, so we follow through regardless of whether the current segment has an SB */
|
||||
conn_tracks = switch_block_conn[from_side_b][to_side][from_track];
|
||||
num_conn += get_bidir_track_to_chan_seg(conn_tracks,
|
||||
rr_graph, to_chan, to_seg, to_sb, to_type,
|
||||
L_rr_node_indices, rr_graph, to_chan, to_seg, to_sb, to_type,
|
||||
to_seg_details, from_is_sblock, from_switch,
|
||||
switch_override,
|
||||
directionality, from_rr_node, rr_edges_to_create);
|
||||
|
@ -1700,7 +1781,7 @@ int get_track_to_tracks(const int from_chan,
|
|||
from_side_b, to_side, Fs_per_side,
|
||||
sblock_pattern,
|
||||
switch_override,
|
||||
rr_graph, to_seg_details,
|
||||
L_rr_node_indices, rr_graph, to_seg_details,
|
||||
&Fs_clipped, from_rr_node, rr_edges_to_create);
|
||||
}
|
||||
}
|
||||
|
@ -1712,6 +1793,7 @@ int get_track_to_tracks(const int from_chan,
|
|||
}
|
||||
|
||||
static int get_bidir_track_to_chan_seg(const std::vector<int> conn_tracks,
|
||||
const t_rr_node_indices& L_rr_node_indices,
|
||||
const RRGraph& rr_graph,
|
||||
const int to_chan,
|
||||
const int to_seg,
|
||||
|
@ -1744,9 +1826,9 @@ static int get_bidir_track_to_chan_seg(const std::vector<int> conn_tracks,
|
|||
num_conn = 0;
|
||||
for (iconn = 0; iconn < conn_tracks.size(); ++iconn) {
|
||||
to_track = conn_tracks[iconn];
|
||||
to_node = rr_graph.find_node(to_x, to_y, to_type, to_track);
|
||||
to_node = get_rr_graph_node_index(L_rr_node_indices, to_x, to_y, to_type, to_track);
|
||||
|
||||
if (to_node == RRNodeId::INVALID()) {
|
||||
if (false == rr_graph.valid_node_id(to_node)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1787,6 +1869,7 @@ static int get_track_to_chan_seg(const int from_wire,
|
|||
const e_side from_side,
|
||||
const e_side to_side,
|
||||
const int switch_override,
|
||||
const t_rr_node_indices& L_rr_node_indices,
|
||||
const RRGraph& rr_graph,
|
||||
t_sb_connection_map* sb_conn_map,
|
||||
const RRNodeId& from_rr_node,
|
||||
|
@ -1823,9 +1906,9 @@ static int get_track_to_chan_seg(const int from_wire,
|
|||
if (conn_vector.at(iconn).from_wire != from_wire) continue;
|
||||
|
||||
int to_wire = conn_vector.at(iconn).to_wire;
|
||||
RRNodeId to_node = rr_graph.find_node(to_x, to_y, to_chan_type, to_wire);
|
||||
RRNodeId to_node = RRNodeId(get_rr_node_index(L_rr_node_indices, to_x, to_y, to_chan_type, to_wire));
|
||||
|
||||
if (to_node == RRNodeId::INVALID()) {
|
||||
if (false == rr_graph.valid_node_id(to_node)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1866,6 +1949,7 @@ static int get_unidir_track_to_chan_seg(const int from_track,
|
|||
const int Fs_per_side,
|
||||
t_sblock_pattern& sblock_pattern,
|
||||
const int switch_override,
|
||||
const t_rr_node_indices& L_rr_node_indices,
|
||||
const RRGraph& rr_graph,
|
||||
const t_chan_seg_details* seg_details,
|
||||
bool* Fs_clipped,
|
||||
|
@ -1923,9 +2007,9 @@ static int get_unidir_track_to_chan_seg(const int from_track,
|
|||
sblock_pattern[sb_x][sb_y][from_side][to_side][from_track][j + 1] = to_track;
|
||||
}
|
||||
|
||||
RRNodeId to_node = rr_graph.find_node(to_x, to_y, to_type, to_track);
|
||||
RRNodeId to_node = get_rr_graph_node_index(L_rr_node_indices, to_x, to_y, to_type, to_track);
|
||||
|
||||
if (to_node == RRNodeId::INVALID()) {
|
||||
if (false == rr_graph.valid_node_id(to_node)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ typedef vtr::NdMatrix<short, 6> t_sblock_pattern;
|
|||
|
||||
/******************* Subroutines exported by rr_graph2.c *********************/
|
||||
|
||||
RRGraph alloc_and_load_rr_node_indices(const int max_chan_width,
|
||||
t_rr_node_indices alloc_and_load_rr_node_indices(const int max_chan_width,
|
||||
const DeviceGrid& grid,
|
||||
int* index,
|
||||
const t_chan_details& chan_details_x,
|
||||
|
@ -59,7 +59,14 @@ int get_rr_node_index(int x,
|
|||
int ptc,
|
||||
const t_rr_node_indices& L_rr_node_indices);
|
||||
|
||||
|
||||
//Returns all the rr nodes associated with the specified coordinate (i.e. accross sides)
|
||||
std::vector<RRNodeId> get_rr_graph_node_indices(const t_rr_node_indices& L_rr_node_indices,
|
||||
int x,
|
||||
int y,
|
||||
t_rr_type rr_type,
|
||||
int ptc);
|
||||
|
||||
std::vector<int> get_rr_node_indices(const t_rr_node_indices& L_rr_node_indices,
|
||||
int x,
|
||||
int y,
|
||||
|
@ -74,6 +81,13 @@ std::vector<int> get_rr_node_chan_wires_at_location(const t_rr_node_indices& L_r
|
|||
|
||||
//Return the first rr node of the specified type and coordinates
|
||||
// For non-IPIN/OPIN types 'side' is ignored
|
||||
RRNodeId get_rr_graph_node_index(const t_rr_node_indices& L_rr_node_indices,
|
||||
int x,
|
||||
int y,
|
||||
t_rr_type rr_type,
|
||||
int ptc,
|
||||
e_side side = NUM_SIDES);
|
||||
|
||||
int get_rr_node_index(const t_rr_node_indices& L_rr_node_indices,
|
||||
int x,
|
||||
int y,
|
||||
|
@ -156,7 +170,7 @@ int get_bidir_opin_connections(const int i,
|
|||
const RRNodeId& from_rr_node,
|
||||
t_rr_edge_info_set& rr_edges_to_create,
|
||||
const t_pin_to_track_lookup& opin_to_track_map,
|
||||
const RRGraph& rr_graph,
|
||||
const t_rr_node_indices& L_rr_node_indices,
|
||||
const t_chan_details& chan_details_x,
|
||||
const t_chan_details& chan_details_y);
|
||||
|
||||
|
@ -171,7 +185,7 @@ int get_unidir_opin_connections(const int chan,
|
|||
vtr::NdMatrix<int, 3>& Fc_ofs,
|
||||
const int max_len,
|
||||
const int max_chan_width,
|
||||
const RRGraph& rr_graph,
|
||||
const t_rr_node_indices& L_rr_node_indices,
|
||||
bool* Fc_clipped);
|
||||
|
||||
int get_track_to_pins(int seg,
|
||||
|
@ -180,6 +194,7 @@ int get_track_to_pins(int seg,
|
|||
int tracks_per_chan,
|
||||
const RRNodeId& from_rr_node,
|
||||
t_rr_edge_info_set& rr_edges_to_create,
|
||||
const t_rr_node_indices& L_rr_node_indices,
|
||||
const RRGraph& rr_graph,
|
||||
const t_track_to_pin_lookup& track_to_pin_lookup,
|
||||
const t_chan_seg_details* seg_details,
|
||||
|
@ -205,6 +220,7 @@ int get_track_to_tracks(const int from_chan,
|
|||
const t_chan_seg_details* to_seg_details,
|
||||
const t_chan_details& to_chan_details,
|
||||
const enum e_directionality directionality,
|
||||
const t_rr_node_indices& L_rr_node_indices,
|
||||
const RRGraph& rr_graph,
|
||||
const vtr::NdMatrix<std::vector<int>, 3>& switch_block_conn,
|
||||
t_sb_connection_map* sb_conn_map);
|
||||
|
|
Loading…
Reference in New Issue