diff --git a/libs/libarchfpga/src/device_grid.h b/libs/libarchfpga/src/device_grid.h index 80f88efbeee..c04e3f8dc4e 100644 --- a/libs/libarchfpga/src/device_grid.h +++ b/libs/libarchfpga/src/device_grid.h @@ -80,6 +80,10 @@ class DeviceGrid { inline int get_height_offset(const t_physical_tile_loc& tile_loc) const { return grid_[tile_loc.layer_num][tile_loc.x][tile_loc.y].height_offset; } + ///@brief Returns true if the given location is the root location (bottom left corner) of a tile. + inline bool is_root_location(const t_physical_tile_loc& tile_loc) const { + return get_width_offset(tile_loc) == 0 && get_height_offset(tile_loc) == 0; + } ///@brief Returns a rectangle which represents the bounding box of the tile at the given location. inline vtr::Rect get_tile_bb(const t_physical_tile_loc& tile_loc) const { diff --git a/libs/libarchfpga/src/physical_types.h b/libs/libarchfpga/src/physical_types.h index 5a32cd2df0c..36d66b76e0e 100644 --- a/libs/libarchfpga/src/physical_types.h +++ b/libs/libarchfpga/src/physical_types.h @@ -540,10 +540,13 @@ struct t_port_power { bool reverse_scaled; /* Scale by (1-prob) */ }; -//The type of Fc specification +/** + * @enum e_fc_type + * @brief The type of Fc specification + */ enum class e_fc_type { - IN, //The fc specification for an input pin - OUT //The fc specification for an output pin + IN, /**< Fc specification for an input pin. */ + OUT /**< Fc specification for an output pin. */ }; //The value type of the Fc specification @@ -1562,6 +1565,7 @@ enum e_directionality { UNI_DIRECTIONAL, BI_DIRECTIONAL }; + /* X_AXIS: Data that describes an x-directed wire segment (CHANX) * * Y_AXIS: Data that describes an y-directed wire segment (CHANY) * * BOTH_AXIS: Data that can be applied to both x-directed and y-directed wire segment */ diff --git a/libs/librrgraph/src/base/check_rr_graph.cpp b/libs/librrgraph/src/base/check_rr_graph.cpp index d23d3022baa..39e859b61dc 100644 --- a/libs/librrgraph/src/base/check_rr_graph.cpp +++ b/libs/librrgraph/src/base/check_rr_graph.cpp @@ -53,10 +53,10 @@ void check_rr_graph(const RRGraphView& rr_graph, const vtr::vector& rr_indexed_data, const DeviceGrid& grid, const t_chan_width& chan_width, - const t_graph_type graph_type, + const e_graph_type graph_type, bool is_flat) { e_route_type route_type = DETAILED; - if (graph_type == GRAPH_GLOBAL) { + if (graph_type == e_graph_type::GLOBAL) { route_type = GLOBAL; } diff --git a/libs/librrgraph/src/base/check_rr_graph.h b/libs/librrgraph/src/base/check_rr_graph.h index ee137e8a956..a869a1a7e0d 100644 --- a/libs/librrgraph/src/base/check_rr_graph.h +++ b/libs/librrgraph/src/base/check_rr_graph.h @@ -10,7 +10,7 @@ void check_rr_graph(const RRGraphView& rr_graph, const vtr::vector& rr_indexed_data, const DeviceGrid& grid, const t_chan_width& chan_width, - const t_graph_type graph_type, + const e_graph_type graph_type, bool is_flat); void check_rr_node(const RRGraphView& rr_graph, diff --git a/libs/librrgraph/src/base/get_parallel_segs.cpp b/libs/librrgraph/src/base/get_parallel_segs.cpp index d20b3066992..2fe07788a19 100644 --- a/libs/librrgraph/src/base/get_parallel_segs.cpp +++ b/libs/librrgraph/src/base/get_parallel_segs.cpp @@ -1,7 +1,5 @@ #include "get_parallel_segs.h" -/*Gets t_segment_inf for parallel segments as defined by the user. - *Segments that have BOTH_AXIS attribute value are always included in the returned vector.*/ std::vector get_parallel_segs(const std::vector& segment_inf, t_unified_to_parallel_seg_index& seg_index_map, enum e_parallel_axis parallel_axis) { diff --git a/libs/librrgraph/src/base/get_parallel_segs.h b/libs/librrgraph/src/base/get_parallel_segs.h index c88b2c88701..f25eb564056 100644 --- a/libs/librrgraph/src/base/get_parallel_segs.h +++ b/libs/librrgraph/src/base/get_parallel_segs.h @@ -4,6 +4,18 @@ #include "rr_graph_type.h" #include "physical_types.h" +/** + * @brief Returns segments aligned with a given axis, including BOTH_AXIS segments. + * + * Filters the unified segment list (`segment_inf`) to include only segments matching + * the specified `parallel_axis` or marked as `BOTH_AXIS`. Also populates `seg_index_map` + * to map unified indices to axis-specific ones. + * + * @param segment_inf Unified list of all segments. + * @param seg_index_map Map from unified to axis-specific segment indices. + * @param parallel_axis Axis to filter segments by. + * @return Filtered list of segments for the given axis. + */ std::vector get_parallel_segs(const std::vector& segment_inf, t_unified_to_parallel_seg_index& seg_index_map, enum e_parallel_axis parallel_axis); diff --git a/libs/librrgraph/src/base/rr_graph_type.h b/libs/librrgraph/src/base/rr_graph_type.h index f6c5bc7efb5..05c0cad0818 100644 --- a/libs/librrgraph/src/base/rr_graph_type.h +++ b/libs/librrgraph/src/base/rr_graph_type.h @@ -19,18 +19,32 @@ enum e_route_type { DETAILED }; -enum e_graph_type { - GRAPH_GLOBAL, /* One node per channel with wire capacity > 1 and full connectivity */ - GRAPH_BIDIR, /* Detailed bidirectional graph */ - GRAPH_UNIDIR, /* Detailed unidir graph, untilable */ - /* RESEARCH TODO: Get this option debugged */ - GRAPH_UNIDIR_TILEABLE /* Detail unidir graph with wire groups multiples of 2*L */ +/** + * @enum e_graph_type + * @brief Represents the type of routing resource graph + */ +enum class e_graph_type { + GLOBAL, ///< One node per channel with wire capacity > 1 and full connectivity + BIDIR, ///< Detailed bidirectional routing graph + UNIDIR, ///< Detailed unidirectional routing graph (non-tileable) + UNIDIR_TILEABLE ///< Tileable unidirectional graph with wire groups in multiples of 2 * L (experimental) }; -typedef enum e_graph_type t_graph_type; -/* This map is used to get indices w.r.t segment_inf_x or segment_inf_y based on parallel_axis of a segment, - * from indices w.r.t the **unified** segment vector, segment_inf in devices context which stores all segments - * regardless of their axis. (see get_parallel_segs for more details)*/ +/** + * @typedef t_unified_to_parallel_seg_index + * @brief Maps indices from the unified segment list to axis-specific segment lists. + * + * This map is used to translate indices from the unified segment vector + * (`segment_inf` in the device context, which contains all segments regardless of axis) + * to axis-specific segment vectors (`segment_inf_x` or `segment_inf_y`), based on the + * segment's parallel axis. + * + * Each entry maps a unified segment index to a pair containing: + * - The index in the corresponding axis-specific segment vector + * - The axis of the segment (X or Y) + * + * @see get_parallel_segs for more details. + */ typedef std::unordered_multimap> t_unified_to_parallel_seg_index; #endif \ No newline at end of file diff --git a/libs/librrgraph/src/base/rr_node_types.h b/libs/librrgraph/src/base/rr_node_types.h index 32cf5a71629..f8a9af655bb 100644 --- a/libs/librrgraph/src/base/rr_node_types.h +++ b/libs/librrgraph/src/base/rr_node_types.h @@ -66,7 +66,7 @@ typedef uint16_t t_edge_size; /** * @brief An iterator that dereferences to an edge index * - * Used inconjunction with vtr::Range to return ranges of edge indices + * Used in conjunction with vtr::Range to return ranges of edge indices */ class edge_idx_iterator { public: @@ -101,7 +101,7 @@ typedef vtr::Range edge_idx_range; typedef std::vector> t_arch_switch_fanin; /* - * Reistance/Capacitance data for an RR Nodes + * Resistance/Capacitance data for an RR Nodes * * In practice many RR nodes have the same values, so they are fly-weighted * to keep t_rr_node small. Each RR node holds an rc_index which allows diff --git a/libs/librrgraph/src/io/rr_graph_reader.cpp b/libs/librrgraph/src/io/rr_graph_reader.cpp index ec574080dba..b0351479f6f 100644 --- a/libs/librrgraph/src/io/rr_graph_reader.cpp +++ b/libs/librrgraph/src/io/rr_graph_reader.cpp @@ -46,7 +46,7 @@ void load_rr_file(RRGraphBuilder* rr_graph_builder, std::vector* rr_rc_data, const DeviceGrid& grid, const std::vector& arch_switch_inf, - const t_graph_type graph_type, + e_graph_type graph_type, const t_arch* arch, t_chan_width* chan_width, const enum e_base_cost_type base_cost_type, diff --git a/libs/librrgraph/src/io/rr_graph_reader.h b/libs/librrgraph/src/io/rr_graph_reader.h index 8549b712bdf..219bc902171 100644 --- a/libs/librrgraph/src/io/rr_graph_reader.h +++ b/libs/librrgraph/src/io/rr_graph_reader.h @@ -21,7 +21,7 @@ void load_rr_file(RRGraphBuilder* rr_graph_builder, std::vector* rr_rc_data, const DeviceGrid& grid, const std::vector& arch_switch_inf, - const t_graph_type graph_type, + e_graph_type graph_type, const t_arch* arch, t_chan_width* chan_width, const enum e_base_cost_type base_cost_type, diff --git a/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h b/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h index e9e83988d0b..9a0126441fb 100644 --- a/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h +++ b/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h @@ -270,7 +270,7 @@ struct RrGraphContextTypes : public uxsd::DefaultRrGraphContextTypes { class RrGraphSerializer final : public uxsd::RrGraphBase { public: RrGraphSerializer( - const t_graph_type graph_type, + const e_graph_type graph_type, const enum e_base_cost_type base_cost_type, int* wire_to_rr_ipin_switch, int* wire_to_rr_ipin_switch_between_dice, @@ -823,7 +823,7 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { auto node = (*rr_nodes_)[inode]; RRNodeId node_id = node.id(); - if (GRAPH_GLOBAL == graph_type_) { + if (e_graph_type::GLOBAL == graph_type_) { rr_graph_builder_->set_node_cost_index(node_id, RRIndexedDataId(0)); } else if (rr_graph.node_type(node.id()) == CHANX) { int seg_ind_x = find_segment_index_along_axis(segment_id, X_AXIS); @@ -2166,7 +2166,7 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { std::vector* rr_rc_data_; // Constant data for loads and writes. - const t_graph_type graph_type_; + const e_graph_type graph_type_; const enum e_base_cost_type base_cost_type_; const bool do_check_rr_graph_; const char* read_rr_graph_name_; diff --git a/libs/librrgraph/src/io/rr_graph_writer.cpp b/libs/librrgraph/src/io/rr_graph_writer.cpp index d254ae9edb7..0e48dd866aa 100644 --- a/libs/librrgraph/src/io/rr_graph_writer.cpp +++ b/libs/librrgraph/src/io/rr_graph_writer.cpp @@ -42,7 +42,7 @@ void write_rr_graph(RRGraphBuilder* rr_graph_builder, bool is_flat) { RrGraphSerializer reader( - /*graph_type=*/t_graph_type(), + /*graph_type=*/e_graph_type(), /*base_cost_type=*/e_base_cost_type(), /*wire_to_rr_ipin_switch=*/nullptr, /*wire_to_rr_ipin_switch_between_dice=*/nullptr, diff --git a/vpr/src/base/place_and_route.cpp b/vpr/src/base/place_and_route.cpp index 4ee6ce7a94a..e910d02418f 100644 --- a/vpr/src/base/place_and_route.cpp +++ b/vpr/src/base/place_and_route.cpp @@ -28,7 +28,7 @@ /******************* Subroutines local to this module ************************/ -static int compute_chan_width(int cfactor, t_chan chan_dist, float distance, float separation, t_graph_type graph_directionality); +static int compute_chan_width(int cfactor, t_chan chan_dist, float distance, float separation, e_graph_type graph_directionality); static float comp_width(t_chan* chan, float x, float separation); /************************* Subroutine Definitions ****************************/ @@ -68,8 +68,8 @@ int binary_search_place_and_route(const Netlist<>& placement_net_list, int udsd_multiplier; int warnings; - t_graph_type graph_type; - t_graph_type graph_directionality; + e_graph_type graph_type; + e_graph_type graph_directionality; /* We have chosen to pass placer_opts_ref by reference because of its large size. * * However, since the value is mutated later in the function, we declare a * @@ -80,11 +80,11 @@ int binary_search_place_and_route(const Netlist<>& placement_net_list, /* Allocate the major routing structures. */ if (router_opts.route_type == GLOBAL) { - graph_type = GRAPH_GLOBAL; - graph_directionality = GRAPH_BIDIR; + graph_type = e_graph_type::GLOBAL; + graph_directionality = e_graph_type::BIDIR; } else { - graph_type = (det_routing_arch->directionality == BI_DIRECTIONAL ? GRAPH_BIDIR : GRAPH_UNIDIR); - graph_directionality = (det_routing_arch->directionality == BI_DIRECTIONAL ? GRAPH_BIDIR : GRAPH_UNIDIR); + graph_type = (det_routing_arch->directionality == BI_DIRECTIONAL ? e_graph_type::BIDIR : e_graph_type::UNIDIR); + graph_directionality = (det_routing_arch->directionality == BI_DIRECTIONAL ? e_graph_type::BIDIR : e_graph_type::UNIDIR); } VTR_ASSERT(!net_delay.empty()); @@ -408,7 +408,7 @@ t_chan_width setup_chan_width(const t_router_opts& router_opts, /*we give plenty of tracks, this increases routability for the */ /*lookup table generation */ - t_graph_type graph_directionality; + e_graph_type graph_directionality; int width_fac; if (router_opts.fixed_channel_width == NO_FIXED_CHANNEL_WIDTH) { @@ -425,9 +425,9 @@ t_chan_width setup_chan_width(const t_router_opts& router_opts, } if (router_opts.route_type == GLOBAL) { - graph_directionality = GRAPH_BIDIR; + graph_directionality = e_graph_type::BIDIR; } else { - graph_directionality = GRAPH_UNIDIR; + graph_directionality = e_graph_type::UNIDIR; } return init_chan(width_fac, chan_width_dist, graph_directionality); @@ -441,7 +441,9 @@ t_chan_width setup_chan_width(const t_router_opts& router_opts, * is used to determine if the channel width should be rounded to an * even number. */ -t_chan_width init_chan(int cfactor, const t_chan_width_dist& chan_width_dist, t_graph_type graph_directionality) { +t_chan_width init_chan(int cfactor, + const t_chan_width_dist& chan_width_dist, + e_graph_type graph_directionality) { auto& device_ctx = g_vpr_ctx.mutable_device(); auto& grid = device_ctx.grid; @@ -513,10 +515,10 @@ t_chan_width init_chan(int cfactor, const t_chan_width_dist& chan_width_dist, t_ * @param separation The distance between two channels in the 0 to 1 coordinate system. * @param graph_directionality The directionality of the graph (unidirectional or bidirectional). */ -static int compute_chan_width(int cfactor, t_chan chan_dist, float distance, float separation, t_graph_type graph_directionality) { +static int compute_chan_width(int cfactor, t_chan chan_dist, float distance, float separation, e_graph_type graph_directionality) { int computed_width; computed_width = (int)floor(cfactor * comp_width(&chan_dist, distance, separation) + 0.5); - if ((GRAPH_BIDIR == graph_directionality) || computed_width % 2 == 0) { + if ((e_graph_type::BIDIR == graph_directionality) || computed_width % 2 == 0) { return computed_width; } else { return computed_width - 1; diff --git a/vpr/src/base/place_and_route.h b/vpr/src/base/place_and_route.h index 538996548f2..e595a2cdedb 100644 --- a/vpr/src/base/place_and_route.h +++ b/vpr/src/base/place_and_route.h @@ -41,7 +41,7 @@ t_chan_width setup_chan_width(const t_router_opts& router_opts, t_chan_width init_chan(int cfactor, const t_chan_width_dist& chan_width_dist, - t_graph_type graph_directionality); + e_graph_type graph_directionality); void post_place_sync(); diff --git a/vpr/src/base/vpr_api.cpp b/vpr/src/base/vpr_api.cpp index be6115112e4..1e1ae176805 100644 --- a/vpr/src/base/vpr_api.cpp +++ b/vpr/src/base/vpr_api.cpp @@ -1099,14 +1099,14 @@ void vpr_create_rr_graph(t_vpr_setup& vpr_setup, const t_arch& arch, int chan_wi auto det_routing_arch = &vpr_setup.RoutingArch; auto& router_opts = vpr_setup.RouterOpts; - t_graph_type graph_type; - t_graph_type graph_directionality; + e_graph_type graph_type; + e_graph_type graph_directionality; if (router_opts.route_type == GLOBAL) { - graph_type = GRAPH_GLOBAL; - graph_directionality = GRAPH_BIDIR; + graph_type = e_graph_type::GLOBAL; + graph_directionality = e_graph_type::BIDIR; } else { - graph_type = (det_routing_arch->directionality == BI_DIRECTIONAL ? GRAPH_BIDIR : GRAPH_UNIDIR); - graph_directionality = (det_routing_arch->directionality == BI_DIRECTIONAL ? GRAPH_BIDIR : GRAPH_UNIDIR); + graph_type = (det_routing_arch->directionality == BI_DIRECTIONAL ? e_graph_type::BIDIR : e_graph_type::UNIDIR); + graph_directionality = (det_routing_arch->directionality == BI_DIRECTIONAL ? e_graph_type::BIDIR : e_graph_type::UNIDIR); } t_chan_width chan_width = init_chan(chan_width_fac, arch.Chans, graph_directionality); diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index 92100562dfb..3bad2e48d3a 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -1368,193 +1368,6 @@ struct t_det_routing_arch { std::string write_rr_graph_filename; }; -/** - * @brief Lists detailed information about segmentation. [0 .. W-1]. - */ -struct t_seg_details { - /** - * @brief Length (in clbs) of the segment. - */ - int length = 0; - - /** - * @brief Index at which a segment starts in channel 0. - */ - int start = 0; - - /** - * @brief True if this segment spans the entire channel. - */ - bool longline = false; - - /** - * @brief [0..length]: true for every channel intersection, relative to the - * segment start, at which there is a switch box. - */ - std::unique_ptr sb; - - /** - * @brief [0..length]: true for every logic block along the segment at - * which there is a connection box. - */ - std::unique_ptr cb; - - /** - * @brief Index of the switch type that connects other wires to this segment. - * Note that this index is in relation to the switches from the architecture - * file, not the expanded list of switches that is built at the end of build_rr_graph. - */ - short arch_wire_switch = 0; - - /** - * @brief Index of the switch type that connects output pins (OPINs) *to* this segment. - * Note that this index is in relation to the switches from the architecture - * file, not the expanded list of switches that is built at the end of build_rr_graph. - */ - short arch_opin_switch = 0; - - /** - * @brief Index of the switch type that connects output pins (OPINs) *to* this segment - * from *another dice*. Note that this index is in relation to the switches from the - * architecture file, not the expanded list of switches that is built at the end of - * build_rr_graph. - */ - short arch_inter_die_switch = 0; - - /** - * @brief Resistance of a routing track, per unit logic block length. - */ - float Rmetal = 0; - - /** - * @brief Capacitance of a routing track, per unit logic block length. - */ - float Cmetal = 0; - - bool twisted = false; - - /** - * @brief Direction of the segment. - */ - enum Direction direction = Direction::NONE; - - /** - * @brief Index of the first logic block in the group. - */ - int group_start = 0; - - /** - * @brief Size of the group. - */ - int group_size = 0; - - /** - * @brief Index of the first logic block in the segment. - */ - int seg_start = 0; - - /** - * @brief Index of the last logic block in the segment. - */ - int seg_end = 0; - - /** - * @brief index of the segment type used for this track. - * Note that this index will store the index of the segment - * relative to its **parallel** segment types, not all segments - * as stored in device_ctx. Look in rr_graph.cpp: build_rr_graph - * for details but here is an example: say our segment_inf_vec in - * device_ctx is as follows: [seg_a_x, seg_b_x, seg_a_y, seg_b_y] - * when building the rr_graph, static segment_inf_vectors will be - * created for each direction, thus you will have the following - * 2 vectors: X_vec =[seg_a_x,seg_b_x] and Y_vec = [seg_a_y,seg_b_y]. - * As a result, e.g. seg_b_y::index == 1 (index in Y_vec) - * and != 3 (index in device_ctx segment_inf_vec). - */ - int index = 0; - - /** - * @brief index is relative to the segment_inf vec as stored in device_ctx. - * Note that the above vector is **unifies** both x-parallel and - * y-parallel segments and is loaded up originally in read_xml_arch_file.cpp - */ - int abs_index = 0; - - /** - * @brief Used for power - */ - float Cmetal_per_m = 0; - - /** - * @brief Name of the segment type. - */ - std::string type_name; -}; - -class t_chan_seg_details { - public: - t_chan_seg_details() = default; - t_chan_seg_details(const t_seg_details* init_seg_details) - : length_(init_seg_details->length) - , seg_detail_(init_seg_details) {} - - public: - int length() const { return length_; } - int seg_start() const { return seg_start_; } - int seg_end() const { return seg_end_; } - - int start() const { return seg_detail_->start; } - bool longline() const { return seg_detail_->longline; } - - int group_start() const { return seg_detail_->group_start; } - int group_size() const { return seg_detail_->group_size; } - - bool cb(int pos) const { return seg_detail_->cb[pos]; } - bool sb(int pos) const { return seg_detail_->sb[pos]; } - - float Rmetal() const { return seg_detail_->Rmetal; } - float Cmetal() const { return seg_detail_->Cmetal; } - float Cmetal_per_m() const { return seg_detail_->Cmetal_per_m; } - - short arch_wire_switch() const { return seg_detail_->arch_wire_switch; } - short arch_opin_switch() const { return seg_detail_->arch_opin_switch; } - short arch_inter_die_switch() const { return seg_detail_->arch_inter_die_switch; } - - Direction direction() const { return seg_detail_->direction; } - - int index() const { return seg_detail_->index; } - int abs_index() const { return seg_detail_->abs_index; } - - const vtr::string_view type_name() const { - return vtr::string_view( - seg_detail_->type_name.data(), - seg_detail_->type_name.size()); - } - - public: //Modifiers - void set_length(int new_len) { length_ = new_len; } - void set_seg_start(int new_start) { seg_start_ = new_start; } - void set_seg_end(int new_end) { seg_end_ = new_end; } - - private: - //The only unique information about a channel segment is it's start/end - //and length. All other information is shared across segment types, - //so we use a flyweight to the t_seg_details which defines that info. - // - //To preserve the illusion of uniqueness we wrap all t_seg_details members - //so it appears transparent -- client code of this class doesn't need to - //know about t_seg_details. - int length_ = -1; - int seg_start_ = -1; - int seg_end_ = -1; - const t_seg_details* seg_detail_ = nullptr; -}; - -/* Defines a 3-D array of t_chan_seg_details data structures (one per-each horizontal and vertical channel) - * once allocated in rr_graph2.cpp, is can be accessed like: [0..grid.width()][0..grid.height()][0..num_tracks-1] - */ -typedef vtr::NdMatrix t_chan_details; - constexpr bool is_pin(e_rr_type type) { return (type == IPIN || type == OPIN); } constexpr bool is_chan(e_rr_type type) { return (type == CHANX || type == CHANY); } constexpr bool is_src_sink(e_rr_type type) { return (type == SOURCE || type == SINK); } diff --git a/vpr/src/route/build_switchblocks.cpp b/vpr/src/route/build_switchblocks.cpp index c0c23c3fe0a..a0dbe35bb1c 100644 --- a/vpr/src/route/build_switchblocks.cpp +++ b/vpr/src/route/build_switchblocks.cpp @@ -141,6 +141,7 @@ #include "physical_types.h" #include "parse_switchblocks.h" #include "vtr_expr_eval.h" +#include "rr_types.h" using vtr::FormulaParser; using vtr::t_formula_data; diff --git a/vpr/src/route/build_switchblocks.h b/vpr/src/route/build_switchblocks.h index 71b24699b5e..917bd16620b 100644 --- a/vpr/src/route/build_switchblocks.h +++ b/vpr/src/route/build_switchblocks.h @@ -7,8 +7,8 @@ #include "physical_types.h" #include "vpr_types.h" #include "device_grid.h" - #include "vtr_random.h" +#include "rr_types.h" /************ Classes, structs, typedefs ************/ diff --git a/vpr/src/route/route.cpp b/vpr/src/route/route.cpp index a237c5368ff..2c077f0c8a8 100644 --- a/vpr/src/route/route.cpp +++ b/vpr/src/route/route.cpp @@ -34,14 +34,14 @@ bool route(const Netlist<>& net_list, VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "No nets to route\n"); } - t_graph_type graph_type; - t_graph_type graph_directionality; + e_graph_type graph_type; + e_graph_type graph_directionality; if (router_opts.route_type == GLOBAL) { - graph_type = GRAPH_GLOBAL; - graph_directionality = GRAPH_BIDIR; + graph_type = e_graph_type::GLOBAL; + graph_directionality = e_graph_type::BIDIR; } else { - graph_type = (det_routing_arch->directionality == BI_DIRECTIONAL ? GRAPH_BIDIR : GRAPH_UNIDIR); - graph_directionality = (det_routing_arch->directionality == BI_DIRECTIONAL ? GRAPH_BIDIR : GRAPH_UNIDIR); + graph_type = (det_routing_arch->directionality == BI_DIRECTIONAL ? e_graph_type::BIDIR : e_graph_type::UNIDIR); + graph_directionality = (det_routing_arch->directionality == BI_DIRECTIONAL ? e_graph_type::BIDIR : e_graph_type::UNIDIR); } /* Set the channel widths */ diff --git a/vpr/src/route/route_utils.cpp b/vpr/src/route/route_utils.cpp index 90a931574ce..aab9e952315 100644 --- a/vpr/src/route/route_utils.cpp +++ b/vpr/src/route/route_utils.cpp @@ -472,14 +472,14 @@ void try_graph(int width_fac, bool is_flat) { auto& device_ctx = g_vpr_ctx.mutable_device(); - t_graph_type graph_type; - t_graph_type graph_directionality; + e_graph_type graph_type; + e_graph_type graph_directionality; if (router_opts.route_type == GLOBAL) { - graph_type = GRAPH_GLOBAL; - graph_directionality = GRAPH_BIDIR; + graph_type = e_graph_type::GLOBAL; + graph_directionality = e_graph_type::BIDIR; } else { - graph_type = (det_routing_arch->directionality == BI_DIRECTIONAL ? GRAPH_BIDIR : GRAPH_UNIDIR); - graph_directionality = (det_routing_arch->directionality == BI_DIRECTIONAL ? GRAPH_BIDIR : GRAPH_UNIDIR); + graph_type = (det_routing_arch->directionality == BI_DIRECTIONAL ? e_graph_type::BIDIR : e_graph_type::UNIDIR); + graph_directionality = (det_routing_arch->directionality == BI_DIRECTIONAL ? e_graph_type::BIDIR : e_graph_type::UNIDIR); } /* Set the channel widths */ @@ -517,7 +517,7 @@ void update_draw_pres_fac(const float /*new_pres_fac*/) { #ifndef NO_GRAPHICS void update_router_info_and_check_bp(bp_router_type type, int net_id) { t_draw_state* draw_state = get_draw_state_vars(); - if (draw_state->list_of_breakpoints.size() != 0) { + if (!draw_state->list_of_breakpoints.empty()) { if (type == BP_ROUTE_ITER) get_bp_state_globals()->get_glob_breakpoint_state()->router_iter++; else if (type == BP_NET_ID) diff --git a/vpr/src/route/router_delay_profiling.cpp b/vpr/src/route/router_delay_profiling.cpp index 6eb515ccb71..68fb441a369 100644 --- a/vpr/src/route/router_delay_profiling.cpp +++ b/vpr/src/route/router_delay_profiling.cpp @@ -249,14 +249,14 @@ void alloc_routing_structs(const t_chan_width& chan_width, const std::vector& directs, bool is_flat) { int warnings; - t_graph_type graph_type; + e_graph_type graph_type; auto& device_ctx = g_vpr_ctx.mutable_device(); if (router_opts.route_type == GLOBAL) { - graph_type = GRAPH_GLOBAL; + graph_type = e_graph_type::GLOBAL; } else { - graph_type = (det_routing_arch->directionality == BI_DIRECTIONAL ? GRAPH_BIDIR : GRAPH_UNIDIR); + graph_type = (det_routing_arch->directionality == BI_DIRECTIONAL ? e_graph_type::BIDIR : e_graph_type::UNIDIR); } create_rr_graph(graph_type, diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index b8fb440a172..a5a72fbe878 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -42,18 +42,6 @@ //#define VERBOSE //used for getting the exact count of each edge type and printing it to std out. -struct t_mux { - int size; - t_mux* next; -}; - -struct t_mux_size_distribution { - int mux_count; - int max_index; - int* distr; - t_mux_size_distribution* next; -}; - struct t_clb_to_clb_directs { t_physical_tile_type_ptr from_clb_type; int from_clb_pin_start_index; @@ -72,12 +60,6 @@ struct t_pin_loc { e_side side; }; -struct t_pin_spec { - t_rr_type pin_type; - int pin_ptc; - RRNodeId pin_rr_node_id; -}; - /******************* Variables local to this module. ***********************/ /********************* Subroutines local to this module. *******************/ @@ -115,11 +97,11 @@ bool channel_widths_unchanged(const t_chan_width& current, const t_chan_width& p static vtr::NdMatrix, 5> alloc_and_load_pin_to_track_map(const e_pin_type pin_type, const vtr::Matrix& Fc, const t_physical_tile_type_ptr tile_type, - const std::set type_layer, + const std::set& type_layer, const std::vector& perturb_switch_pattern, const e_directionality directionality, const std::vector& seg_inf, - const int* sets_per_seg_type); + const std::vector& sets_per_seg_type); /** * @brief This routine calculates pin connections to tracks for a specific type and a specific segment based on the Fc value * defined for each pin in the architecture file. This routine is called twice for each combination of block type and segment @@ -153,7 +135,7 @@ static void advance_to_next_block_side(t_physical_tile_type_ptr tile_type, int& static vtr::NdMatrix, 5> alloc_and_load_track_to_pin_lookup(vtr::NdMatrix, 5> pin_to_track_map, const vtr::Matrix& Fc, const t_physical_tile_type_ptr tile_type, - const std::set type_layer, + const std::set& type_layer, const int width, const int height, const int num_pins, @@ -173,7 +155,7 @@ static void build_bidir_rr_opins(RRGraphBuilder& rr_graph_builder, const t_chan_details& chan_details_y, const DeviceGrid& grid, const std::vector& directs, - const t_clb_to_clb_directs* clb_to_clb_directs, + const std::vector& clb_to_clb_directs, const int num_seg_types); static void build_unidir_rr_opins(RRGraphBuilder& rr_graph_builder, @@ -193,7 +175,7 @@ static void build_unidir_rr_opins(RRGraphBuilder& rr_graph_builder, bool* Fc_clipped, const t_unified_to_parallel_seg_index& seg_index_map, const std::vector& directs, - const t_clb_to_clb_directs* clb_to_clb_directs, + const std::vector& clb_to_clb_directs, const int num_seg_types, int& edge_count); @@ -207,7 +189,7 @@ static int get_opin_direct_connections(RRGraphBuilder& rr_graph_builder, RRNodeId from_rr_node, t_rr_edge_info_set& rr_edges_to_create, const std::vector& directs, - const t_clb_to_clb_directs* clb_to_clb_directs); + const std::vector& clb_to_clb_directs); static std::function alloc_and_load_rr_graph(RRGraphBuilder& rr_graph_builder, t_rr_graph_storage& L_rr_node, @@ -236,7 +218,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder const enum e_directionality directionality, bool* Fc_clipped, const std::vector& directs, - const t_clb_to_clb_directs* clb_to_clb_directs, + const std::vector& clb_to_clb_directs, bool is_global_graph, const enum e_clock_modeling clock_modeling, bool is_flat, @@ -381,7 +363,7 @@ static void check_all_tracks_reach_pins(t_logical_block_type_ptr type, static std::vector> alloc_and_load_perturb_ipins(const int L_num_types, const int num_seg_types, - const int* sets_per_seg_type, + const std::vector& sets_per_seg_type, const std::vector>& Fc_in, const std::vector>& Fc_out, const enum e_directionality directionality); @@ -535,7 +517,7 @@ static float get_min_delay_to_chain(t_physical_tile_type_ptr physical_type, int pin_physical_num, int chain_sink_pin); -static std::unordered_set get_chain_pins(std::vector chain); +static std::unordered_set get_chain_pins(const std::vector& chain); static void build_rr_chan(RRGraphBuilder& rr_graph_builder, const int layer, @@ -587,7 +569,7 @@ void alloc_and_load_edges(RRGraphBuilder& rr_graph_builder, static void alloc_and_load_rr_switch_inf(RRGraphBuilder& rr_graph_builder, std::vector>& switch_fanin_remap, - const std::map arch_sw_inf, + const std::map& arch_sw_inf, const float R_minW_nmos, const float R_minW_pmos, const int wire_to_arch_ipin_switch, @@ -613,15 +595,15 @@ static void rr_graph_externals(const std::vector& segment_inf, int wire_to_rr_ipin_switch, enum e_base_cost_type base_cost_type); -static t_clb_to_clb_directs* alloc_and_load_clb_to_clb_directs(const std::vector& directs, const int delayless_switch); +static std::vector alloc_and_load_clb_to_clb_directs(const std::vector& directs, + int delayless_switch); -static t_seg_details* alloc_and_load_global_route_seg_details(const int global_route_switch, - int* num_seg_details = nullptr); +static std::vector alloc_and_load_global_route_seg_details(const int global_route_switch); static std::vector> alloc_and_load_actual_fc(const std::vector& types, const int max_pins, const std::vector& segment_inf, - const int* sets_per_seg_type, + const std::vector& sets_per_seg_type, const t_chan_width* nodes_per_chan, const e_fc_type fc_type, const enum e_directionality directionality, @@ -720,7 +702,7 @@ static float get_delay_directly_connected_pins(t_physical_tile_type_ptr physical static void process_non_config_sets(); -static void build_rr_graph(const t_graph_type graph_type, +static void build_rr_graph(e_graph_type graph_type, const std::vector& types, const DeviceGrid& grid, t_chan_width nodes_per_chan, @@ -743,7 +725,7 @@ static void build_rr_graph(const t_graph_type graph_type, int* Warnings, const int route_verbosity); -static void build_intra_cluster_rr_graph(const t_graph_type graph_type, +static void build_intra_cluster_rr_graph(e_graph_type graph_type, const DeviceGrid& grid, const std::vector& types, const RRGraphView& rr_graph, @@ -765,7 +747,7 @@ static int get_delayless_switch_id(t_det_routing_arch* det_routing_arch, /******************* Subroutine definitions *******************************/ -void create_rr_graph(const t_graph_type graph_type, +void create_rr_graph(e_graph_type graph_type, const std::vector& block_types, const DeviceGrid& grid, const t_chan_width& nodes_per_chan, @@ -1049,7 +1031,7 @@ bool channel_widths_unchanged(const t_chan_width& current, const t_chan_width& p return true; //Identical } -static void build_rr_graph(const t_graph_type graph_type, +static void build_rr_graph(e_graph_type graph_type, const std::vector& types, const DeviceGrid& grid, t_chan_width nodes_per_chan, @@ -1077,9 +1059,9 @@ static void build_rr_graph(const t_graph_type graph_type, *Warnings = RR_GRAPH_NO_WARN; /* Decode the graph_type */ - bool is_global_graph = ((GRAPH_GLOBAL == graph_type) ? true : false); - bool use_full_seg_groups = ((GRAPH_UNIDIR_TILEABLE == graph_type) ? true : false); - enum e_directionality directionality = ((GRAPH_BIDIR == graph_type) ? BI_DIRECTIONAL : UNI_DIRECTIONAL); + bool is_global_graph = (e_graph_type::GLOBAL == graph_type); + bool use_full_seg_groups = (e_graph_type::UNIDIR_TILEABLE == graph_type); + enum e_directionality directionality = (e_graph_type::BIDIR == graph_type) ? BI_DIRECTIONAL : UNI_DIRECTIONAL; if (is_global_graph) { directionality = BI_DIRECTIONAL; } @@ -1095,32 +1077,26 @@ static void build_rr_graph(const t_graph_type graph_type, auto& device_ctx = g_vpr_ctx.mutable_device(); const auto& rr_graph = device_ctx.rr_graph; - t_clb_to_clb_directs* clb_to_clb_directs = nullptr; - if (!directs.empty()) { - clb_to_clb_directs = alloc_and_load_clb_to_clb_directs(directs, delayless_switch); - } + std::vector clb_to_clb_directs = alloc_and_load_clb_to_clb_directs(directs, delayless_switch); /* START SEG_DETAILS */ - size_t num_segments = segment_inf.size(); + const size_t num_segments = segment_inf.size(); device_ctx.rr_graph_builder.reserve_segments(num_segments); for (size_t iseg = 0; iseg < num_segments; ++iseg) { device_ctx.rr_graph_builder.add_rr_segment(segment_inf[iseg]); } - int num_seg_details_x = 0; - int num_seg_details_y = 0; - - t_seg_details* seg_details_x = nullptr; - t_seg_details* seg_details_y = nullptr; - t_unified_to_parallel_seg_index segment_index_map; std::vector segment_inf_x = get_parallel_segs(segment_inf, segment_index_map, X_AXIS); std::vector segment_inf_y = get_parallel_segs(segment_inf, segment_index_map, Y_AXIS); + std::vector seg_details_x; + std::vector seg_details_y; + if (is_global_graph) { /* Sets up a single unit length segment type for global routing. */ - seg_details_x = alloc_and_load_global_route_seg_details(global_route_switch, &num_seg_details_x); - seg_details_y = alloc_and_load_global_route_seg_details(global_route_switch, &num_seg_details_y); + seg_details_x = alloc_and_load_global_route_seg_details(global_route_switch); + seg_details_y = alloc_and_load_global_route_seg_details(global_route_switch); } else { /* Setup segments including distributing tracks and staggering. @@ -1135,13 +1111,11 @@ static void build_rr_graph(const t_graph_type graph_type, /*Get x & y segments separately*/ seg_details_x = alloc_and_load_seg_details(&max_chan_width_x, max_dim, segment_inf_x, - use_full_seg_groups, directionality, - &num_seg_details_x); + use_full_seg_groups, directionality); seg_details_y = alloc_and_load_seg_details(&max_chan_width_y, max_dim, segment_inf_y, - use_full_seg_groups, directionality, - &num_seg_details_y); + use_full_seg_groups, directionality); if (nodes_per_chan.x_max != max_chan_width_x || nodes_per_chan.y_max != max_chan_width_y) { nodes_per_chan.x_max = max_chan_width_x; @@ -1170,8 +1144,7 @@ static void build_rr_graph(const t_graph_type graph_type, t_chan_details chan_details_x; t_chan_details chan_details_y; - alloc_and_load_chan_details(grid, &nodes_per_chan, - num_seg_details_x, num_seg_details_y, + alloc_and_load_chan_details(grid, nodes_per_chan, seg_details_x, seg_details_y, chan_details_x, chan_details_y); @@ -1209,14 +1182,9 @@ static void build_rr_graph(const t_graph_type graph_type, total_sets_x /= 2; total_sets_y /= 2; } - auto sets_per_seg_type_x = get_seg_track_counts(total_sets_x, segment_inf_x, use_full_seg_groups); - auto sets_per_seg_type_y = get_seg_track_counts(total_sets_y, segment_inf_y, use_full_seg_groups); - auto sets_per_seg_type = get_seg_track_counts(total_sets, segment_inf, use_full_seg_groups); - - auto sets_test = get_ordered_seg_track_counts(segment_inf_x, segment_inf_y, segment_inf, sets_per_seg_type_x, sets_per_seg_type_y); - - //VTR_ASSERT_MSG(sets_test==sets_per_seg_type, - // "Not equal combined output after combining segs " ); + std::vector sets_per_seg_type_x = get_seg_track_counts(total_sets_x, segment_inf_x, use_full_seg_groups); + std::vector sets_per_seg_type_y = get_seg_track_counts(total_sets_y, segment_inf_y, use_full_seg_groups); + std::vector sets_per_seg_type = get_seg_track_counts(total_sets, segment_inf, use_full_seg_groups); if (is_global_graph) { //All pins can connect during global routing @@ -1225,19 +1193,19 @@ static void build_rr_graph(const t_graph_type graph_type, Fc_out = std::vector>(types.size(), ones); } else { bool Fc_clipped = false; - Fc_in = alloc_and_load_actual_fc(types, max_pins, segment_inf, sets_per_seg_type.get(), &nodes_per_chan, + Fc_in = alloc_and_load_actual_fc(types, max_pins, segment_inf, sets_per_seg_type, &nodes_per_chan, e_fc_type::IN, directionality, &Fc_clipped, is_flat); if (Fc_clipped) { *Warnings |= RR_GRAPH_WARN_FC_CLIPPED; } Fc_clipped = false; - Fc_out = alloc_and_load_actual_fc(types, max_pins, segment_inf, sets_per_seg_type.get(), &nodes_per_chan, + Fc_out = alloc_and_load_actual_fc(types, max_pins, segment_inf, sets_per_seg_type, &nodes_per_chan, e_fc_type::OUT, directionality, &Fc_clipped, is_flat); if (Fc_clipped) { *Warnings |= RR_GRAPH_WARN_FC_CLIPPED; } - for (const auto& type : types) { + for (const t_physical_tile_type& type : types) { int i = type.index; /* Skip "EMPTY" */ @@ -1267,7 +1235,7 @@ static void build_rr_graph(const t_graph_type graph_type, } auto perturb_ipins = alloc_and_load_perturb_ipins(types.size(), segment_inf.size(), - sets_per_seg_type.get(), Fc_in, Fc_out, directionality); + sets_per_seg_type, Fc_in, Fc_out, directionality); /* END FC */ /* Alloc node lookups, count nodes, alloc rr nodes */ @@ -1339,10 +1307,10 @@ static void build_rr_graph(const t_graph_type graph_type, /* it looks like we get unbalanced muxing from this switch block code with Fs > 3 */ VTR_ASSERT(Fs == 3); - unidir_sb_pattern = alloc_sblock_pattern_lookup(grid, &nodes_per_chan); + unidir_sb_pattern = alloc_sblock_pattern_lookup(grid, nodes_per_chan); 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, + load_sblock_pattern_lookup(i, j, grid, nodes_per_chan, chan_details_x, chan_details_y, Fs, sb_type, unidir_sb_pattern); } @@ -1384,12 +1352,12 @@ static void build_rr_graph(const t_graph_type graph_type, ipin_to_track_map_x[itype] = alloc_and_load_pin_to_track_map(RECEIVER, Fc_in[itype], &types[itype], type_layer, perturb_ipins[itype], directionality, - segment_inf_x, sets_per_seg_type_x.get()); + segment_inf_x, sets_per_seg_type_x); ipin_to_track_map_y[itype] = alloc_and_load_pin_to_track_map(RECEIVER, Fc_in[itype], &types[itype], type_layer, perturb_ipins[itype], directionality, - segment_inf_y, sets_per_seg_type_y.get()); + segment_inf_y, sets_per_seg_type_y); track_to_pin_lookup_x[itype] = alloc_and_load_track_to_pin_lookup(ipin_to_track_map_x[itype], Fc_in[itype], &types[itype], @@ -1426,7 +1394,7 @@ static void build_rr_graph(const t_graph_type graph_type, max_chan_width, segment_inf); opin_to_track_map[itype] = alloc_and_load_pin_to_track_map(DRIVER, Fc_out[itype], &types[itype], type_layer, perturb_opins, directionality, - segment_inf, sets_per_seg_type.get()); + segment_inf, sets_per_seg_type); } } /* END OPIN MAP */ @@ -1482,7 +1450,7 @@ static void build_rr_graph(const t_graph_type graph_type, } /* Update rr_nodes capacities if global routing */ - if (graph_type == GRAPH_GLOBAL) { + if (graph_type == e_graph_type::GLOBAL) { // Using num_rr_nodes here over device_ctx.rr_nodes.size() because // clock_modeling::DEDICATED_NETWORK will append some rr nodes after // the regular graph. @@ -1499,7 +1467,7 @@ static void build_rr_graph(const t_graph_type graph_type, } /*Update rr_nodes ptc_twist_incr number if we are creating tileable graph*/ - if (graph_type == GRAPH_UNIDIR_TILEABLE) { + if (graph_type == e_graph_type::UNIDIR_TILEABLE) { device_ctx.rr_graph_builder.resize_ptc_twist_incr(num_rr_nodes); for (int rr_node_id = 0; rr_node_id < num_rr_nodes; rr_node_id++) { auto node_type = rr_graph.node_type(RRNodeId(rr_node_id)); @@ -1547,34 +1515,17 @@ static void build_rr_graph(const t_graph_type graph_type, graph_type, is_flat); - /* Free all temp structs */ - delete[] seg_details_x; - delete[] seg_details_y; - - seg_details_x = nullptr; - seg_details_y = nullptr; - if (!chan_details_x.empty() || !chan_details_y.empty()) { - free_chan_details(chan_details_x, chan_details_y); - } - if (sb_conn_map) { free_switchblock_permutations(sb_conn_map); sb_conn_map = nullptr; } - track_to_pin_lookup_x.clear(); - track_to_pin_lookup_y.clear(); - - if (clb_to_clb_directs != nullptr) { - delete[] clb_to_clb_directs; - } - // We are done with building the RR Graph. Thus, we can clear the storages only used // to build the RR Graph device_ctx.rr_graph_builder.clear_temp_storage(); } -static void build_intra_cluster_rr_graph(const t_graph_type graph_type, +static void build_intra_cluster_rr_graph(e_graph_type graph_type, const DeviceGrid& grid, const std::vector& types, const RRGraphView& rr_graph, @@ -1719,7 +1670,7 @@ void build_tile_rr_graph(RRGraphBuilder& rr_graph_builder, * of rr_nodes to index into the rr_switch_inf array. */ static void alloc_and_load_rr_switch_inf(RRGraphBuilder& rr_graph_builder, std::vector>& switch_fanin_remap, - const std::map arch_sw_inf, + const std::map& arch_sw_inf, const float R_minW_nmos, const float R_minW_pmos, const int wire_to_arch_ipin_switch, @@ -1925,7 +1876,7 @@ static void rr_graph_externals(const std::vector& segment_inf, static std::vector> alloc_and_load_perturb_ipins(const int L_num_types, const int num_seg_types, - const int* sets_per_seg_type, + const std::vector& sets_per_seg_type, const std::vector>& Fc_in, const std::vector>& Fc_out, const enum e_directionality directionality) { @@ -1976,33 +1927,27 @@ static std::vector> alloc_and_load_perturb_ipins(const int L_n return result; } -static t_seg_details* alloc_and_load_global_route_seg_details(const int global_route_switch, - int* num_seg_details) { - t_seg_details* seg_details = new t_seg_details[1]; - - seg_details->index = 0; - seg_details->abs_index = 0; - seg_details->length = 1; - seg_details->arch_wire_switch = global_route_switch; - seg_details->arch_opin_switch = global_route_switch; - seg_details->longline = false; - seg_details->direction = Direction::BIDIR; - seg_details->Cmetal = 0.0; - seg_details->Rmetal = 0.0; - seg_details->start = 1; - seg_details->cb = std::make_unique(1); - seg_details->cb[0] = true; - seg_details->sb = std::make_unique(2); - seg_details->sb[0] = true; - seg_details->sb[1] = true; - seg_details->group_size = 1; - seg_details->group_start = 0; - seg_details->seg_start = -1; - seg_details->seg_end = -1; - - if (num_seg_details) { - *num_seg_details = 1; - } +static std::vector alloc_and_load_global_route_seg_details(const int global_route_switch) { + std::vector seg_details(1); + + seg_details[0].index = 0; + seg_details[0].abs_index = 0; + seg_details[0].length = 1; + seg_details[0].arch_wire_switch = global_route_switch; + seg_details[0].arch_opin_switch = global_route_switch; + seg_details[0].longline = false; + seg_details[0].direction = Direction::BIDIR; + seg_details[0].Cmetal = 0.0; + seg_details[0].Rmetal = 0.0; + seg_details[0].start = 1; + seg_details[0].cb = std::make_unique(1); + seg_details[0].cb[0] = true; + seg_details[0].sb = std::make_unique(2); + seg_details[0].sb[0] = true; + seg_details[0].sb[1] = true; + seg_details[0].group_size = 1; + seg_details[0].group_start = 0; + return seg_details; } @@ -2010,7 +1955,7 @@ static t_seg_details* alloc_and_load_global_route_seg_details(const int global_r static std::vector> alloc_and_load_actual_fc(const std::vector& types, const int max_pins, const std::vector& segment_inf, - const int* sets_per_seg_type, + const std::vector& sets_per_seg_type, const t_chan_width* nodes_per_chan, const e_fc_type fc_type, const enum e_directionality directionality, @@ -2030,7 +1975,7 @@ static std::vector> alloc_and_load_actual_fc(const std::vector< VTR_ASSERT((nodes_per_chan->x_max % fac) == 0 && (nodes_per_chan->y_max % fac) == 0); - for (const auto& type : types) { //Skip EMPTY + for (const t_physical_tile_type& type : types) { //Skip EMPTY int itype = type.index; for (const t_fc_specification& fc_spec : type.fc_specs) { @@ -2048,7 +1993,7 @@ static std::vector> alloc_and_load_actual_fc(const std::vector< } else { /* General case indicating that this pin connects to general-purpose routing */ - //Calculate how many connections there should be accross all the pins in this fc_spec + //Calculate how many connections there should be across all the pins in this fc_spec int total_connections = 0; if (fc_spec.fc_value_type == e_fc_value_type::FRACTIONAL) { float conns_per_pin = fac * sets_per_seg_type[iseg] * fc_spec.fc_value; @@ -2149,7 +2094,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder const enum e_directionality directionality, bool* Fc_clipped, const std::vector& directs, - const t_clb_to_clb_directs* clb_to_clb_directs, + const std::vector& clb_to_clb_directs, bool is_global_graph, const enum e_clock_modeling clock_modeling, bool /*is_flat*/, @@ -2732,7 +2677,7 @@ static void build_bidir_rr_opins(RRGraphBuilder& rr_graph_builder, const t_chan_details& chan_details_y, const DeviceGrid& grid, const std::vector& directs, - const t_clb_to_clb_directs* clb_to_clb_directs, + const std::vector& clb_to_clb_directs, const int num_seg_types) { //Don't connect pins which are not adjacent to channels around the perimeter if ((i == 0 && side != RIGHT) @@ -3167,7 +3112,7 @@ static float get_min_delay_to_chain(t_physical_tile_type_ptr physical_type, return min_delay; } -static std::unordered_set get_chain_pins(std::vector chain) { +static std::unordered_set get_chain_pins(const std::vector& chain) { std::unordered_set chain_pins; for (auto node : chain) { chain_pins.insert(node.pin_physical_num); @@ -3432,11 +3377,11 @@ void alloc_and_load_edges(RRGraphBuilder& rr_graph_builder, const t_rr_edge_info static vtr::NdMatrix, 5> alloc_and_load_pin_to_track_map(const e_pin_type pin_type, const vtr::Matrix& Fc, const t_physical_tile_type_ptr tile_type, - const std::set type_layer, + const std::set& type_layer, const std::vector& perturb_switch_pattern, const e_directionality directionality, const std::vector& seg_inf, - const int* sets_per_seg_type) { + const std::vector& sets_per_seg_type) { /* allocate 'result' matrix and initialize entries to OPEN. also allocate and intialize matrix which will be * used to index into the correct entries when loading up 'result' */ auto& grid = g_vpr_ctx.device().grid; @@ -4143,7 +4088,7 @@ static void check_all_tracks_reach_pins(t_logical_block_type_ptr type, static vtr::NdMatrix, 5> alloc_and_load_track_to_pin_lookup(vtr::NdMatrix, 5> pin_to_track_map, const vtr::Matrix& Fc, const t_physical_tile_type_ptr tile_type, - const std::set type_layer, + const std::set& type_layer, const int type_width, const int type_height, const int num_pins, @@ -4232,7 +4177,7 @@ static void build_unidir_rr_opins(RRGraphBuilder& rr_graph_builder, bool* Fc_clipped, const t_unified_to_parallel_seg_index& seg_index_map, const std::vector& directs, - const t_clb_to_clb_directs* clb_to_clb_directs, + const std::vector& clb_to_clb_directs, const int num_seg_types, int& rr_edge_count) { /* @@ -4341,21 +4286,18 @@ static void build_unidir_rr_opins(RRGraphBuilder& rr_graph_builder, * This data structure supplements the the info in the "directs" data structure * TODO: The function that does this parsing in placement is poorly done because it lacks generality on heterogeniety, should replace with this one */ -static t_clb_to_clb_directs* alloc_and_load_clb_to_clb_directs(const std::vector& directs, int delayless_switch) { - t_clb_to_clb_directs* clb_to_clb_directs; - t_physical_tile_type_ptr physical_tile = nullptr; - t_physical_tile_port tile_port; - +static std::vector alloc_and_load_clb_to_clb_directs(const std::vector& directs, + int delayless_switch) { auto& device_ctx = g_vpr_ctx.device(); const int num_directs = directs.size(); - clb_to_clb_directs = new t_clb_to_clb_directs[num_directs]; + std::vector clb_to_clb_directs(num_directs); for (int i = 0; i < num_directs; i++) { //clb_to_clb_directs[i].from_clb_type; clb_to_clb_directs[i].from_clb_pin_start_index = 0; clb_to_clb_directs[i].from_clb_pin_end_index = 0; - //clb_to_clb_directs[i]. t_physical_tile_type_ptr to_clb_type; + //clb_to_clb_directs[i].to_clb_type; clb_to_clb_directs[i].to_clb_pin_start_index = 0; clb_to_clb_directs[i].to_clb_pin_end_index = 0; clb_to_clb_directs[i].switch_index = 0; @@ -4364,20 +4306,15 @@ static t_clb_to_clb_directs* alloc_and_load_clb_to_clb_directs(const std::vector // Parse out the pb_type name, port name, and pin range auto [start_pin_index, end_pin_index, tile_name, port_name] = parse_direct_pin_name(directs[i].from_pin, directs[i].line); + t_physical_tile_type_ptr physical_tile = nullptr; // Figure out which type, port, and pin is used - for (const t_physical_tile_type& type : device_ctx.physical_tile_types) { - if (tile_name == type.name) { - physical_tile = &type; - break; - } - } - + physical_tile = find_tile_type_by_name(tile_name, device_ctx.physical_tile_types); if (physical_tile == nullptr) { VPR_THROW(VPR_ERROR_ARCH, "Unable to find block %s.\n", tile_name.c_str()); } - clb_to_clb_directs[i].from_clb_type = physical_tile; + t_physical_tile_port tile_port; tile_port = find_tile_port_by_name(physical_tile, port_name); if (start_pin_index == OPEN) { @@ -4396,17 +4333,10 @@ static t_clb_to_clb_directs* alloc_and_load_clb_to_clb_directs(const std::vector std::tie(start_pin_index, end_pin_index, tile_name, port_name) = parse_direct_pin_name(directs[i].to_pin, directs[i].line); // Figure out which type, port, and pin is used - for (const t_physical_tile_type& type : device_ctx.physical_tile_types) { - if (tile_name == type.name) { - physical_tile = &type; - break; - } - } - + physical_tile = find_tile_type_by_name(tile_name, device_ctx.physical_tile_types); if (physical_tile == nullptr) { VPR_THROW(VPR_ERROR_ARCH, "Unable to find block %s.\n", tile_name.c_str()); } - clb_to_clb_directs[i].to_clb_type = physical_tile; tile_port = find_tile_port_by_name(physical_tile, port_name); @@ -4454,7 +4384,7 @@ static int get_opin_direct_connections(RRGraphBuilder& rr_graph_builder, RRNodeId from_rr_node, t_rr_edge_info_set& rr_edges_to_create, const std::vector& directs, - const t_clb_to_clb_directs* clb_to_clb_directs) { + const std::vector& clb_to_clb_directs) { auto& device_ctx = g_vpr_ctx.device(); t_physical_tile_type_ptr curr_type = device_ctx.grid.get_physical_type({x, y, layer}); diff --git a/vpr/src/route/rr_graph.h b/vpr/src/route/rr_graph.h index b0b3b7d1f00..283da1a296c 100644 --- a/vpr/src/route/rr_graph.h +++ b/vpr/src/route/rr_graph.h @@ -20,7 +20,7 @@ enum { RR_GRAPH_WARN_CHAN_Y_WIDTH_CHANGED = 0x03 }; -void create_rr_graph(const t_graph_type graph_type, +void create_rr_graph(e_graph_type graph_type, const std::vector& block_types, const DeviceGrid& grid, const t_chan_width& nodes_per_chan, diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index 755428a8780..76a71af29a5 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -255,56 +255,35 @@ static bool should_apply_switch_override(int switch_override); /******************** Subroutine definitions *******************************/ -/* This assigns tracks (individually or pairs) to segment types. - * It tries to match requested ratio. If use_full_seg_groups is - * true, then segments are assigned only in multiples of their - * length. This is primarily used for making a tileable unidir - * layout. The effect of using this is that the number of tracks - * requested will not always be met and the result will sometimes - * be over and sometimes under. - * The pattern when using use_full_seg_groups is to keep adding - * one group of the track type that wants the largest number of - * groups of tracks. Each time a group is assigned, the types - * demand is reduced by 1 unit. The process stops when we are - * no longer less than the requested number of tracks. As a final - * step, if we were closer to target before last more, undo it - * and end up with a result that uses fewer tracks than given. */ -std::unique_ptr get_seg_track_counts(const int num_sets, - const std::vector& segment_inf, - const bool use_full_seg_groups) { - std::unique_ptr result; - int imax, freq_sum, assigned, size; - double scale, max, reduce; - - result = std::make_unique(segment_inf.size()); - std::vector demand(segment_inf.size()); - - /* Scale factor so we can divide by any length - * and still use integers */ - scale = 1; - freq_sum = 0; +std::vector get_seg_track_counts(int num_sets, + const std::vector& segment_inf, + bool use_full_seg_groups) { + // Scale factor so we can divide by any length and still use integers + double scale = 1; + int freq_sum = 0; for (size_t i = 0; i < segment_inf.size(); ++i) { scale *= segment_inf[i].length; freq_sum += segment_inf[i].frequency; } - reduce = scale * freq_sum; + const double reduce = scale * freq_sum; - /* Init assignments to 0 and set the demand values */ + // Init assignments to 0 and set the demand values + std::vector result(segment_inf.size(), 0); + std::vector demand(segment_inf.size()); for (size_t i = 0; i < segment_inf.size(); ++i) { - result[i] = 0; demand[i] = scale * num_sets * segment_inf[i].frequency; if (use_full_seg_groups) { demand[i] /= segment_inf[i].length; } } - /* Keep assigning tracks until we use them up */ - assigned = 0; - size = 0; - imax = 0; + // Keep assigning tracks until we use them up + int assigned = 0; + int imax = 0; + int size = 0; while (assigned < num_sets) { - /* Find current maximum demand */ - max = 0; + // Find current maximum demand + double max = 0; for (size_t i = 0; i < segment_inf.size(); ++i) { if (demand[i] > max) { imax = i; @@ -312,19 +291,18 @@ std::unique_ptr get_seg_track_counts(const int num_sets, } } - /* Assign tracks to the type and reduce the types demand */ - size = (use_full_seg_groups ? segment_inf[imax].length : 1); + // Assign tracks to the type and reduce the types demand + size = use_full_seg_groups ? segment_inf[imax].length : 1; demand[imax] -= reduce; result[imax] += size; assigned += size; } - /* Undo last assignment if we were closer to goal without it */ + // Undo last assignment if we were closer to goal without it if ((assigned - num_sets) > (size / 2)) { result[imax] -= size; } - /* This must be freed by caller */ return result; } @@ -343,53 +321,11 @@ int get_parallel_seg_index(const int abs_index, return index; } -/* Returns an array of tracks per segment, with matching indices to segment_inf by combining * - * sets per segment for each direction. This is a helper function to avoid having to refactor * - * alot of the functions inside rr_graph.cpp & rr_graph2.cpp to model different horizontal and vertical * - * channel widths. */ -std::unique_ptr get_ordered_seg_track_counts(const std::vector& segment_inf_x, - const std::vector& segment_inf_y, - const std::vector& segment_inf, - const std::unique_ptr& segment_sets_x, - const std::unique_ptr& segment_sets_y) { - std::unordered_map all_segs_index; - std::unique_ptr ordered_seg_track_counts; - ordered_seg_track_counts = std::make_unique(segment_inf.size()); - - for (size_t iseg = 0; iseg < segment_inf.size(); ++iseg) { - all_segs_index.insert(std::make_pair(segment_inf[iseg], iseg)); - } - for (size_t iseg_x = 0; iseg_x < segment_inf_x.size(); ++iseg_x) { - auto seg_in_x_dir = all_segs_index.find(segment_inf_x[iseg_x]); - if (seg_in_x_dir != all_segs_index.end()) { - ordered_seg_track_counts[seg_in_x_dir->second] = segment_sets_x[iseg_x]; - } else { - VTR_ASSERT_MSG(seg_in_x_dir != all_segs_index.end(), - "Segment in the x-direction must be a part of all segments."); - } - } - for (size_t iseg_y = 0; iseg_y < segment_inf_y.size(); ++iseg_y) { - if (segment_inf_y[iseg_y].parallel_axis == BOTH_AXIS) { /*Avoid counting segments in both horizontal and vertical direction twice*/ - continue; - } - auto seg_in_y_dir = all_segs_index.find(segment_inf_y[iseg_y]); - if (seg_in_y_dir != all_segs_index.end()) { - ordered_seg_track_counts[seg_in_y_dir->second] = segment_sets_y[iseg_y]; - } else { - VTR_ASSERT_MSG(seg_in_y_dir != all_segs_index.end(), - "Segment in the x-direction must be a part of all segments."); - } - } - - return ordered_seg_track_counts; -} - -t_seg_details* alloc_and_load_seg_details(int* max_chan_width, - const int max_len, - const std::vector& segment_inf, - const bool use_full_seg_groups, - const enum e_directionality directionality, - int* num_seg_details) { +std::vector alloc_and_load_seg_details(int* max_chan_width, + const int max_len, + const std::vector& segment_inf, + const bool use_full_seg_groups, + const enum e_directionality directionality) { /* Allocates and loads the seg_details data structure. Max_len gives the * * maximum length of a segment (dimension of array). The code below tries * * to: * @@ -399,16 +335,8 @@ t_seg_details* alloc_and_load_seg_details(int* max_chan_width, * (3) stagger the connection and switch boxes on different long lines, * * as they will not be staggered by different segment start points. */ - int cur_track, ntracks, itrack, length, j, index; - int fac, num_sets, tmp; - int arch_wire_switch, arch_opin_switch, arch_wire_switch_dec, arch_opin_switch_dec; - int arch_inter_die_switch; - int group_start, first_track; - std::unique_ptr sets_per_seg_type; - t_seg_details* seg_details = nullptr; - bool longline; - - /* Unidir tracks are assigned in pairs, and bidir tracks individually */ + // Unidir tracks are assigned in pairs, and bidir tracks individually + int fac; if (directionality == BI_DIRECTIONAL) { fac = 1; } else { @@ -420,51 +348,45 @@ t_seg_details* alloc_and_load_seg_details(int* max_chan_width, VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Routing channel width must be divisible by %d (channel width was %d)", fac, *max_chan_width); } - /* Map segment type fractions and groupings to counts of tracks */ - sets_per_seg_type = get_seg_track_counts((*max_chan_width / fac), - segment_inf, use_full_seg_groups); + // Map segment type fractions and groupings to counts of tracks + const std::vector sets_per_seg_type = get_seg_track_counts((*max_chan_width / fac), + segment_inf, use_full_seg_groups); - /* Count the number tracks actually assigned. */ - tmp = 0; - for (size_t i = 0; i < segment_inf.size(); ++i) { - tmp += sets_per_seg_type[i] * fac; - } + // Count the number tracks actually assigned. + int tmp = std::accumulate(sets_per_seg_type.begin(), sets_per_seg_type.end(), 0) * fac; VTR_ASSERT(use_full_seg_groups || (tmp == *max_chan_width)); *max_chan_width = tmp; - seg_details = new t_seg_details[*max_chan_width]; + std::vector seg_details(*max_chan_width); - /* Setup the seg_details data */ - cur_track = 0; + // Setup the seg_details data + int cur_track = 0; for (size_t i = 0; i < segment_inf.size(); ++i) { - first_track = cur_track; + int first_track = cur_track; - num_sets = sets_per_seg_type[i]; - ntracks = fac * num_sets; + const int num_sets = sets_per_seg_type[i]; + const int ntracks = fac * num_sets; if (ntracks < 1) { continue; } /* Avoid divide by 0 if ntracks */ - longline = segment_inf[i].longline; - length = segment_inf[i].length; - if (longline) { - length = max_len; - } - - arch_wire_switch = segment_inf[i].arch_wire_switch; - arch_opin_switch = segment_inf[i].arch_opin_switch; - arch_wire_switch_dec = segment_inf[i].arch_wire_switch_dec; - arch_opin_switch_dec = segment_inf[i].arch_opin_switch_dec; - arch_inter_die_switch = segment_inf[i].arch_inter_die_switch; + const bool longline = segment_inf[i].longline; + const int length = (longline) ? max_len : segment_inf[i].length; + + const int arch_wire_switch = segment_inf[i].arch_wire_switch; + const int arch_opin_switch = segment_inf[i].arch_opin_switch; + const int arch_wire_switch_dec = segment_inf[i].arch_wire_switch_dec; + const int arch_opin_switch_dec = segment_inf[i].arch_opin_switch_dec; + const int arch_inter_die_switch = segment_inf[i].arch_inter_die_switch; VTR_ASSERT((arch_wire_switch == arch_opin_switch && arch_wire_switch_dec == arch_opin_switch_dec) || (directionality != UNI_DIRECTIONAL)); - /* Set up the tracks of same type */ - group_start = 0; - for (itrack = 0; itrack < ntracks; itrack++) { - /* set the name of the segment type this track belongs to */ + // Set up the tracks of same type + int group_start = 0; + for (int itrack = 0; itrack < ntracks; itrack++) { + // set the name of the segment type this track belongs to seg_details[cur_track].type_name = segment_inf[i].name; - /* Remember the start track of the current wire group */ + // Remember the start track of the current wire group if ((itrack / fac) % length == 0 && (itrack % fac) == 0) { group_start = cur_track; } @@ -476,12 +398,10 @@ t_seg_details* alloc_and_load_seg_details(int* max_chan_width, * pin mappings should be aware of this when choosing an * intelligent way of connecting pins and tracks. * cur_track is used as an offset so that extra tracks - * from different segment types are hopefully better - * balanced. */ + * from different segment types are hopefully better balanced. */ seg_details[cur_track].start = (cur_track / fac) % length + 1; - /* These properties are used for vpr_to_phy_track to determine - * * twisting of wires. */ + // These properties are used for vpr_to_phy_track to determine twisting of wires. seg_details[cur_track].group_start = group_start; seg_details[cur_track].group_size = std::min(ntracks + first_track - group_start, length * fac); VTR_ASSERT(0 == seg_details[cur_track].group_size % fac); @@ -489,28 +409,25 @@ t_seg_details* alloc_and_load_seg_details(int* max_chan_width, seg_details[cur_track].group_size = length * fac; } - seg_details[cur_track].seg_start = -1; - seg_details[cur_track].seg_end = -1; - /* Setup the cb and sb patterns. Global route graphs can't depopulate cb and sb * since this is a property of a detailed route. */ seg_details[cur_track].cb = std::make_unique(length); seg_details[cur_track].sb = std::make_unique(length + 1); - for (j = 0; j < length; ++j) { + for (int j = 0; j < length; ++j) { if (seg_details[cur_track].longline) { seg_details[cur_track].cb[j] = true; } else { - /* Use the segment's pattern. */ - index = j % segment_inf[i].cb.size(); + // Use the segment's pattern. + int index = j % segment_inf[i].cb.size(); seg_details[cur_track].cb[j] = segment_inf[i].cb[index]; } } - for (j = 0; j < (length + 1); ++j) { + for (int j = 0; j < (length + 1); ++j) { if (seg_details[cur_track].longline) { seg_details[cur_track].sb[j] = true; } else { /* Use the segment's pattern. */ - index = j % segment_inf[i].sb.size(); + int index = j % segment_inf[i].sb.size(); seg_details[cur_track].sb[j] = segment_inf[i].sb[index]; } } @@ -528,8 +445,8 @@ t_seg_details* alloc_and_load_seg_details(int* max_chan_width, seg_details[cur_track].direction = (itrack % 2) ? Direction::DEC : Direction::INC; } - //check for directionality to set the wire_switch and opin_switch - //if not specified in the architecture file, we will use a same mux for both directions + // check for directionality to set the wire_switch and opin_switch + // if not specified in the architecture file, we will use a same mux for both directions if (seg_details[cur_track].direction == Direction::INC || seg_details[cur_track].direction == Direction::BIDIR || arch_wire_switch_dec == -1) { seg_details[cur_track].arch_opin_switch = arch_opin_switch; seg_details[cur_track].arch_wire_switch = arch_wire_switch; @@ -546,43 +463,35 @@ t_seg_details* alloc_and_load_seg_details(int* max_chan_width, } } /* End for each segment type. */ - if (num_seg_details) { - *num_seg_details = cur_track; - } + seg_details.resize(cur_track); return seg_details; } /* Allocates and loads the chan_details data structure, a 2D array of * seg_details structures. This array is used to handle unique seg_details * (ie. channel segments) for each horizontal and vertical channel. */ - void alloc_and_load_chan_details(const DeviceGrid& grid, - const t_chan_width* nodes_per_chan, - const int num_seg_details_x, - const int num_seg_details_y, - const t_seg_details* seg_details_x, - const t_seg_details* seg_details_y, + const t_chan_width& nodes_per_chan, + const std::vector& seg_details_x, + const std::vector& seg_details_y, t_chan_details& chan_details_x, t_chan_details& chan_details_y) { - chan_details_x = init_chan_details(grid, nodes_per_chan, - num_seg_details_x, seg_details_x, X_AXIS); - chan_details_y = init_chan_details(grid, nodes_per_chan, - num_seg_details_y, seg_details_y, Y_AXIS); + chan_details_x = init_chan_details(grid, nodes_per_chan, seg_details_x, X_AXIS); + chan_details_y = init_chan_details(grid, nodes_per_chan, seg_details_y, Y_AXIS); /* Adjust segment start/end based on obstructed channels, if any */ - adjust_chan_details(grid, nodes_per_chan, - chan_details_x, chan_details_y); + adjust_chan_details(grid, nodes_per_chan, chan_details_x, chan_details_y); } t_chan_details init_chan_details(const DeviceGrid& grid, - const t_chan_width* nodes_per_chan, - const int num_seg_details, - const t_seg_details* seg_details, + const t_chan_width& nodes_per_chan, + const std::vector& seg_details, const enum e_parallel_axis seg_parallel_axis) { + const int num_seg_details = (int)seg_details.size(); if (seg_parallel_axis == X_AXIS) { - VTR_ASSERT(num_seg_details <= nodes_per_chan->x_max); + VTR_ASSERT(num_seg_details <= nodes_per_chan.x_max); } else if (seg_parallel_axis == Y_AXIS) { - VTR_ASSERT(num_seg_details <= nodes_per_chan->y_max); + VTR_ASSERT(num_seg_details <= nodes_per_chan.y_max); } t_chan_details chan_details({grid.width(), grid.height(), size_t(num_seg_details)}); @@ -608,11 +517,11 @@ t_chan_details init_chan_details(const DeviceGrid& grid, p_seg_details[i].set_seg_end(seg_end); if (seg_parallel_axis == X_AXIS) { - if (i >= nodes_per_chan->x_list[y]) { + if (i >= nodes_per_chan.x_list[y]) { p_seg_details[i].set_length(0); } } else if (seg_parallel_axis == Y_AXIS) { - if (i >= nodes_per_chan->y_list[x]) { + if (i >= nodes_per_chan.y_list[x]) { p_seg_details[i].set_length(0); } } @@ -623,7 +532,7 @@ t_chan_details init_chan_details(const DeviceGrid& grid, } void adjust_chan_details(const DeviceGrid& grid, - const t_chan_width* nodes_per_chan, + const t_chan_width& nodes_per_chan, t_chan_details& chan_details_x, t_chan_details& chan_details_y) { for (size_t y = 0; y <= grid.height() - 2; ++y) { //-2 for no perim channels @@ -654,18 +563,18 @@ void adjust_chan_details(const DeviceGrid& grid, void adjust_seg_details(const int x, const int y, const DeviceGrid& grid, - const t_chan_width* nodes_per_chan, + const t_chan_width& nodes_per_chan, t_chan_details& chan_details, const enum e_parallel_axis seg_parallel_axis) { int seg_index = (seg_parallel_axis == X_AXIS ? x : y); int max_chan_width = 0; if (seg_parallel_axis == X_AXIS) { - max_chan_width = nodes_per_chan->x_max; + max_chan_width = nodes_per_chan.x_max; } else if (seg_parallel_axis == Y_AXIS) { - max_chan_width = nodes_per_chan->y_max; + max_chan_width = nodes_per_chan.y_max; } else { VTR_ASSERT(seg_parallel_axis == BOTH_AXIS); - max_chan_width = nodes_per_chan->max; + max_chan_width = nodes_per_chan.max; } for (int track = 0; track < max_chan_width; ++track) { @@ -699,14 +608,8 @@ void adjust_seg_details(const int x, } } -void free_chan_details(t_chan_details& chan_details_x, - t_chan_details& chan_details_y) { - chan_details_x.clear(); - chan_details_y.clear(); -} - -/* Returns the segment number at which the segment this track lies on * - * started. */ +/* Returns the segment number at which the segment this track lies on + * started. */ int get_seg_start(const t_chan_seg_details* seg_details, const int itrack, const int chan_num, @@ -714,16 +617,14 @@ int get_seg_start(const t_chan_seg_details* seg_details, int seg_start = 0; if (seg_details[itrack].seg_start() >= 0) { seg_start = seg_details[itrack].seg_start(); - } else { seg_start = 1; - if (false == seg_details[itrack].longline()) { + if (!seg_details[itrack].longline()) { int length = seg_details[itrack].length(); int start = seg_details[itrack].start(); - /* Start is guaranteed to be between 1 and length. Hence adding length to * - * the quantity in brackets below guarantees it will be nonnegative. */ - + /* Start is guaranteed to be between 1 and length. Hence, adding length to + * the quantity in brackets below guarantees it will be non-negative. */ VTR_ASSERT(start > 0); VTR_ASSERT(start <= length); @@ -737,6 +638,7 @@ int get_seg_start(const t_chan_seg_details* seg_details, } } } + return seg_start; } @@ -1185,7 +1087,7 @@ static void load_chan_rr_indices(const int max_chan_width, const t_chan_details& chan_details, RRGraphBuilder& rr_graph_builder, int* index) { - auto& device_ctx = g_vpr_ctx.device(); + const auto& device_ctx = g_vpr_ctx.device(); for (int layer = 0; layer < grid.get_num_layers(); layer++) { /* Skip the current die if architecture file specifies that it doesn't require global resource routing */ @@ -1361,17 +1263,14 @@ static void load_block_rr_indices(RRGraphBuilder& rr_graph_builder, for (int x = 0; x < (int)grid.width(); x++) { for (int y = 0; y < (int)grid.height(); y++) { //Process each block from its root location - if (grid.get_width_offset({x, y, layer}) == 0 && grid.get_height_offset({x, y, layer}) == 0) { - t_physical_tile_type_ptr physical_type = grid.get_physical_type({x, - y, - layer}); + if (grid.is_root_location({x, y, layer})) { + t_physical_tile_type_ptr physical_type = grid.get_physical_type({x, y, layer}); + //Assign indices for SINKs and SOURCEs // Note that SINKS/SOURCES have no side, so we always use side 0 - std::vector class_num_vec; - std::vector pin_num_vec; + std::vector class_num_vec = get_tile_root_classes(physical_type); + std::vector pin_num_vec = get_tile_root_pins(physical_type); - class_num_vec = get_tile_root_classes(physical_type); - pin_num_vec = get_tile_root_pins(physical_type); add_classes_spatial_lookup(rr_graph_builder, physical_type, class_num_vec, @@ -1468,17 +1367,14 @@ static void add_pins_spatial_lookup(RRGraphBuilder& rr_graph_builder, } } - for (auto pin_num : pin_num_vec) { + for (const int pin_num : pin_num_vec) { bool assigned_to_rr_node = false; - std::vector x_offset; - std::vector y_offset; - std::vector pin_sides; - std::tie(x_offset, y_offset, pin_sides) = get_pin_coordinates(physical_type_ptr, pin_num, wanted_sides); - auto pin_type = get_pin_type_from_pin_physical_num(physical_type_ptr, pin_num); + const auto [x_offset, y_offset, pin_sides] = get_pin_coordinates(physical_type_ptr, pin_num, wanted_sides); + e_pin_type pin_type = get_pin_type_from_pin_physical_num(physical_type_ptr, pin_num); for (int pin_coord_idx = 0; pin_coord_idx < (int)pin_sides.size(); pin_coord_idx++) { int x_tile = root_x + x_offset[pin_coord_idx]; int y_tile = root_y + y_offset[pin_coord_idx]; - auto side = pin_sides[pin_coord_idx]; + e_side side = pin_sides[pin_coord_idx]; if (pin_type == DRIVER) { rr_graph_builder.node_lookup().add_node(RRNodeId(*index), layer, x_tile, y_tile, OPIN, pin_num, side); assigned_to_rr_node = true; @@ -1521,8 +1417,8 @@ static void add_classes_spatial_lookup(RRGraphBuilder& rr_graph_builder, } } - for (auto class_num : class_num_vec) { - auto class_type = get_class_type_from_class_physical_num(physical_type_ptr, class_num); + for (const int class_num : class_num_vec) { + e_pin_type class_type = get_class_type_from_class_physical_num(physical_type_ptr, class_num); e_rr_type node_type = SINK; if (class_type == DRIVER) { node_type = SOURCE; @@ -1543,16 +1439,7 @@ static void add_classes_spatial_lookup(RRGraphBuilder& rr_graph_builder, } } -/* As the rr_indices builders modify a local copy of indices, use the local copy in the builder - * TODO: these building functions should only talk to a RRGraphBuilder object - * The biggest and fatal issue is - * - the rr_graph2.h is included in the rr_graph_storage.h, - * which is included in the rr_graph_builder.h - * If we include rr_graph_builder.h in rr_graph2.h, this creates a loop - * for C++ compiler to identify data structures, which cannot be solved!!! - * This will block us when putting the RRGraphBuilder object as an input arguement - * of this function - */ +/* As the rr_indices builders modify a local copy of indices, use the local copy in the builder */ void alloc_and_load_rr_node_indices(RRGraphBuilder& rr_graph_builder, const t_chan_width* nodes_per_chan, const DeviceGrid& grid, @@ -1591,8 +1478,8 @@ void alloc_and_load_intra_cluster_rr_node_indices(RRGraphBuilder& rr_graph_build for (int layer = 0; layer < grid.get_num_layers(); layer++) { for (int x = 0; x < (int)grid.width(); x++) { for (int y = 0; y < (int)grid.height(); y++) { - //Process each block from it's root location - if (grid.get_width_offset({x, y, layer}) == 0 && grid.get_height_offset({x, y, layer}) == 0) { + //Process each block from its root location + if (grid.is_root_location({x, y, layer})) { t_physical_tile_type_ptr physical_type = grid.get_physical_type({x, y, layer}); //Assign indices for SINKs and SOURCEs // Note that SINKS/SOURCES have no side, so we always use side 0 @@ -2665,7 +2552,7 @@ static int vpr_to_phy_track(const int itrack, } t_sblock_pattern alloc_sblock_pattern_lookup(const DeviceGrid& grid, - t_chan_width* nodes_per_chan) { + const t_chan_width& nodes_per_chan) { /* loading up the sblock connection pattern matrix. It's a huge matrix because * for nonquantized W, it's impossible to make simple permutations to figure out * where muxes are and how to connect to them such that their sizes are balanced */ @@ -2680,14 +2567,14 @@ t_sblock_pattern alloc_sblock_pattern_lookup(const DeviceGrid& grid, VTR_ASSERT(grid.width() > 0); VTR_ASSERT(grid.height() > 0); //CHANGE THIS - VTR_ASSERT(nodes_per_chan->max >= 0); + VTR_ASSERT(nodes_per_chan.max >= 0); t_sblock_pattern sblock_pattern({{ grid.width() - 1, grid.height() - 1, 4, //From side 4, //To side - size_t(nodes_per_chan->max), + size_t(nodes_per_chan.max), 4 //to_mux, to_trac, alt_mux, alt_track }}, UN_SET); @@ -2699,7 +2586,7 @@ t_sblock_pattern alloc_sblock_pattern_lookup(const DeviceGrid& grid, void load_sblock_pattern_lookup(const int i, const int j, const DeviceGrid& grid, - const t_chan_width* nodes_per_chan, + const t_chan_width& nodes_per_chan, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, const int /*Fs*/, @@ -2858,9 +2745,9 @@ void load_sblock_pattern_lookup(const int i, for (int ichan = 0; ichan < get_chan_width((e_side)side_cw, nodes_per_chan); ichan++) { int itrack = ichan; if (side_cw == TOP || side_cw == BOTTOM) { - itrack = ichan % nodes_per_chan->y_list[i]; + itrack = ichan % nodes_per_chan.y_list[i]; } else if (side_cw == RIGHT || side_cw == LEFT) { - itrack = ichan % nodes_per_chan->x_list[j]; + itrack = ichan % nodes_per_chan.x_list[j]; } if (incoming_wire_label[side_cw][itrack] != UN_SET) { @@ -2884,9 +2771,9 @@ void load_sblock_pattern_lookup(const int i, for (int ichan = 0; ichan < get_chan_width((e_side)side_ccw, nodes_per_chan); ichan++) { int itrack = ichan; if (side_ccw == TOP || side_ccw == BOTTOM) { - itrack = ichan % nodes_per_chan->y_list[i]; + itrack = ichan % nodes_per_chan.y_list[i]; } else if (side_ccw == RIGHT || side_ccw == LEFT) { - itrack = ichan % nodes_per_chan->x_list[j]; + itrack = ichan % nodes_per_chan.x_list[j]; } if (incoming_wire_label[side_ccw][itrack] != UN_SET) { @@ -3155,6 +3042,6 @@ static bool should_apply_switch_override(int switch_override) { return false; } -inline int get_chan_width(enum e_side side, const t_chan_width* nodes_per_chan) { - return (side == TOP || side == BOTTOM ? nodes_per_chan->y_max : nodes_per_chan->x_max); +inline int get_chan_width(enum e_side side, const t_chan_width& nodes_per_chan) { + return (side == TOP || side == BOTTOM ? nodes_per_chan.y_max : nodes_per_chan.x_max); } diff --git a/vpr/src/route/rr_graph2.h b/vpr/src/route/rr_graph2.h index 9cc24e78b66..71b7004197f 100644 --- a/vpr/src/route/rr_graph2.h +++ b/vpr/src/route/rr_graph2.h @@ -12,13 +12,6 @@ #include "device_grid.h" #include "get_parallel_segs.h" -/******************* Types shared by rr_graph2 functions *********************/ - -/* [0..grid.width()-1][0..grid.width()][0..3 (From side)] \ - * [0..3 (To side)][0...max_chan_width][0..3 (to_mux,to_trac,alt_mux,alt_track)] - * originally initialized to UN_SET until alloc_and_load_sb is called */ -typedef vtr::NdMatrix t_sblock_pattern; - /******************* Subroutines exported by rr_graph2.c *********************/ void alloc_and_load_rr_node_indices(RRGraphBuilder& rr_graph_builder, @@ -75,40 +68,36 @@ vtr::NdMatrix get_number_track_to_track_inter_die_conn(t_sb_connection_m const int custom_3d_sb_fanin_fanout, RRGraphBuilder& rr_graph_builder); -t_seg_details* alloc_and_load_seg_details(int* max_chan_width, - const int max_len, - const std::vector& segment_inf, - const bool use_full_seg_groups, - const enum e_directionality directionality, - int* num_seg_details = nullptr); +std::vector alloc_and_load_seg_details(int* max_chan_width, + const int max_len, + const std::vector& segment_inf, + const bool use_full_seg_groups, + const enum e_directionality directionality); void alloc_and_load_chan_details(const DeviceGrid& grid, - const t_chan_width* nodes_per_chan, - const int num_seg_details_x, - const int num_seg_details_y, - const t_seg_details* seg_details_x, - const t_seg_details* seg_details_y, + const t_chan_width& nodes_per_chan, + const std::vector& seg_details_x, + const std::vector& seg_details_y, t_chan_details& chan_details_x, t_chan_details& chan_details_y); + t_chan_details init_chan_details(const DeviceGrid& grid, - const t_chan_width* nodes_per_chan, - const int num_seg_details, - const t_seg_details* seg_details, + const t_chan_width& nodes_per_chan, + const std::vector& seg_details, const enum e_parallel_axis seg_details_type); + void adjust_chan_details(const DeviceGrid& grid, - const t_chan_width* nodes_per_chan, + const t_chan_width& nodes_per_chan, t_chan_details& chan_details_x, t_chan_details& chan_details_y); + void adjust_seg_details(const int x, const int y, const DeviceGrid& grid, - const t_chan_width* nodes_per_chan, + const t_chan_width& nodes_per_chan, t_chan_details& chan_details, const enum e_parallel_axis seg_details_type); -void free_chan_details(t_chan_details& chan_details_x, - t_chan_details& chan_details_y); - int get_seg_start(const t_chan_seg_details* seg_details, const int itrack, const int chan_num, @@ -202,12 +191,12 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, t_sb_connection_map* sb_conn_map); t_sblock_pattern alloc_sblock_pattern_lookup(const DeviceGrid& grid, - t_chan_width* nodes_per_chan); + const t_chan_width& nodes_per_chan); void load_sblock_pattern_lookup(const int i, const int j, const DeviceGrid& grid, - const t_chan_width* nodes_per_chan, + const t_chan_width& nodes_per_chan, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, const int Fs, @@ -218,15 +207,28 @@ int get_parallel_seg_index(const int abs, const t_unified_to_parallel_seg_index& index_map, const e_parallel_axis parallel_axis); -std::unique_ptr get_ordered_seg_track_counts(const std::vector& segment_inf_x, - const std::vector& segment_inf_y, - const std::vector& segment_inf, - const std::unique_ptr& segment_sets_x, - const std::unique_ptr& segment_sets_y); - -std::unique_ptr get_seg_track_counts(const int num_sets, - const std::vector& segment_inf, - const bool use_full_seg_groups); +/** + * @brief Assigns routing tracks to each segment type based on their frequencies and lengths. + * + * This function determines how many routing tracks (or sets of tracks) to assign to each + * segment type in order to match the desired frequency distribution specified in + * the segment information. + * + * When @p use_full_seg_groups is true, the function assigns tracks in multiples of the + * segment length, which may result in a total track count that slightly overshoots or + * undershoots the target @p num_sets. The algorithm proceeds by: + * - Calculating the demand for each segment type. + * - Iteratively assigning tracks to the segment type with the highest remaining demand. + * - Optionally undoing the last assignment if it overshoots the target by more than half a group. + * + * @param num_sets Total number of track sets to assign. + * @param segment_inf Vector containing segment type information (frequency, length, etc.). + * @param use_full_seg_groups If true, assign tracks in full segment-length groups. + * @return A vector where each element indicates the number of tracks assigned to the corresponding segment type. + */ +std::vector get_seg_track_counts(int num_sets, + const std::vector& segment_inf, + bool use_full_seg_groups); void dump_seg_details(const t_chan_seg_details* seg_details, int max_chan_width, @@ -249,7 +251,5 @@ void dump_track_to_pin_map(t_track_to_pin_lookup& track_to_pin_map, int max_chan_width, FILE* fp); -void insert_at_ptc_index(std::vector& rr_indices, int ptc, int inode); - -inline int get_chan_width(enum e_side side, const t_chan_width* nodes_per_channel); +inline int get_chan_width(enum e_side side, const t_chan_width& nodes_per_channel); #endif diff --git a/vpr/src/route/rr_types.h b/vpr/src/route/rr_types.h index d75f107d082..8e093faca75 100644 --- a/vpr/src/route/rr_types.h +++ b/vpr/src/route/rr_types.h @@ -22,4 +22,164 @@ typedef std::vector, 5>> t_pin_to_track_lookup; typedef std::vector, 5>> t_track_to_pin_lookup; +/** + * @brief Lists detailed information about wire segments. [0 .. W-1]. + */ +struct t_seg_details { + /** @brief Length (in clbs) of the segment. */ + int length = 0; + + /** @brief Index at which a segment starts in channel 0. */ + int start = 0; + + /** @brief True if this segment spans the entire channel. */ + bool longline = false; + + /** @brief [0..length]: true for every channel intersection, relative to the + * segment start, at which there is a switch box. + */ + std::unique_ptr sb; + + /** @brief [0..length-1]: true for every logic block along the segment at + * which there is a connection box. + */ + std::unique_ptr cb; + + /** @brief Index of the switch type that connects other wires to this segment. + * Note that this index is in relation to the switches from the architecture + * file, not the expanded list of switches that is built at the end of build_rr_graph. + */ + short arch_wire_switch = 0; + + /** @brief Index of the switch type that connects output pins (OPINs) *to* this segment. + * Note that this index is in relation to the switches from the architecture + * file, not the expanded list of switches that is built at the end of build_rr_graph. + */ + short arch_opin_switch = 0; + + /** @brief Index of the switch type that connects output pins (OPINs) *to* this segment + * from *another dice*. Note that this index is in relation to the switches from the + * architecture file, not the expanded list of switches that is built at the end of + * build_rr_graph. + */ + short arch_inter_die_switch = 0; + + /** @brief Resistance of a routing track, per unit logic block length. */ + float Rmetal = 0; + + /** @brief Capacitance of a routing track, per unit logic block length. */ + float Cmetal = 0; + + /** @brief Whether the segment is twisted. */ + bool twisted = false; + + /** @brief Direction of the segment. */ + enum Direction direction = Direction::NONE; + + /** @brief Index of the first logic block in the group. */ + int group_start = 0; + + /** @brief Size of the group. */ + int group_size = 0; + + /** @brief index of the segment type used for this track. + * Note that this index will store the index of the segment + * relative to its **parallel** segment types, not all segments + * as stored in device_ctx. Look in rr_graph.cpp: build_rr_graph + * for details but here is an example: say our segment_inf_vec in + * device_ctx is as follows: [seg_a_x, seg_b_x, seg_a_y, seg_b_y] + * when building the rr_graph, static segment_inf_vectors will be + * created for each direction, thus you will have the following + * 2 vectors: X_vec =[seg_a_x,seg_b_x] and Y_vec = [seg_a_y,seg_b_y]. + * As a result, e.g. seg_b_y::index == 1 (index in Y_vec) + * and != 3 (index in device_ctx segment_inf_vec). + */ + int index = 0; + + /** @brief index is relative to the segment_inf vec as stored in device_ctx. + * Note that the above vector is **unifies** both x-parallel and + * y-parallel segments and is loaded up originally in read_xml_arch_file.cpp + */ + int abs_index = 0; + + /** @brief Used for power */ + float Cmetal_per_m = 0; + + /** @brief Name of the segment type. */ + std::string type_name; +}; + +class t_chan_seg_details { + public: + t_chan_seg_details() = default; + t_chan_seg_details(const t_seg_details* init_seg_details) + : length_(init_seg_details->length) + , seg_detail_(init_seg_details) {} + + public: + int length() const { return length_; } + int seg_start() const { return seg_start_; } + int seg_end() const { return seg_end_; } + + int start() const { return seg_detail_->start; } + bool longline() const { return seg_detail_->longline; } + + int group_start() const { return seg_detail_->group_start; } + int group_size() const { return seg_detail_->group_size; } + + bool cb(int pos) const { return seg_detail_->cb[pos]; } + bool sb(int pos) const { return seg_detail_->sb[pos]; } + + float Rmetal() const { return seg_detail_->Rmetal; } + float Cmetal() const { return seg_detail_->Cmetal; } + float Cmetal_per_m() const { return seg_detail_->Cmetal_per_m; } + + short arch_wire_switch() const { return seg_detail_->arch_wire_switch; } + short arch_opin_switch() const { return seg_detail_->arch_opin_switch; } + short arch_inter_die_switch() const { return seg_detail_->arch_inter_die_switch; } + + Direction direction() const { return seg_detail_->direction; } + + int index() const { return seg_detail_->index; } + int abs_index() const { return seg_detail_->abs_index; } + + const vtr::string_view type_name() const { + return vtr::string_view( + seg_detail_->type_name.data(), + seg_detail_->type_name.size()); + } + + public: //Modifiers + void set_length(int new_len) { length_ = new_len; } + void set_seg_start(int new_start) { seg_start_ = new_start; } + void set_seg_end(int new_end) { seg_end_ = new_end; } + + private: + //The only unique information about a channel segment is it's start/end + //and length. All other information is shared across segment types, + //so we use a flyweight to the t_seg_details which defines that info. + // + //To preserve the illusion of uniqueness we wrap all t_seg_details members + //so it appears transparent -- client code of this class doesn't need to + //know about t_seg_details. + int length_ = -1; + int seg_start_ = -1; + int seg_end_ = -1; + const t_seg_details* seg_detail_ = nullptr; +}; + +/** + * @typedef t_chan_details + * @brief Defines a 3-D array of t_chan_seg_details structures (one for each horizontal and vertical channel). + * + * Once allocated in rr_graph2.cpp, it can be accessed as: + * [0..grid.width()][0..grid.height()][0..num_tracks-1] + */ +typedef vtr::NdMatrix t_chan_details; + +/* [0..grid.width()-1][0..grid.width()][0..3 (From side)] \ + * [0..3 (To side)][0...max_chan_width][0..3 (to_mux,to_trac,alt_mux,alt_track)] + * originally initialized to UN_SET until alloc_and_load_sb is called */ +typedef vtr::NdMatrix t_sblock_pattern; + #endif diff --git a/vpr/test/test_connection_router.cpp b/vpr/test/test_connection_router.cpp index fbf1a63e142..c824d9b876e 100644 --- a/vpr/test/test_connection_router.cpp +++ b/vpr/test/test_connection_router.cpp @@ -150,12 +150,12 @@ TEST_CASE("connection_router", "[vpr]") { vpr_setup_clock_networks(vpr_setup, arch); auto det_routing_arch = &vpr_setup.RoutingArch; auto& router_opts = vpr_setup.RouterOpts; - t_graph_type graph_directionality; + e_graph_type graph_directionality; if (router_opts.route_type == GLOBAL) { - graph_directionality = GRAPH_BIDIR; + graph_directionality = e_graph_type::BIDIR; } else { - graph_directionality = (det_routing_arch->directionality == BI_DIRECTIONAL ? GRAPH_BIDIR : GRAPH_UNIDIR); + graph_directionality = (det_routing_arch->directionality == BI_DIRECTIONAL ? e_graph_type::BIDIR : e_graph_type::UNIDIR); } auto chan_width = init_chan(vpr_setup.RouterOpts.fixed_channel_width, arch.Chans, graph_directionality);