diff --git a/utils/route_diag/src/main.cpp b/utils/route_diag/src/main.cpp index fbb06cf7764..d081c442662 100644 --- a/utils/route_diag/src/main.cpp +++ b/utils/route_diag/src/main.cpp @@ -170,7 +170,7 @@ static void profile_source(int source_rr_node, for (int sink_ptc : best_sink_ptcs) { VTR_ASSERT(sink_ptc != OPEN); - int sink_rr_node = get_rr_node_index(device_ctx.rr_node_indices, sink_x, sink_y, SINK, sink_ptc); + int sink_rr_node = size_t(device_ctx.rr_graph.node_lookup().find_node(sink_x, sink_y, SINK, sink_ptc)); if (directconnect_exists(source_rr_node, sink_rr_node)) { //Skip if we shouldn't measure direct connects and a direct connect exists diff --git a/vpr/src/device/rr_graph_builder.h b/vpr/src/device/rr_graph_builder.h index 9020fa5bf1c..efaa01c668c 100644 --- a/vpr/src/device/rr_graph_builder.h +++ b/vpr/src/device/rr_graph_builder.h @@ -38,6 +38,8 @@ class RRGraphBuilder { /* Return a writable object for update the fast look-up of rr_node */ RRSpatialLookup& node_lookup(); /* Add an existing rr_node in the node storage to the node look-up + * The node will be added to the lookup for every side it is on (for OPINs and IPINs) + * and for every (x,y) location at which it exists (for wires that span more than one (x,y)). * This function requires a valid node which has already been allocated in the node storage, with * - a valid node id * - valid geometry information: xlow/ylow/xhigh/yhigh diff --git a/vpr/src/device/rr_spatial_lookup.cpp b/vpr/src/device/rr_spatial_lookup.cpp index 86b4f87cbfe..28e67a1e103 100644 --- a/vpr/src/device/rr_spatial_lookup.cpp +++ b/vpr/src/device/rr_spatial_lookup.cpp @@ -122,6 +122,15 @@ std::vector RRSpatialLookup::find_nodes(int x, return nodes; } + /* Reserve space to avoid memory fragmentation */ + size_t num_nodes = 0; + for (const auto& node : rr_node_indices_[type][node_x][node_y][side]) { + if (RRNodeId(node)) { + num_nodes++; + } + } + + nodes.reserve(num_nodes); for (const auto& node : rr_node_indices_[type][node_x][node_y][side]) { if (RRNodeId(node)) { nodes.push_back(RRNodeId(node)); @@ -142,11 +151,6 @@ std::vector RRSpatialLookup::find_channel_nodes(int x, return find_nodes(x, y, type); } -std::vector RRSpatialLookup::find_sink_nodes(int x, - int y) const { - return find_nodes(x, y, SINK); -} - std::vector RRSpatialLookup::find_nodes_at_all_sides(int x, int y, t_rr_type rr_type, @@ -155,6 +159,7 @@ std::vector RRSpatialLookup::find_nodes_at_all_sides(int x, /* TODO: Consider to access the raw data like find_node() rather than calling find_node() many times, which hurts runtime */ if (rr_type == IPIN || rr_type == OPIN) { + indices.reserve(NUM_SIDES); //For pins we need to look at all the sides of the current grid tile for (e_side side : SIDES) { RRNodeId rr_node_index = find_node(x, y, rr_type, ptc, side); @@ -162,6 +167,7 @@ std::vector RRSpatialLookup::find_nodes_at_all_sides(int x, indices.push_back(rr_node_index); } } + indices.shrink_to_fit(); } else { //Sides do not effect non-pins so there should only be one per ptc RRNodeId rr_node_index = find_node(x, y, rr_type, ptc); @@ -173,6 +179,46 @@ std::vector RRSpatialLookup::find_nodes_at_all_sides(int x, return indices; } +std::vector RRSpatialLookup::find_grid_nodes_at_all_sides(int x, + int y, + t_rr_type rr_type) const { + VTR_ASSERT(rr_type == SOURCE || rr_type == OPIN || rr_type == IPIN || rr_type == SINK); + if (rr_type == SOURCE || rr_type == SINK) { + return find_nodes(x, y, rr_type); + } + + std::vector nodes; + /* Reserve space to avoid memory fragmentation */ + size_t num_nodes = 0; + for (e_side node_side : SIDES) { + num_nodes += find_nodes(x, y, rr_type, node_side).size(); + } + + nodes.reserve(num_nodes); + for (e_side node_side : SIDES) { + std::vector temp_nodes = find_nodes(x, y, rr_type, node_side); + nodes.insert(nodes.end(), temp_nodes.begin(), temp_nodes.end()); + } + return nodes; +} + +void RRSpatialLookup::reserve_nodes(int x, + int y, + t_rr_type type, + int num_nodes, + e_side side) { + VTR_ASSERT_SAFE(3 == rr_node_indices_[type].ndims()); + + /* For non-IPIN/OPIN nodes, the side should always be the TOP side which follows the convention in find_node() API! */ + if (type != IPIN && type != OPIN) { + VTR_ASSERT(side == SIDES[0]); + } + + resize_nodes(x, y, type, side); + + rr_node_indices_[type][x][y][side].reserve(num_nodes); +} + void RRSpatialLookup::add_node(RRNodeId node, int x, int y, diff --git a/vpr/src/device/rr_spatial_lookup.h b/vpr/src/device/rr_spatial_lookup.h index 6e682083558..9e30ac6f55c 100644 --- a/vpr/src/device/rr_spatial_lookup.h +++ b/vpr/src/device/rr_spatial_lookup.h @@ -81,30 +81,35 @@ class RRSpatialLookup { int y, t_rr_type type) const; - /** - * Returns the indices of the specified routing resource nodes, - * representing virtual sinks. - * - (x, y) are the coordinate of the sink nodes within the FPGA - * - * Note: - * - Return an empty list if there are no sinks at the given (x, y) location - * - The node list returned only contains valid ids - */ - std::vector find_sink_nodes(int x, - int y) const; - /** * Like find_node() but returns all matching nodes on all the sides. * 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 find_nodes_at_all_sides(int x, int y, t_rr_type rr_type, int ptc) const; + /** + * Returns all matching nodes on all the sides at a specific grid tile (x,y) location. + * As this is applicable to grid pins, the type of nodes are limited to SOURCE/SINK/IPIN/OPIN + */ + std::vector find_grid_nodes_at_all_sides(int x, + int y, + t_rr_type rr_type) const; + /* -- Mutators -- */ public: + /** + * Reserve the memory for a list of nodes at (x, y) location with given type and side + */ + void reserve_nodes(int x, + int y, + t_rr_type type, + int num_nodes, + e_side side = SIDES[0]); + /** * Register a node in the fast look-up * - You must have a valid node id to register the node in the lookup diff --git a/vpr/src/place/timing_place_lookup.cpp b/vpr/src/place/timing_place_lookup.cpp index 6cf7ceebd5b..b564e09ea80 100644 --- a/vpr/src/place/timing_place_lookup.cpp +++ b/vpr/src/place/timing_place_lookup.cpp @@ -142,8 +142,7 @@ static bool find_direct_connect_sample_locations(const t_direct_inf* direct, int to_pin, int to_pin_class, int* src_rr, - int* sink_rr, - std::vector* scratch); + int* sink_rr); static bool verify_delta_delays(const vtr::Matrix& delta_delays); @@ -955,8 +954,7 @@ static bool find_direct_connect_sample_locations(const t_direct_inf* direct, int to_pin, int to_pin_class, int* src_rr, - int* sink_rr, - std::vector* scratch) { + int* sink_rr) { VTR_ASSERT(from_type != nullptr); VTR_ASSERT(to_type != nullptr); @@ -983,8 +981,7 @@ static bool find_direct_connect_sample_locations(const t_direct_inf* direct, RRNodeId from_pin_rr = node_lookup.find_node(from_x, from_y, OPIN, from_pin, direct->from_side); from_pin_found = (from_pin_rr != RRNodeId::INVALID()); } else { - (*scratch) = node_lookup.find_nodes_at_all_sides(from_x, from_y, OPIN, from_pin); - from_pin_found = !(*scratch).empty(); + from_pin_found = !(node_lookup.find_nodes_at_all_sides(from_x, from_y, OPIN, from_pin).empty()); } if (!from_pin_found) continue; @@ -1000,8 +997,7 @@ static bool find_direct_connect_sample_locations(const t_direct_inf* direct, RRNodeId to_pin_rr = node_lookup.find_node(to_x, to_y, IPIN, to_pin, direct->to_side); to_pin_found = (to_pin_rr != RRNodeId::INVALID()); } else { - (*scratch) = node_lookup.find_nodes_at_all_sides(to_x, to_y, IPIN, to_pin); - to_pin_found = !(*scratch).empty(); + to_pin_found = !(node_lookup.find_nodes_at_all_sides(to_x, to_y, IPIN, to_pin).empty()); } if (!to_pin_found) continue; @@ -1038,15 +1034,15 @@ static bool find_direct_connect_sample_locations(const t_direct_inf* direct, // { - (*scratch) = node_lookup.find_nodes_at_all_sides(from_x, from_y, SOURCE, from_pin_class); - VTR_ASSERT((*scratch).size() > 0); - *src_rr = size_t((*scratch)[0]); + RRNodeId src_rr_candidate = node_lookup.find_node(from_x, from_y, SOURCE, from_pin_class); + VTR_ASSERT(src_rr_candidate); + *src_rr = size_t(src_rr_candidate); } { - (*scratch) = node_lookup.find_nodes_at_all_sides(to_x, to_y, SINK, to_pin_class); - VTR_ASSERT((*scratch).size() > 0); - *sink_rr = size_t((*scratch)[0]); + RRNodeId sink_rr_candidate = node_lookup.find_node(to_x, to_y, SINK, to_pin_class); + VTR_ASSERT(sink_rr_candidate); + *sink_rr = size_t(sink_rr_candidate); } return true; @@ -1079,7 +1075,6 @@ void OverrideDelayModel::compute_override_delay_model( //Look at all the direct connections that exist, and add overrides to delay model auto& device_ctx = g_vpr_ctx.device(); - std::vector scratch; for (int idirect = 0; idirect < device_ctx.arch->num_directs; ++idirect) { const t_direct_inf* direct = &device_ctx.arch->Directs[idirect]; @@ -1120,7 +1115,7 @@ void OverrideDelayModel::compute_override_delay_model( int src_rr = OPEN; int sink_rr = OPEN; - bool found_sample_points = find_direct_connect_sample_locations(direct, from_type, from_pin, from_pin_class, to_type, to_pin, to_pin_class, &src_rr, &sink_rr, &scratch); + bool found_sample_points = find_direct_connect_sample_locations(direct, from_type, from_pin, from_pin_class, to_type, to_pin, to_pin_class, &src_rr, &sink_rr); if (!found_sample_points) { ++missing_instances; diff --git a/vpr/src/route/clock_connection_builders.cpp b/vpr/src/route/clock_connection_builders.cpp index 0b79bb093d0..48f9eb103eb 100644 --- a/vpr/src/route/clock_connection_builders.cpp +++ b/vpr/src/route/clock_connection_builders.cpp @@ -74,18 +74,18 @@ void RoutingToClockConnection::create_switches(const ClockRRGraphBuilder& clock_ // Connect to x-channel wires unsigned num_wires_x = x_wire_indices.size() * fc; for (size_t i = 0; i < num_wires_x; i++) { - clock_graph.add_edge(rr_edges_to_create, size_t(x_wire_indices[i]), clock_index, arch_switch_idx); + clock_graph.add_edge(rr_edges_to_create, x_wire_indices[i], RRNodeId(clock_index), arch_switch_idx); } // Connect to y-channel wires unsigned num_wires_y = y_wire_indices.size() * fc; for (size_t i = 0; i < num_wires_y; i++) { - clock_graph.add_edge(rr_edges_to_create, size_t(y_wire_indices[i]), clock_index, arch_switch_idx); + clock_graph.add_edge(rr_edges_to_create, y_wire_indices[i], RRNodeId(clock_index), arch_switch_idx); } // Connect to virtual clock sink node // used by the two stage router - clock_graph.add_edge(rr_edges_to_create, clock_index, size_t(virtual_clock_network_root_idx), arch_switch_idx); + clock_graph.add_edge(rr_edges_to_create, RRNodeId(clock_index), virtual_clock_network_root_idx, arch_switch_idx); } } @@ -97,7 +97,7 @@ RRNodeId RoutingToClockConnection::create_virtual_clock_network_sink_node(int x, RRNodeId node_index = RRNodeId(rr_graph.size() - 1); //Determine the a valid PTC - std::vector nodes_at_loc = node_lookup.find_sink_nodes(x, y); + std::vector nodes_at_loc = node_lookup.find_grid_nodes_at_all_sides(x, y, SINK); int max_ptc = 0; for (RRNodeId inode : nodes_at_loc) { @@ -204,7 +204,7 @@ void ClockToClockConneciton::create_switches(const ClockRRGraphBuilder& clock_gr if (from_itter == from_rr_node_indices.end()) { from_itter = from_rr_node_indices.begin(); } - clock_graph.add_edge(rr_edges_to_create, *from_itter, to_index, arch_switch_idx); + clock_graph.add_edge(rr_edges_to_create, RRNodeId(*from_itter), RRNodeId(to_index), arch_switch_idx); from_itter++; } } @@ -317,7 +317,7 @@ void ClockToPinsConnection::create_switches(const ClockRRGraphBuilder& clock_gra //Create edges depending on Fc for (size_t i = 0; i < clock_network_indices.size() * fc; i++) { - clock_graph.add_edge(rr_edges_to_create, clock_network_indices[i], size_t(clock_pin_node_idx), arch_switch_idx); + clock_graph.add_edge(rr_edges_to_create, RRNodeId(clock_network_indices[i]), RRNodeId(clock_pin_node_idx), arch_switch_idx); } } } diff --git a/vpr/src/route/clock_network_builders.cpp b/vpr/src/route/clock_network_builders.cpp index 303955b885e..5d26591faca 100644 --- a/vpr/src/route/clock_network_builders.cpp +++ b/vpr/src/route/clock_network_builders.cpp @@ -301,8 +301,8 @@ void ClockRib::create_rr_nodes_and_internal_edges_for_one_instance(ClockRRGraphB clock_graph); // connect drive point to each half rib using a directed switch - clock_graph.add_edge(rr_edges_to_create, drive_node_idx, left_node_idx, drive.switch_idx); - clock_graph.add_edge(rr_edges_to_create, drive_node_idx, right_node_idx, drive.switch_idx); + clock_graph.add_edge(rr_edges_to_create, RRNodeId(drive_node_idx), RRNodeId(left_node_idx), drive.switch_idx); + clock_graph.add_edge(rr_edges_to_create, RRNodeId(drive_node_idx), RRNodeId(right_node_idx), drive.switch_idx); } } } @@ -606,8 +606,8 @@ void ClockSpine::create_rr_nodes_and_internal_edges_for_one_instance(ClockRRGrap clock_graph); // connect drive point to each half spine using a directed switch - clock_graph.add_edge(rr_edges_to_create, drive_node_idx, left_node_idx, drive.switch_idx); - clock_graph.add_edge(rr_edges_to_create, drive_node_idx, right_node_idx, drive.switch_idx); + clock_graph.add_edge(rr_edges_to_create, RRNodeId(drive_node_idx), RRNodeId(left_node_idx), drive.switch_idx); + clock_graph.add_edge(rr_edges_to_create, RRNodeId(drive_node_idx), RRNodeId(right_node_idx), drive.switch_idx); } } } diff --git a/vpr/src/route/connection_router.cpp b/vpr/src/route/connection_router.cpp index ac8dc06a2f9..476b3fd20d9 100644 --- a/vpr/src/route/connection_router.cpp +++ b/vpr/src/route/connection_router.cpp @@ -577,7 +577,7 @@ void ConnectionRouter::timing_driven_add_to_heap(const t_conn_cost_params if (rcv_path_manager.is_enabled() && current->path_data) { next_ptr->path_data->path_rr = current->path_data->path_rr; next_ptr->path_data->edge = current->path_data->edge; - next_ptr->path_data->path_rr.emplace_back(from_node); + next_ptr->path_data->path_rr.emplace_back(RRNodeId(from_node)); next_ptr->path_data->edge.emplace_back(from_edge); } diff --git a/vpr/src/route/router_lookahead_map_utils.cpp b/vpr/src/route/router_lookahead_map_utils.cpp index bc395e7ba74..7b940ea25b4 100644 --- a/vpr/src/route/router_lookahead_map_utils.cpp +++ b/vpr/src/route/router_lookahead_map_utils.cpp @@ -308,8 +308,6 @@ t_src_opin_delays compute_router_src_opin_lookahead() { src_opin_delays.resize(device_ctx.physical_tile_types.size()); - std::vector rr_nodes_at_loc; - //We assume that the routing connectivity of each instance of a physical tile is the same, //and so only measure one instance of each type for (size_t itile = 0; itile < device_ctx.physical_tile_types.size(); ++itile) { @@ -334,14 +332,8 @@ t_src_opin_delays compute_router_src_opin_lookahead() { //VTR_LOG("Sampling %s at (%d,%d)\n", device_ctx.physical_tile_types[itile].name, sample_loc.x(), sample_loc.y()); - rr_nodes_at_loc.clear(); - - get_rr_node_indices(device_ctx.rr_node_indices, sample_loc.x(), sample_loc.y(), rr_type, &rr_nodes_at_loc); - for (int inode : rr_nodes_at_loc) { - if (inode < 0) continue; - - RRNodeId node_id(inode); - + const std::vector& rr_nodes_at_loc = device_ctx.rr_graph.node_lookup().find_grid_nodes_at_all_sides(sample_loc.x(), sample_loc.y(), rr_type); + for (RRNodeId node_id : rr_nodes_at_loc) { int ptc = rr_graph.node_ptc_num(node_id); if (ptc >= int(src_opin_delays[itile].size())) { @@ -355,7 +347,7 @@ t_src_opin_delays compute_router_src_opin_lookahead() { if (src_opin_delays[itile][ptc].empty()) { VTR_LOGV_DEBUG(f_router_debug, "Found no reachable wires from %s (%s) at (%d,%d)\n", rr_node_typename[rr_type], - rr_node_arch_name(inode).c_str(), + rr_node_arch_name(size_t(node_id)).c_str(), sample_loc.x(), sample_loc.y()); diff --git a/vpr/src/route/rr_edge.h b/vpr/src/route/rr_edge.h index 8fed4114322..b14e52785bd 100644 --- a/vpr/src/route/rr_edge.h +++ b/vpr/src/route/rr_edge.h @@ -1,15 +1,17 @@ #ifndef RR_EDGE_H #define RR_EDGE_H +#include "rr_graph_fwd.h" + /* TODO: MUST change the node id to RRNodeId before refactoring is finished! */ struct t_rr_edge_info { - t_rr_edge_info(int from, int to, short type) noexcept + t_rr_edge_info(RRNodeId from, RRNodeId to, short type) noexcept : from_node(from) , to_node(to) , switch_type(type) {} - int from_node = OPEN; - int to_node = OPEN; + RRNodeId from_node = RRNodeId::INVALID(); + RRNodeId to_node = RRNodeId::INVALID(); short switch_type = OPEN; friend bool operator<(const t_rr_edge_info& lhs, const t_rr_edge_info& rhs) { diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index 9b633565d53..6caa5e3ecec 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -104,7 +104,6 @@ static void build_bidir_rr_opins(RRGraphBuilder& rr_graph_builder, const int i, const int j, const e_side side, - const t_rr_node_indices& L_rr_node_indices, const t_rr_graph_storage& rr_nodes, const t_pin_to_track_lookup& opin_to_track_map, const std::vector>& Fc_out, @@ -115,8 +114,7 @@ static void build_bidir_rr_opins(RRGraphBuilder& rr_graph_builder, const t_direct_inf* directs, const int num_directs, const t_clb_to_clb_directs* clb_to_clb_directs, - const int num_seg_types, - t_opin_connections_scratchpad* scratchpad); + const int num_seg_types); static void build_unidir_rr_opins(RRGraphBuilder& rr_graph_builder, const int i, @@ -131,13 +129,11 @@ static void build_unidir_rr_opins(RRGraphBuilder& rr_graph_builder, vtr::NdMatrix& Fc_yofs, t_rr_edge_info_set& created_rr_edges, bool* Fc_clipped, - const t_rr_node_indices& L_rr_node_indices, const t_rr_graph_storage& rr_nodes, const t_direct_inf* directs, const int num_directs, const t_clb_to_clb_directs* clb_to_clb_directs, - const int num_seg_types, - t_opin_connections_scratchpad* scratchpad); + const int num_seg_types); static int get_opin_direct_connections(RRGraphBuilder& rr_graph_builder, int x, @@ -146,12 +142,10 @@ static int get_opin_direct_connections(RRGraphBuilder& rr_graph_builder, int opin, RRNodeId from_rr_node, t_rr_edge_info_set& rr_edges_to_create, - const t_rr_node_indices& L_rr_node_indices, const t_rr_graph_storage& rr_nodes, const t_direct_inf* directs, const int num_directs, - const t_clb_to_clb_directs* clb_to_clb_directs, - t_opin_connections_scratchpad* scratchpad); + const t_clb_to_clb_directs* clb_to_clb_directs); static std::function alloc_and_load_rr_graph(RRGraphBuilder& rr_graph_builder, t_rr_graph_storage& L_rr_node, @@ -168,7 +162,6 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder const std::vector>& Fc_out, vtr::NdMatrix& Fc_xofs, vtr::NdMatrix& Fc_yofs, - t_rr_node_indices& L_rr_node_indices, const int max_chan_width, const t_chan_width& chan_width, const int wire_to_ipin_switch, @@ -218,10 +211,8 @@ static void build_rr_sinks_sources(RRGraphBuilder& rr_graph_builder, const int j, t_rr_graph_storage& L_rr_node, t_rr_edge_info_set& rr_edges_to_create, - const t_rr_node_indices& L_rr_node_indices, const int delayless_switch, - const DeviceGrid& grid, - t_opin_connections_scratchpad* scratchpad); + const DeviceGrid& grid); static void build_rr_chan(RRGraphBuilder& rr_graph_builder, const int i, @@ -241,8 +232,7 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, t_rr_edge_info_set& created_rr_edges, t_rr_graph_storage& L_rr_node, const int wire_to_ipin_switch, - const enum e_directionality directionality, - t_opin_connections_scratchpad* scratchpad); + const enum e_directionality directionality); void uniquify_edges(t_rr_edge_info_set& rr_edges_to_create); @@ -285,7 +275,7 @@ static std::vector> alloc_and_load_actual_fc(const std::vector< static RRNodeId pick_best_direct_connect_target_rr_node(const t_rr_graph_storage& rr_nodes, RRNodeId from_rr, - const std::vector& candidate_rr_nodes); + const std::vector& candidate_rr_nodes); static void process_non_config_sets(); @@ -637,15 +627,13 @@ static void build_rr_graph(const t_graph_type graph_type, } else { /* it looks like we get unbalanced muxing from this switch block code with Fs > 3 */ VTR_ASSERT(Fs == 3); - t_opin_connections_scratchpad scratchpad; unidir_sb_pattern = alloc_sblock_pattern_lookup(grid, max_chan_width); for (size_t i = 0; i < grid.width() - 1; i++) { for (size_t j = 0; j < grid.height() - 1; j++) { load_sblock_pattern_lookup(i, j, grid, &nodes_per_chan, chan_details_x, chan_details_y, - Fs, sb_type, unidir_sb_pattern, - &scratchpad); + Fs, sb_type, unidir_sb_pattern); } } @@ -695,7 +683,7 @@ static void build_rr_graph(const t_graph_type graph_type, 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, max_chan_width, nodes_per_chan, wire_to_arch_ipin_switch, @@ -1152,7 +1140,6 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder const std::vector>& Fc_out, vtr::NdMatrix& Fc_xofs, vtr::NdMatrix& Fc_yofs, - t_rr_node_indices& L_rr_node_indices, const int max_chan_width, const t_chan_width& chan_width, const int wire_to_ipin_switch, @@ -1179,16 +1166,14 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder //RR graph creation is the high-watermark of VPR's memory use. t_rr_edge_info_set rr_edges_to_create; - t_opin_connections_scratchpad scratchpad; - /* If Fc gets clipped, this will be flagged to true */ *Fc_clipped = false; /* Connection SINKS and SOURCES to their pins. */ for (size_t i = 0; i < grid.width(); ++i) { for (size_t j = 0; j < grid.height(); ++j) { - build_rr_sinks_sources(rr_graph_builder, i, j, L_rr_node, rr_edges_to_create, L_rr_node_indices, - delayless_switch, grid, &scratchpad); + build_rr_sinks_sources(rr_graph_builder, i, j, L_rr_node, rr_edges_to_create, + delayless_switch, grid); //Create the actual SOURCE->OPIN, IPIN->SINK edges uniquify_edges(rr_edges_to_create); @@ -1202,17 +1187,17 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder for (size_t j = 0; j < grid.height(); ++j) { for (e_side side : SIDES) { if (BI_DIRECTIONAL == directionality) { - build_bidir_rr_opins(rr_graph_builder, i, j, side, L_rr_node_indices, L_rr_node, + build_bidir_rr_opins(rr_graph_builder, i, j, side, L_rr_node, opin_to_track_map, Fc_out, rr_edges_to_create, chan_details_x, chan_details_y, grid, - directs, num_directs, clb_to_clb_directs, num_seg_types, &scratchpad); + directs, num_directs, clb_to_clb_directs, num_seg_types); } else { VTR_ASSERT(UNI_DIRECTIONAL == directionality); bool clipped; build_unidir_rr_opins(rr_graph_builder, i, j, side, grid, Fc_out, max_chan_width, chan_details_x, chan_details_y, Fc_xofs, Fc_yofs, - rr_edges_to_create, &clipped, L_rr_node_indices, L_rr_node, - directs, num_directs, clb_to_clb_directs, num_seg_types, &scratchpad); + rr_edges_to_create, &clipped, L_rr_node, + directs, num_directs, clb_to_clb_directs, num_seg_types); if (clipped) { *Fc_clipped = true; } @@ -1238,7 +1223,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder sblock_pattern, Fs / 3, chan_details_x, chan_details_y, rr_edges_to_create, L_rr_node, wire_to_ipin_switch, - directionality, &scratchpad); + directionality); //Create the actual CHAN->CHAN edges uniquify_edges(rr_edges_to_create); @@ -1253,7 +1238,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder sblock_pattern, Fs / 3, chan_details_x, chan_details_y, rr_edges_to_create, L_rr_node, wire_to_ipin_switch, - directionality, &scratchpad); + directionality); //Create the actual CHAN->CHAN edges uniquify_edges(rr_edges_to_create); @@ -1285,7 +1270,6 @@ static void build_bidir_rr_opins(RRGraphBuilder& rr_graph_builder, const int i, const int j, const e_side side, - const t_rr_node_indices& L_rr_node_indices, const t_rr_graph_storage& rr_nodes, const t_pin_to_track_lookup& opin_to_track_map, const std::vector>& Fc_out, @@ -1296,8 +1280,7 @@ static void build_bidir_rr_opins(RRGraphBuilder& rr_graph_builder, const t_direct_inf* directs, const int num_directs, const t_clb_to_clb_directs* clb_to_clb_directs, - const int num_seg_types, - t_opin_connections_scratchpad* scratchpad) { + const int num_seg_types) { //Don't connect pins which are not adjacent to channels around the perimeter if ((i == 0 && side != RIGHT) || (i == int(grid.width() - 1) && side != LEFT) @@ -1341,8 +1324,8 @@ static void build_bidir_rr_opins(RRGraphBuilder& rr_graph_builder, /* Add in direct connections */ get_opin_direct_connections(rr_graph_builder, i, j, side, pin_index, - node_index, rr_edges_to_create, L_rr_node_indices, rr_nodes, - directs, num_directs, clb_to_clb_directs, scratchpad); + node_index, rr_edges_to_create, rr_nodes, + directs, num_directs, clb_to_clb_directs); } } @@ -1383,10 +1366,8 @@ static void build_rr_sinks_sources(RRGraphBuilder& rr_graph_builder, const int j, t_rr_graph_storage& L_rr_node, t_rr_edge_info_set& rr_edges_to_create, - const t_rr_node_indices& L_rr_node_indices, const int delayless_switch, - const DeviceGrid& grid, - t_opin_connections_scratchpad* scratchpad) { + const DeviceGrid& grid) { /* Loads IPIN, SINK, SOURCE, and OPIN. * Loads IPIN to SINK edges, and SOURCE to OPIN edges */ @@ -1410,23 +1391,20 @@ static void build_rr_sinks_sources(RRGraphBuilder& rr_graph_builder, //Retrieve all the physical OPINs associated with this source, this includes //those at different grid tiles of this block - std::vector opin_nodes; + std::vector opin_nodes; for (int width_offset = 0; width_offset < type->width; ++width_offset) { 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]; - /* TODO: scratchpad should be reworked to use RRNodeId */ - std::vector& physical_pins = scratchpad->scratch[0]; - get_rr_node_indices(L_rr_node_indices, i + width_offset, j + height_offset, OPIN, pin_num, &physical_pins); + std::vector physical_pins = rr_graph_builder.node_lookup().find_nodes_at_all_sides(i + width_offset, j + height_offset, OPIN, pin_num); opin_nodes.insert(opin_nodes.end(), physical_pins.begin(), physical_pins.end()); } } } //Connect the SOURCE to each OPIN - //TODO: rr_edges_to_create should be adapted to use RRNodeId for (size_t iedge = 0; iedge < opin_nodes.size(); ++iedge) { - rr_edges_to_create.emplace_back(size_t(inode), opin_nodes[iedge], delayless_switch); + rr_edges_to_create.emplace_back(inode, opin_nodes[iedge], delayless_switch); } L_rr_node.set_node_cost_index(inode, SOURCE_COST_INDEX); @@ -1480,8 +1458,7 @@ static void build_rr_sinks_sources(RRGraphBuilder& rr_graph_builder, RRNodeId to_node = rr_graph_builder.node_lookup().find_node(i, j, SINK, iclass); //Add info about the edge to be created - //TODO: rr_edges_to_create should be adapted to use RRNodeId - rr_edges_to_create.emplace_back(size_t(inode), size_t(to_node), delayless_switch); + rr_edges_to_create.emplace_back(inode, to_node, delayless_switch); L_rr_node.set_node_cost_index(inode, IPIN_COST_INDEX); L_rr_node.set_node_type(inode, IPIN); @@ -1549,8 +1526,7 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, t_rr_edge_info_set& rr_edges_to_create, t_rr_graph_storage& L_rr_node, const int wire_to_ipin_switch, - const enum e_directionality directionality, - t_opin_connections_scratchpad* scratchpad) { + const enum e_directionality directionality) { /* this function builds both x and y-directed channel segments, so set up our * coordinates based on channel type */ @@ -1630,7 +1606,7 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, Fs_per_side, sblock_pattern, node, rr_edges_to_create, from_seg_details, to_seg_details, opposite_chan_details, directionality, - switch_block_conn, sb_conn_map, scratchpad); + switch_block_conn, sb_conn_map); } } if (chan_coord < chan_dimension) { @@ -1647,7 +1623,7 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, Fs_per_side, sblock_pattern, node, rr_edges_to_create, from_seg_details, to_seg_details, opposite_chan_details, directionality, - switch_block_conn, sb_conn_map, scratchpad); + switch_block_conn, sb_conn_map); } } @@ -1676,7 +1652,7 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, Fs_per_side, sblock_pattern, node, rr_edges_to_create, from_seg_details, to_seg_details, from_chan_details, directionality, - switch_block_conn, sb_conn_map, scratchpad); + switch_block_conn, sb_conn_map); } } } @@ -2515,13 +2491,11 @@ static void build_unidir_rr_opins(RRGraphBuilder& rr_graph_builder, vtr::NdMatrix& Fc_yofs, t_rr_edge_info_set& rr_edges_to_create, bool* Fc_clipped, - const t_rr_node_indices& L_rr_node_indices, const t_rr_graph_storage& rr_nodes, const t_direct_inf* directs, const int num_directs, const t_clb_to_clb_directs* clb_to_clb_directs, - const int num_seg_types, - t_opin_connections_scratchpad* scratchpad) { + const int num_seg_types) { /* * This routine adds the edges from opins to channels at the specified * grid location (i,j) and grid tile side @@ -2598,15 +2572,15 @@ static void build_unidir_rr_opins(RRGraphBuilder& rr_graph_builder, opin_node_index, rr_edges_to_create, Fc_ofs, max_len, max_chan_width, - &clipped, scratchpad); + &clipped); if (clipped) { *Fc_clipped = true; } } /* Add in direct connections */ - get_opin_direct_connections(rr_graph_builder, i, j, side, pin_index, opin_node_index, rr_edges_to_create, L_rr_node_indices, rr_nodes, - directs, num_directs, clb_to_clb_directs, scratchpad); + get_opin_direct_connections(rr_graph_builder, i, j, side, pin_index, opin_node_index, rr_edges_to_create, rr_nodes, + directs, num_directs, clb_to_clb_directs); } } @@ -2727,12 +2701,10 @@ static int get_opin_direct_connections(RRGraphBuilder& rr_graph_builder, int opin, RRNodeId from_rr_node, t_rr_edge_info_set& rr_edges_to_create, - const t_rr_node_indices& L_rr_node_indices, const t_rr_graph_storage& rr_nodes, const t_direct_inf* directs, const int num_directs, - const t_clb_to_clb_directs* clb_to_clb_directs, - t_opin_connections_scratchpad* scratchpad) { + const t_clb_to_clb_directs* clb_to_clb_directs) { auto& device_ctx = g_vpr_ctx.device(); t_physical_tile_type_ptr curr_type = device_ctx.grid[x][y].type; @@ -2807,19 +2779,17 @@ static int get_opin_direct_connections(RRGraphBuilder& rr_graph_builder, int ipin = get_physical_pin_from_capacity_location(target_type, relative_ipin, target_sub_tile); /* Add new ipin edge to list of edges */ - std::vector& inodes = scratchpad->scratch[0]; - inodes.resize(0); + std::vector inodes; if (directs[i].to_side != NUM_SIDES) { //Explicit side specified, only create if pin exists on that side RRNodeId inode = rr_graph_builder.node_lookup().find_node(x + directs[i].x_offset, y + directs[i].y_offset, IPIN, ipin, directs[i].to_side); if (inode) { - inodes.push_back(size_t(inode)); + inodes.push_back(inode); } } else { //No side specified, get all candidates - get_rr_node_indices(L_rr_node_indices, x + directs[i].x_offset, y + directs[i].y_offset, - IPIN, ipin, &inodes); + inodes = rr_graph_builder.node_lookup().find_nodes_at_all_sides(x + directs[i].x_offset, y + directs[i].y_offset, IPIN, ipin); } if (inodes.size() > 0) { @@ -2829,7 +2799,7 @@ static int get_opin_direct_connections(RRGraphBuilder& rr_graph_builder, //back fairly directly to the architecture file in the case of pin equivalence RRNodeId inode = pick_best_direct_connect_target_rr_node(rr_nodes, from_rr_node, inodes); - rr_edges_to_create.emplace_back(size_t(from_rr_node), size_t(inode), clb_to_clb_directs[i].switch_index); + rr_edges_to_create.emplace_back(from_rr_node, inode, clb_to_clb_directs[i].switch_index); ++num_pins; } } @@ -2943,7 +2913,7 @@ static std::vector alloc_and_load_perturb_opins(const t_physical_tile_type static RRNodeId pick_best_direct_connect_target_rr_node(const t_rr_graph_storage& rr_nodes, RRNodeId from_rr, - const std::vector& candidate_rr_nodes) { + const std::vector& candidate_rr_nodes) { //With physically equivalent pins there may be multiple candidate rr nodes (which are equivalent) //to connect the direct edge to. //As a result it does not matter (from a correctness standpoint) which is picked. @@ -2958,7 +2928,7 @@ static RRNodeId pick_best_direct_connect_target_rr_node(const t_rr_graph_storage VTR_ASSERT(rr_graph.node_type(from_rr) == OPIN); float best_dist = std::numeric_limits::infinity(); - int best_rr = OPEN; + RRNodeId best_rr = RRNodeId::INVALID(); for (const e_side& from_side : SIDES) { /* Bypass those side where the node does not appear */ @@ -2966,14 +2936,14 @@ static RRNodeId pick_best_direct_connect_target_rr_node(const t_rr_graph_storage continue; } - for (int to_rr : candidate_rr_nodes) { - VTR_ASSERT(rr_graph.node_type(RRNodeId(to_rr)) == IPIN); - float to_dist = std::abs(rr_nodes.node_xlow(from_rr) - rr_nodes[to_rr].xlow()) - + std::abs(rr_nodes.node_ylow(from_rr) - rr_nodes[to_rr].ylow()); + for (RRNodeId to_rr : candidate_rr_nodes) { + VTR_ASSERT(rr_graph.node_type(to_rr) == IPIN); + float to_dist = std::abs(rr_nodes.node_xlow(from_rr) - rr_nodes.node_xlow(to_rr)) + + std::abs(rr_nodes.node_ylow(from_rr) - rr_nodes.node_ylow(to_rr)); for (const e_side& to_side : SIDES) { /* Bypass those side where the node does not appear */ - if (!rr_nodes[to_rr].is_node_on_specific_side(to_side)) { + if (!rr_nodes.is_node_on_specific_side(to_rr, to_side)) { continue; } @@ -3003,9 +2973,9 @@ static RRNodeId pick_best_direct_connect_target_rr_node(const t_rr_graph_storage } } - VTR_ASSERT(best_rr != OPEN); + VTR_ASSERT(best_rr); - return RRNodeId(best_rr); + return best_rr; } //Collects the sets of connected non-configurable edges in the RR graph diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index ada0301af7d..b3d4eb7367e 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -69,8 +69,7 @@ static int get_unidir_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, const t_chan_seg_details* seg_details, bool* Fs_clipped, RRNodeId from_rr_node, - t_rr_edge_info_set& rr_edges_to_create, - t_opin_connections_scratchpad* scratchpad); + t_rr_edge_info_set& rr_edges_to_create); static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, const int from_track, @@ -98,7 +97,7 @@ static void label_wire_muxes(const int chan_num, const enum Direction dir, const int max_chan_width, const bool check_cb, - std::vector* labels, + std::vector& labels, int* num_wire_muxes, int* num_wire_muxes_cb_restricted); @@ -109,11 +108,11 @@ static void label_incoming_wires(const int chan_num, const int max_len, const enum Direction dir, const int max_chan_width, - std::vector* labels, + std::vector& labels, int* num_incoming_wires, int* num_ending_wires); -static int find_label_of_track(int* wire_mux_on_track, +static int find_label_of_track(const std::vector& wire_mux_on_track, int num_wire_muxes, int from_track); @@ -645,7 +644,7 @@ int get_bidir_opin_connections(RRGraphBuilder& rr_graph_builder, continue; } - rr_edges_to_create.emplace_back(size_t(from_rr_node), size_t(to_node), to_switch); + rr_edges_to_create.emplace_back(from_rr_node, to_node, to_switch); ++num_conn; } } @@ -666,8 +665,7 @@ int get_unidir_opin_connections(RRGraphBuilder& rr_graph_builder, vtr::NdMatrix& Fc_ofs, const int max_len, const int max_chan_width, - bool* Fc_clipped, - t_opin_connections_scratchpad* scratchpad) { + 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. */ @@ -688,13 +686,13 @@ int get_unidir_opin_connections(RRGraphBuilder& rr_graph_builder, /* Get the lists of possible muxes. */ int dummy; - std::vector& inc_muxes = scratchpad->scratch[0]; - std::vector& dec_muxes = scratchpad->scratch[1]; + std::vector inc_muxes; + std::vector dec_muxes; label_wire_muxes(chan, seg, seg_details, seg_type_index, max_len, - Direction::INC, max_chan_width, true, &inc_muxes, &num_inc_muxes, &dummy); + Direction::INC, max_chan_width, true, inc_muxes, &num_inc_muxes, &dummy); label_wire_muxes(chan, seg, seg_details, seg_type_index, max_len, - Direction::DEC, max_chan_width, true, &dec_muxes, &num_dec_muxes, &dummy); + Direction::DEC, max_chan_width, true, dec_muxes, &num_dec_muxes, &dummy); /* Clip Fc to the number of muxes. */ if (((Fc / 2) > num_inc_muxes) || ((Fc / 2) > num_dec_muxes)) { @@ -723,10 +721,10 @@ int get_unidir_opin_connections(RRGraphBuilder& rr_graph_builder, } /* Add to the list. */ - rr_edges_to_create.emplace_back(size_t(from_rr_node), size_t(inc_inode_index), seg_details[inc_track].arch_opin_switch()); + rr_edges_to_create.emplace_back(from_rr_node, inc_inode_index, seg_details[inc_track].arch_opin_switch()); ++num_edges; - rr_edges_to_create.emplace_back(size_t(from_rr_node), size_t(dec_inode_index), seg_details[dec_track].arch_opin_switch()); + rr_edges_to_create.emplace_back(from_rr_node, dec_inode_index, seg_details[dec_track].arch_opin_switch()); ++num_edges; } @@ -935,6 +933,9 @@ 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(); + /* Reserve nodes in lookup to save memory */ + rr_graph_builder.node_lookup().reserve_nodes(chan, seg, type, max_chan_width); + for (int track = 0; track < max_chan_width; ++track) { /* TODO: May let the length() == 0 case go through, to model muxes */ if (seg_details[track].length() <= 0) @@ -951,16 +952,16 @@ static void load_chan_rr_indices(const int max_chan_width, /* If the start of the wire doesn't have a inode, * assign one to it. */ - RRNodeId inode = rr_graph_builder.node_lookup().find_node(node_x, node_y, type, track, SIDES[0]); + RRNodeId inode = rr_graph_builder.node_lookup().find_node(node_x, node_y, type, track); if (!inode) { inode = RRNodeId(*index); ++(*index); - rr_graph_builder.node_lookup().add_node(inode, chan, start, type, track, SIDES[0]); + rr_graph_builder.node_lookup().add_node(inode, chan, start, type, track); } /* Assign inode of start of wire to current position */ - rr_graph_builder.node_lookup().add_node(inode, chan, seg, type, track, SIDES[0]); + rr_graph_builder.node_lookup().add_node(inode, chan, seg, type, track); } } } @@ -984,10 +985,10 @@ static void load_block_rr_indices(RRGraphBuilder& rr_graph_builder, for (size_t iclass = 0; iclass < type->class_inf.size(); ++iclass) { auto class_type = type->class_inf[iclass].type; if (class_type == DRIVER) { - rr_graph_builder.node_lookup().add_node(RRNodeId(*index), x, y, SOURCE, iclass, SIDES[0]); + rr_graph_builder.node_lookup().add_node(RRNodeId(*index), x, y, SOURCE, iclass); } else { VTR_ASSERT(class_type == RECEIVER); - rr_graph_builder.node_lookup().add_node(RRNodeId(*index), x, y, SINK, iclass, SIDES[0]); + rr_graph_builder.node_lookup().add_node(RRNodeId(*index), x, y, SINK, iclass); } ++(*index); } @@ -1045,6 +1046,18 @@ static void load_block_rr_indices(RRGraphBuilder& rr_graph_builder, } } + // Reserve nodes in lookup to save memory + for (e_side side : wanted_sides) { + 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; + rr_graph_builder.node_lookup().reserve_nodes(x_tile, y_tile, OPIN, type->num_pins, side); + rr_graph_builder.node_lookup().reserve_nodes(x_tile, y_tile, IPIN, type->num_pins, side); + } + } + } + //Assign indices for IPINs and OPINs at all offsets from root for (int ipin = 0; ipin < type->num_pins; ++ipin) { bool assigned_to_rr_node = false; @@ -1324,186 +1337,6 @@ bool verify_rr_node_indices(const DeviceGrid& grid, const t_rr_node_indices& rr_ return true; } -void get_rr_node_indices(const t_rr_node_indices& L_rr_node_indices, - int x, - int y, - t_rr_type rr_type, - int ptc, - std::vector* indices) { - indices->resize(0); - - /* - * 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. - */ - - 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(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(rr_node_index); - } - } -} - -void get_rr_node_indices(const t_rr_node_indices& L_rr_node_indices, - int x, - int y, - t_rr_type rr_type, - std::vector* indices, - e_side side) { - //Comparison predicate - auto is_valid_id = [](int id) { return id != OPEN; }; - - indices->resize(0); - - if (rr_type == SOURCE - || rr_type == SINK - || rr_type == CHANX - || rr_type == CHANY) { - //CHANX uses an odd swapped x/y convention... - if (CHANX == rr_type) { - std::swap(x, y); - } - - VTR_ASSERT_MSG(side == NUM_SIDES, "Non-IPINs/OPINs must not specify side"); - indices->reserve(L_rr_node_indices[rr_type][x][y][0].size()); - std::copy_if( - L_rr_node_indices[rr_type][x][y][0].begin(), - L_rr_node_indices[rr_type][x][y][0].end(), - std::back_inserter(*indices), - is_valid_id); - } else { - VTR_ASSERT(rr_type == OPIN || rr_type == IPIN); - if (side == NUM_SIDES) { - //All sides - size_t capacity_needed = 0; - for (e_side tmp_side : SIDES) { - capacity_needed += L_rr_node_indices[rr_type][x][y][tmp_side].size(); - } - - indices->reserve(capacity_needed); - for (e_side tmp_side : SIDES) { - std::copy_if( - L_rr_node_indices[rr_type][x][y][tmp_side].begin(), - L_rr_node_indices[rr_type][x][y][tmp_side].end(), - std::back_inserter(*indices), - is_valid_id); - } - } else { - //Side specified - indices->reserve(L_rr_node_indices[rr_type][x][y][side].size()); - std::copy_if( - L_rr_node_indices[rr_type][x][y][side].begin(), - L_rr_node_indices[rr_type][x][y][side].end(), - std::back_inserter(*indices), - is_valid_id); - } - } -} - -int get_rr_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) { - /* - * Returns the index of the specified routing resource node. (x,y) are - * the location within the FPGA, rr_type specifies the type of resource, - * and ptc gives the number of this resource. ptc is the class number, - * pin number or track number, depending on what type of resource this - * is. All ptcs start at 0 and go up to pins_per_clb-1 or the equivalent. - * There are class_inf size SOURCEs + SINKs, type->num_pins IPINs + OPINs, - * and max_chan_width CHANX and CHANY (each). - * - * Note that for segments (CHANX and CHANY) of length > 1, the segment is - * given an rr_index based on the (x,y) location at which it starts (i.e. - * lowest (x,y) location at which this segment exists). - * This routine also performs error checking to make sure the node in - * question exists. - * - * The 'side' argument only applies to IPIN/OPIN types, and specifies which - * side of the grid tile the node should be located on. The value is ignored - * for non-IPIN/OPIN types - */ - if (rr_type == IPIN || rr_type == OPIN) { - VTR_ASSERT_MSG(side != NUM_SIDES, "IPIN/OPIN must specify desired side (can not be default NUM_SIDES)"); - } else { - VTR_ASSERT(rr_type != IPIN && rr_type != OPIN); - side = SIDES[0]; - } - - int iclass; - - auto& device_ctx = g_vpr_ctx.device(); - - VTR_ASSERT(ptc >= 0); - VTR_ASSERT(x >= 0 && x < int(device_ctx.grid.width())); - VTR_ASSERT(y >= 0 && y < int(device_ctx.grid.height())); - - auto type = device_ctx.grid[x][y].type; - - /* Currently need to swap x and y for CHANX because of chan, seg convention */ - if (CHANX == rr_type) { - std::swap(x, y); - } - - /* Start of that block. */ - const std::vector& lookup = L_rr_node_indices[rr_type][x][y][side]; - - /* Check valid ptc num */ - VTR_ASSERT(ptc >= 0); - - switch (rr_type) { - case SOURCE: - VTR_ASSERT(ptc < (int)type->class_inf.size()); - VTR_ASSERT(type->class_inf[ptc].type == DRIVER); - break; - - case SINK: - VTR_ASSERT(ptc < (int)type->class_inf.size()); - VTR_ASSERT(type->class_inf[ptc].type == RECEIVER); - break; - - case OPIN: - VTR_ASSERT(ptc < type->num_pins); - iclass = type->pin_class[ptc]; - VTR_ASSERT(type->class_inf[iclass].type == DRIVER); - break; - - case IPIN: - VTR_ASSERT(ptc < type->num_pins); - iclass = type->pin_class[ptc]; - VTR_ASSERT(type->class_inf[iclass].type == RECEIVER); - break; - - case CHANX: - case CHANY: - break; - - default: - VPR_FATAL_ERROR(VPR_ERROR_ROUTE, - "Bad rr_node passed to get_rr_node_index.\n" - "Request for type=%d ptc=%d at (%d, %d).\n", - rr_type, ptc, x, y); - } - - return ((unsigned)ptc < lookup.size() ? lookup[ptc] : -1); -} - int get_track_to_pins(RRGraphBuilder& rr_graph_builder, int seg, int chan, @@ -1570,7 +1403,7 @@ int get_track_to_pins(RRGraphBuilder& rr_graph_builder, /*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_builder.node_lookup().find_node(x, y, IPIN, ipin, side); if (to_node) { - rr_edges_to_create.emplace_back(size_t(from_rr_node), size_t(to_node), wire_to_ipin_switch); + rr_edges_to_create.emplace_back(from_rr_node, to_node, wire_to_ipin_switch); ++num_conn; } } @@ -1617,8 +1450,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, const t_chan_details& to_chan_details, const enum e_directionality directionality, const vtr::NdMatrix, 3>& switch_block_conn, - t_sb_connection_map* sb_conn_map, - t_opin_connections_scratchpad* scratchpad) { + t_sb_connection_map* sb_conn_map) { int to_chan, to_sb; std::vector conn_tracks; bool from_is_sblock, is_behind, Fs_clipped; @@ -1773,7 +1605,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, sblock_pattern, switch_override, to_seg_details, - &Fs_clipped, from_rr_node, rr_edges_to_create, scratchpad); + &Fs_clipped, from_rr_node, rr_edges_to_create); } } } @@ -1812,7 +1644,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, sblock_pattern, switch_override, to_seg_details, - &Fs_clipped, from_rr_node, rr_edges_to_create, scratchpad); + &Fs_clipped, from_rr_node, rr_edges_to_create); } } } @@ -1877,7 +1709,7 @@ static int get_bidir_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, } /* Add the edge to the list */ - rr_edges_to_create.emplace_back(size_t(from_rr_node), size_t(to_node), switch_types[i]); + rr_edges_to_create.emplace_back(from_rr_node, to_node, switch_types[i]); ++num_conn; } } @@ -1947,14 +1779,14 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, src_switch = switch_override; } - rr_edges_to_create.emplace_back(size_t(from_rr_node), size_t(to_node), src_switch); + rr_edges_to_create.emplace_back(from_rr_node, to_node, src_switch); ++edge_count; auto& device_ctx = g_vpr_ctx.device(); if (device_ctx.arch_switch_inf[src_switch].directionality() == BI_DIRECTIONAL) { //Add reverse edge since bi-directional - rr_edges_to_create.emplace_back(size_t(to_node), size_t(from_rr_node), src_switch); + rr_edges_to_create.emplace_back(to_node, from_rr_node, src_switch); ++edge_count; } } @@ -1980,10 +1812,9 @@ static int get_unidir_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, const t_chan_seg_details* seg_details, bool* Fs_clipped, RRNodeId from_rr_node, - t_rr_edge_info_set& rr_edges_to_create, - t_opin_connections_scratchpad* scratchpad) { + t_rr_edge_info_set& rr_edges_to_create) { int num_labels = 0; - std::vector& mux_labels = scratchpad->scratch[0]; + std::vector mux_labels; /* x, y coords for get_rr_node lookups */ int to_x = (CHANX == to_type ? to_seg : to_chan); @@ -2002,7 +1833,7 @@ static int get_unidir_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, /* get list of muxes to which we can connect */ int dummy; label_wire_muxes(to_chan, to_seg, seg_details, UNDEFINED, max_len, - to_dir, max_chan_width, false, &mux_labels, &num_labels, &dummy); + to_dir, max_chan_width, false, mux_labels, &num_labels, &dummy); /* Can't connect if no muxes. */ if (num_labels < 1) { @@ -2046,13 +1877,13 @@ static int get_unidir_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, VTR_ASSERT(iswitch != OPEN); /* Add edge to list. */ - rr_edges_to_create.emplace_back(size_t(from_rr_node), size_t(to_node), iswitch); + rr_edges_to_create.emplace_back(from_rr_node, to_node, iswitch); ++count; auto& device_ctx = g_vpr_ctx.device(); if (device_ctx.arch_switch_inf[iswitch].directionality() == BI_DIRECTIONAL) { //Add reverse edge since bi-directional - rr_edges_to_create.emplace_back(size_t(to_node), size_t(from_rr_node), iswitch); + rr_edges_to_create.emplace_back(to_node, from_rr_node, iswitch); ++count; } } @@ -2239,8 +2070,7 @@ void load_sblock_pattern_lookup(const int i, const t_chan_details& chan_details_y, const int /*Fs*/, const enum e_switch_block_type switch_block_type, - t_sblock_pattern& sblock_pattern, - t_opin_connections_scratchpad* scratchpad) { + t_sblock_pattern& sblock_pattern) { /* This routine loads a lookup table for sblock topology. The lookup table is huge * because the sblock varies from location to location. The i, j means the owning * location of the sblock under investigation. */ @@ -2287,21 +2117,17 @@ void load_sblock_pattern_lookup(const int i, /* First find all four sides' incoming wires */ static_assert(NUM_SIDES == 4, "Should be 4 sides"); - VTR_ASSERT(scratchpad->scratch.size() == NUM_SIDES * 2); - std::array*, NUM_SIDES> wire_mux_on_track; - std::array*, NUM_SIDES> incoming_wire_label; + std::array, NUM_SIDES> wire_mux_on_track; + std::array, NUM_SIDES> incoming_wire_label; int num_incoming_wires[NUM_SIDES]; int num_ending_wires[NUM_SIDES]; int num_wire_muxes[NUM_SIDES]; - wire_mux_on_track.fill(nullptr); - incoming_wire_label.fill(nullptr); - /* "Label" the wires around the switch block by connectivity. */ for (e_side side : {TOP, RIGHT, BOTTOM, LEFT}) { /* Assume the channel segment doesn't exist. */ - wire_mux_on_track[side] = nullptr; - incoming_wire_label[side] = nullptr; + wire_mux_on_track[side].clear(); + incoming_wire_label[side].clear(); num_incoming_wires[side] = 0; num_ending_wires[side] = 0; num_wire_muxes[side] = 0; @@ -2353,7 +2179,6 @@ void load_sblock_pattern_lookup(const int i, /* Figure out all the tracks on a side that are ending and the * ones that are passing through and have a SB. */ enum Direction end_dir = (pos_dir ? Direction::DEC : Direction::INC); - incoming_wire_label[side] = &scratchpad->scratch[NUM_SIDES + side]; label_incoming_wires(chan, seg, sb_seg, seg_details, chan_len, end_dir, nodes_per_chan->max, incoming_wire_label[side], @@ -2363,7 +2188,6 @@ void load_sblock_pattern_lookup(const int i, /* Figure out all the tracks on a side that are starting. */ int dummy; enum Direction start_dir = (pos_dir ? Direction::INC : Direction::DEC); - wire_mux_on_track[side] = &scratchpad->scratch[side]; label_wire_muxes(chan, seg, seg_details, UNDEFINED, chan_len, start_dir, nodes_per_chan->max, false, wire_mux_on_track[side], &num_wire_muxes[side], &dummy); @@ -2391,7 +2215,7 @@ void load_sblock_pattern_lookup(const int i, * passing and ending wires so the above statement still holds * if you replace "passing" by "incoming" */ - if (incoming_wire_label[side_cw]) { + if (!incoming_wire_label[side_cw].empty()) { for (int ichan = 0; ichan < nodes_per_chan->max; ichan++) { int itrack = ichan; if (side_cw == TOP || side_cw == BOTTOM) { @@ -2400,10 +2224,10 @@ void load_sblock_pattern_lookup(const int i, itrack = ichan % nodes_per_chan->x_list[j]; } - if ((*incoming_wire_label[side_cw])[itrack] != UN_SET) { + if (incoming_wire_label[side_cw][itrack] != UN_SET) { int mux = get_simple_switch_block_track((enum e_side)side_cw, (enum e_side)to_side, - (*incoming_wire_label[side_cw])[ichan], + incoming_wire_label[side_cw][ichan], switch_block_type, num_wire_muxes[to_side]); @@ -2416,7 +2240,7 @@ void load_sblock_pattern_lookup(const int i, } } - if (incoming_wire_label[side_ccw]) { + if (!incoming_wire_label[side_ccw].empty()) { for (int ichan = 0; ichan < nodes_per_chan->max; ichan++) { int itrack = ichan; if (side_ccw == TOP || side_ccw == BOTTOM) { @@ -2425,10 +2249,10 @@ void load_sblock_pattern_lookup(const int i, itrack = ichan % nodes_per_chan->x_list[j]; } - if ((*incoming_wire_label[side_ccw])[itrack] != UN_SET) { + if (incoming_wire_label[side_ccw][itrack] != UN_SET) { int mux = get_simple_switch_block_track((enum e_side)side_ccw, (enum e_side)to_side, - (*incoming_wire_label[side_ccw])[ichan], + incoming_wire_label[side_ccw][ichan], switch_block_type, num_wire_muxes[to_side]); if (sblock_pattern[i][j][side_ccw][to_side][itrack][0] == UN_SET) { @@ -2440,17 +2264,17 @@ void load_sblock_pattern_lookup(const int i, } } - if (incoming_wire_label[side_opp]) { + if (!incoming_wire_label[side_opp].empty()) { for (int itrack = 0; itrack < nodes_per_chan->max; itrack++) { /* not ending wire nor passing wire with sblock */ - if ((*incoming_wire_label[side_opp])[itrack] != UN_SET) { + if (incoming_wire_label[side_opp][itrack] != UN_SET) { /* corner sblocks for sure have no opposite channel segments so don't care about them */ - if ((*incoming_wire_label[side_opp])[itrack] < num_ending_wires[side_opp]) { + if (incoming_wire_label[side_opp][itrack] < num_ending_wires[side_opp]) { /* The ending wires in core sblocks form N-to-N assignment problem, so can * use any pattern such as Wilton */ /* In the direct connect case, I know for sure the init mux is at the same track # * as this ending wire, but still need to find the init mux label for Fs > 3 */ - int mux = find_label_of_track(wire_mux_on_track[to_side]->data(), + int mux = find_label_of_track(wire_mux_on_track[to_side], num_wire_muxes[to_side], itrack); sblock_pattern[i][j][side_opp][to_side][itrack][0] = mux; } else { @@ -2477,7 +2301,7 @@ static void label_wire_muxes(const int chan_num, const enum Direction dir, const int max_chan_width, const bool check_cb, - std::vector* labels_ptr, + std::vector& labels, int* num_wire_muxes, int* num_wire_muxes_cb_restricted) { /* Labels the muxes on that side (seg_num, chan_num, direction). The returned array @@ -2485,8 +2309,6 @@ static void label_wire_muxes(const int chan_num, * This routine orders wire muxes by their natural order, i.e. track # * If seg_type_index == UNDEFINED, all segments in the channel are considered. Otherwise this routine * only looks at segments that belong to the specified segment type. */ - - std::vector& labels = *labels_ptr; int itrack, start, end, num_labels, num_labels_restricted, pass; bool is_endpoint; @@ -2561,14 +2383,13 @@ static void label_incoming_wires(const int chan_num, const int max_len, const enum Direction dir, const int max_chan_width, - std::vector* labels_ptr, + std::vector& labels, int* num_incoming_wires, int* num_ending_wires) { /* Labels the incoming wires on that side (seg_num, chan_num, direction). * The returned array maps a track # to a label: array[0] = , * the labels 0,1,2,.. identify consecutive incoming wires that have sblock (passing wires with sblock and ending wires) */ - std::vector& labels = *labels_ptr; int itrack, start, end, num_passing, num_ending, pass; bool sblock_exists, is_endpoint; @@ -2628,7 +2449,7 @@ static void label_incoming_wires(const int chan_num, *num_ending_wires = num_ending; } -static int find_label_of_track(int* wire_mux_on_track, +static int find_label_of_track(const std::vector& wire_mux_on_track, int num_wire_muxes, int from_track) { /* Returns the index/label in array wire_mux_on_track whose entry equals from_track. If none are diff --git a/vpr/src/route/rr_graph2.h b/vpr/src/route/rr_graph2.h index 9e02ea8ba44..9ec4c0987ec 100644 --- a/vpr/src/route/rr_graph2.h +++ b/vpr/src/route/rr_graph2.h @@ -18,10 +18,6 @@ enum e_seg_details_type { typedef vtr::NdMatrix t_sblock_pattern; -struct t_opin_connections_scratchpad { - std::array, 8> scratch; -}; - /******************* Subroutines exported by rr_graph2.c *********************/ void alloc_and_load_rr_node_indices(RRGraphBuilder& rr_graph_builder, @@ -33,27 +29,6 @@ void alloc_and_load_rr_node_indices(RRGraphBuilder& rr_graph_builder, bool verify_rr_node_indices(const DeviceGrid& grid, const t_rr_node_indices& rr_node_indices, const t_rr_graph_storage& rr_nodes); -int get_rr_node_index(int x, - int y, - t_rr_type rr_type, - 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) -void get_rr_node_indices(const t_rr_node_indices& L_rr_node_indices, - int x, - int y, - t_rr_type rr_type, - int ptc, - std::vector* indices); - -void get_rr_node_indices(const t_rr_node_indices& L_rr_node_indices, - int x, - int y, - t_rr_type rr_type, - std::vector* indices, - e_side side = NUM_SIDES); - //Returns all x-channel or y-channel wires at the specified location std::vector get_rr_node_chan_wires_at_location(const t_rr_node_indices& L_rr_node_indices, t_rr_type rr_type, @@ -152,8 +127,7 @@ int get_unidir_opin_connections(RRGraphBuilder& rr_graph_builder, vtr::NdMatrix& Fc_ofs, const int max_len, const int max_chan_width, - bool* Fc_clipped, - t_opin_connections_scratchpad* scratchpad); + bool* Fc_clipped); int get_track_to_pins(RRGraphBuilder& rr_graph_builder, int seg, @@ -188,8 +162,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, const t_chan_details& to_chan_details, const enum e_directionality directionality, const vtr::NdMatrix, 3>& switch_block_conn, - t_sb_connection_map* sb_conn_map, - t_opin_connections_scratchpad* scratchpad); + t_sb_connection_map* sb_conn_map); t_sblock_pattern alloc_sblock_pattern_lookup(const DeviceGrid& grid, const int max_chan_width); @@ -202,8 +175,7 @@ void load_sblock_pattern_lookup(const int i, const t_chan_details& chan_details_y, const int Fs, const enum e_switch_block_type switch_block_type, - t_sblock_pattern& sblock_pattern, - t_opin_connections_scratchpad* scratchpad); + t_sblock_pattern& sblock_pattern); std::unique_ptr get_seg_track_counts(const int num_sets, const std::vector& segment_inf, diff --git a/vpr/src/route/rr_graph_clock.cpp b/vpr/src/route/rr_graph_clock.cpp index a21df23affa..c94a70ffe2e 100644 --- a/vpr/src/route/rr_graph_clock.cpp +++ b/vpr/src/route/rr_graph_clock.cpp @@ -181,8 +181,8 @@ size_t ClockRRGraphBuilder::estimate_additional_nodes(const DeviceGrid& grid) { } void ClockRRGraphBuilder::add_edge(t_rr_edge_info_set* rr_edges_to_create, - int src_node, - int sink_node, + RRNodeId src_node, + RRNodeId sink_node, int arch_switch_idx) const { const auto& device_ctx = g_vpr_ctx.device(); VTR_ASSERT(arch_switch_idx < device_ctx.num_arch_switches); diff --git a/vpr/src/route/rr_graph_clock.h b/vpr/src/route/rr_graph_clock.h index dc88e57e4eb..8ec23580252 100644 --- a/vpr/src/route/rr_graph_clock.h +++ b/vpr/src/route/rr_graph_clock.h @@ -114,8 +114,8 @@ class ClockRRGraphBuilder { static size_t estimate_additional_nodes(const DeviceGrid& grid); void add_edge(t_rr_edge_info_set* rr_edges_to_create, - int src_node, - int sink_node, + RRNodeId src_node, + RRNodeId sink_node, int arch_switch_idx) const; public: diff --git a/vpr/src/route/rr_graph_storage.cpp b/vpr/src/route/rr_graph_storage.cpp index 7ec22d729f5..fd45ed12077 100644 --- a/vpr/src/route/rr_graph_storage.cpp +++ b/vpr/src/route/rr_graph_storage.cpp @@ -43,8 +43,8 @@ void t_rr_graph_storage::alloc_and_load_edges(const t_rr_edge_info_set* rr_edges for (const auto& new_edge : *rr_edges_to_create) { emplace_back_edge( - RRNodeId(new_edge.from_node), - RRNodeId(new_edge.to_node), + new_edge.from_node, + new_edge.to_node, new_edge.switch_type); } } @@ -96,8 +96,8 @@ struct edge_swapper { operator t_rr_edge_info() const { VTR_ASSERT(idx_ < storage_->edge_src_node_.size()); t_rr_edge_info info( - size_t(storage_->edge_src_node_[RREdgeId(idx_)]), - size_t(storage_->edge_dest_node_[RREdgeId(idx_)]), + storage_->edge_src_node_[RREdgeId(idx_)], + storage_->edge_dest_node_[RREdgeId(idx_)], storage_->edge_switch_[RREdgeId(idx_)]); return info;