diff --git a/vpr/src/device/rr_graph_obj.cpp b/vpr/src/device/rr_graph_obj.cpp index 74ee29667..1b738d212 100644 --- a/vpr/src/device/rr_graph_obj.cpp +++ b/vpr/src/device/rr_graph_obj.cpp @@ -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,52 +1220,29 @@ 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 xlows; - std::vector 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()); + size_t itype = node_type(node); + + size_t ptc = node_ptc_num(node); + if (ptc >= node_lookup_[x][y][itype].size()) { + node_lookup_[x][y][itype].resize(ptc + 1); + } + + size_t iside = -1; + if (node_type(node) == OPIN || node_type(node) == IPIN) { + iside = node_side(node); } else { - */ - xlows.push_back(node_xlow(node)); - ylows.push_back(node_ylow(node)); - /* + iside = NUM_SIDES; } - */ - for (size_t x : xlows) { - for (size_t y : ylows) { - size_t itype = node_type(node); - - size_t ptc = node_ptc_num(node); - if (ptc >= node_lookup_[x][y][itype].size()) { - node_lookup_[x][y][itype].resize(ptc + 1); - } - - size_t iside = -1; - if (node_type(node) == OPIN || node_type(node) == IPIN) { - iside = node_side(node); - } else { - iside = NUM_SIDES; - } - - if (iside >= node_lookup_[x][y][itype][ptc].size()) { - node_lookup_[x][y][itype][ptc].resize(iside + 1); - } - - //Save node in lookup - node_lookup_[x][y][itype][ptc][iside] = node; - } + if (iside >= node_lookup_[x][y][itype][ptc].size()) { + node_lookup_[x][y][itype][ptc].resize(iside + 1); } + + //Save node in lookup + node_lookup_[x][y][itype][ptc][iside] = node; } } diff --git a/vpr/src/device/rr_graph_obj.h b/vpr/src/device/rr_graph_obj.h index a81a5b301..fd8439868 100644 --- a/vpr/src/device/rr_graph_obj.h +++ b/vpr/src/device/rr_graph_obj.h @@ -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); diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index b24c2f6ef..f9a87bfea 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -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,10 +598,19 @@ 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, - &num_rr_nodes, chan_details_x, chan_details_y); + 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 */ @@ -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,8 +3020,8 @@ 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, - IPIN, ipin); + inodes = get_rr_graph_node_indices(L_rr_node_indices, x + directs[i].x_offset, y + directs[i].y_offset, + IPIN, ipin); } if (inodes.size() > 0) { diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index ede1fdff5..6317b53b7 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -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 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& 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)) { - - RRNodeId new_node = rr_graph.create_node(type); - rr_graph.set_node_bounding_box(new_node, vtr::Rect(xlow, ylow, xlow, ylow)); - rr_graph.set_node_track_num(new_node, track); - - (*index)++; + /* 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); + + 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(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(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(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(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(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(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, - 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; +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 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 get_rr_node_chan_wires_at_location(const t_rr_node_indices& L_rr_node_indices, @@ -1225,6 +1257,44 @@ std::vector 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 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 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 get_rr_node_indices(const t_rr_node_indices& L_rr_node_indices, int x, int y, @@ -1259,6 +1329,15 @@ std::vector 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, 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 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 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; } diff --git a/vpr/src/route/rr_graph2.h b/vpr/src/route/rr_graph2.h index 6aa5cae68..30d68d6db 100644 --- a/vpr/src/route/rr_graph2.h +++ b/vpr/src/route/rr_graph2.h @@ -47,11 +47,11 @@ typedef vtr::NdMatrix t_sblock_pattern; /******************* Subroutines exported by rr_graph2.c *********************/ -RRGraph 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); +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); int get_rr_node_index(int x, int y, @@ -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 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 get_rr_node_indices(const t_rr_node_indices& L_rr_node_indices, int x, int y, @@ -74,6 +81,13 @@ std::vector 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& 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, 3>& switch_block_conn, t_sb_connection_map* sb_conn_map);