diff --git a/libs/libarchfpga/src/parse_switchblocks.cpp b/libs/libarchfpga/src/parse_switchblocks.cpp index 3ef9ec8e15..512ba6ef30 100644 --- a/libs/libarchfpga/src/parse_switchblocks.cpp +++ b/libs/libarchfpga/src/parse_switchblocks.cpp @@ -23,7 +23,7 @@ #include "arch_error.h" #include "arch_util.h" -#include "physical_types.h" +#include "switchblock_types.h" #include "parse_switchblocks.h" using pugiutil::ReqOpt; @@ -34,20 +34,55 @@ using vtr::t_formula_data; /**** Function Declarations ****/ /*---- Functions for Parsing Switchblocks from Architecture ----*/ -//Load an XML wireconn specification into a t_wireconn_inf +/** + * @brief Parses a wireconn node and returns a `t_wireconn_inf` structure. + * + * Determines whether the wireconn is in inline or multi-node format and dispatches + * to the appropriate parsing subroutine. + * + * @param node XML node representing the wireconn. + * @param loc_data Location data for error reporting. + * @param switches List of architecture switch definitions (used for switch overrides). + * @return A `t_wireconn_inf` structure populated with parsed data. + */ static t_wireconn_inf parse_wireconn(pugi::xml_node node, const pugiutil::loc_data& loc_data, const std::vector& switches); //Process the desired order of a wireconn static void parse_switchpoint_order(const char* order, SwitchPointOrder& switchpoint_order); -//Process a wireconn defined in the inline style (using attributes) -static void parse_wireconn_inline(pugi::xml_node node, const pugiutil::loc_data& loc_data, t_wireconn_inf& wc, const std::vector& switches); +/** + * @brief Parses an inline `` node using its attributes. + * + * Extracts wire types, switch points, orders, and optional switch overrides + * from the attributes of the inline `` XML node and returns a populated + * `t_wireconn_inf` structure. + * + * @param node XML node containing inline wireconn attributes. + * @param loc_data Location data for error reporting. + * @param switches List of architecture switch definitions (used for switch overrides). + * @return A `t_wireconn_inf` structure populated with parsed data. + */ +static t_wireconn_inf parse_wireconn_inline(pugi::xml_node node, + const pugiutil::loc_data& loc_data, + const std::vector& switches); -//Process a wireconn defined in the multinode style (more advanced specification) -static void parse_wireconn_multinode(pugi::xml_node node, const pugiutil::loc_data& loc_data, t_wireconn_inf& wc, const std::vector& switches); +/** + * @brief Parses a multi-node `` definition with `` and `` children. + * + * Processes wire connection endpoints described in child nodes and returns a `t_wireconn_inf` + * structure populated with switchpoint sets and optional metadata like orders and switch overrides. + * + * @param node XML node containing `` and `` children. + * @param loc_data Location data for error reporting. + * @param switches List of architecture switch definitions (used for switch overrides). + * @return A `t_wireconn_inf` structure populated with parsed data. + */ +static t_wireconn_inf parse_wireconn_multinode(pugi::xml_node node, + const pugiutil::loc_data& loc_data, + const std::vector& switches); //Process a or sub-node of a multinode wireconn -t_wire_switchpoints parse_wireconn_from_to_node(pugi::xml_node node, const pugiutil::loc_data& loc_data); +static t_wire_switchpoints parse_wireconn_from_to_node(pugi::xml_node node, const pugiutil::loc_data& loc_data); /* parses the wire types specified in the comma-separated 'ch' char array into the vector wire_points_vec. * Spaces are trimmed off */ @@ -60,13 +95,13 @@ static void parse_comma_separated_wire_points(const char* ch, std::vector& switches); /* checks for correctness of a unidir switchblock. */ -static void check_unidir_switchblock(const t_switchblock_inf* sb); +static void check_unidir_switchblock(const t_switchblock_inf& sb); /* checks for correctness of a bidir switchblock. */ static void check_bidir_switchblock(const t_permutation_map* permutation_map); @@ -78,65 +113,71 @@ static void check_wireconn(const t_arch* arch, const t_wireconn_inf& wireconn); /*---- Functions for Parsing Switchblocks from Architecture ----*/ -/* Reads-in the wire connections specified for the switchblock in the xml arch file */ -void read_sb_wireconns(const std::vector& switches, pugi::xml_node Node, t_switchblock_inf* sb, const pugiutil::loc_data& loc_data) { - /* Make sure that Node is a switchblock */ +void read_sb_wireconns(const std::vector& switches, + pugi::xml_node Node, + t_switchblock_inf& sb, + const pugiutil::loc_data& loc_data) { + // Make sure that Node is a switchblock check_node(Node, "switchblock", loc_data); - int num_wireconns; pugi::xml_node SubElem; - /* count the number of specified wire connections for this SB */ - num_wireconns = count_children(Node, "wireconn", loc_data, ReqOpt::OPTIONAL); - sb->wireconns.reserve(num_wireconns); + // Count the number of specified wire connections for this SB + const int num_wireconns = count_children(Node, "wireconn", loc_data, ReqOpt::OPTIONAL); + sb.wireconns.reserve(num_wireconns); if (num_wireconns > 0) { SubElem = get_first_child(Node, "wireconn", loc_data); } + for (int i = 0; i < num_wireconns; i++) { t_wireconn_inf wc = parse_wireconn(SubElem, loc_data, switches); // need to pass in switch info for switch override - sb->wireconns.push_back(wc); + sb.wireconns.push_back(wc); SubElem = SubElem.next_sibling(SubElem.name()); } } -static t_wireconn_inf parse_wireconn(pugi::xml_node node, const pugiutil::loc_data& loc_data, const std::vector& switches) { - t_wireconn_inf wc; +static t_wireconn_inf parse_wireconn(pugi::xml_node node, + const pugiutil::loc_data& loc_data, + const std::vector& switches) { size_t num_children = count_children(node, "from", loc_data, ReqOpt::OPTIONAL); num_children += count_children(node, "to", loc_data, ReqOpt::OPTIONAL); if (num_children == 0) { - parse_wireconn_inline(node, loc_data, wc, switches); + return parse_wireconn_inline(node, loc_data, switches); } else { VTR_ASSERT(num_children > 0); - parse_wireconn_multinode(node, loc_data, wc, switches); + return parse_wireconn_multinode(node, loc_data, switches); } - - return wc; } -static void parse_wireconn_inline(pugi::xml_node node, const pugiutil::loc_data& loc_data, t_wireconn_inf& wc, const std::vector& switches) { - //Parse an inline wireconn definition, using attributes +static t_wireconn_inf parse_wireconn_inline(pugi::xml_node node, + const pugiutil::loc_data& loc_data, + const std::vector& switches) { + + // Parse an inline wireconn definition, using attributes expect_only_attributes(node, {"num_conns", "from_type", "to_type", "from_switchpoint", "to_switchpoint", "from_order", "to_order", "switch_override"}, loc_data); - /* get the connection style */ + t_wireconn_inf wc; + + // get the connection style const char* char_prop = get_attribute(node, "num_conns", loc_data).value(); parse_num_conns(char_prop, wc); - /* get from type */ + // get from type char_prop = get_attribute(node, "from_type", loc_data).value(); parse_comma_separated_wire_types(char_prop, wc.from_switchpoint_set); - /* get to type */ + // get to type char_prop = get_attribute(node, "to_type", loc_data).value(); parse_comma_separated_wire_types(char_prop, wc.to_switchpoint_set); - /* get the source wire point */ + // get the source wire point char_prop = get_attribute(node, "from_switchpoint", loc_data).value(); parse_comma_separated_wire_points(char_prop, wc.from_switchpoint_set); - /* get the destination wire point */ + // get the destination wire point char_prop = get_attribute(node, "to_switchpoint", loc_data).value(); parse_comma_separated_wire_points(char_prop, wc.to_switchpoint_set); @@ -149,12 +190,18 @@ static void parse_wireconn_inline(pugi::xml_node node, const pugiutil::loc_data& // parse switch overrides if they exist: char_prop = get_attribute(node, "switch_override", loc_data, ReqOpt::OPTIONAL).value(); parse_switch_override(char_prop, wc, switches); + + return wc; } -void parse_wireconn_multinode(pugi::xml_node node, const pugiutil::loc_data& loc_data, t_wireconn_inf& wc, const std::vector& switches) { +static t_wireconn_inf parse_wireconn_multinode(pugi::xml_node node, + const pugiutil::loc_data& loc_data, + const std::vector& switches) { expect_only_children(node, {"from", "to"}, loc_data); - /* get the connection style */ + t_wireconn_inf wc; + + // get the connection style const char* char_prop = get_attribute(node, "num_conns", loc_data).value(); parse_num_conns(char_prop, wc); @@ -185,9 +232,11 @@ void parse_wireconn_multinode(pugi::xml_node node, const pugiutil::loc_data& loc node.name(), child.name()); } } + + return wc; } -t_wire_switchpoints parse_wireconn_from_to_node(pugi::xml_node node, const pugiutil::loc_data& loc_data) { +static t_wire_switchpoints parse_wireconn_from_to_node(pugi::xml_node node, const pugiutil::loc_data& loc_data) { expect_only_attributes(node, {"type", "switchpoint"}, loc_data); size_t attribute_count = count_attributes(node, loc_data); @@ -229,13 +278,13 @@ static void parse_switchpoint_order(const char* order, SwitchPointOrder& switchp /* parses the wire types specified in the comma-separated 'ch' char array into the vector wire_points_vec. * Spaces are trimmed off */ static void parse_comma_separated_wire_types(const char* ch, std::vector& wire_switchpoints) { - auto types = vtr::split(ch, ","); + std::vector types = vtr::split(ch, ","); if (types.empty()) { archfpga_throw(__FILE__, __LINE__, "parse_comma_separated_wire_types: found empty wireconn wire type entry\n"); } - for (const auto& type : types) { + for (const std::string& type : types) { t_wire_switchpoints wsp; wsp.segment_name = type; @@ -245,15 +294,15 @@ static void parse_comma_separated_wire_types(const char* ch, std::vector& wire_switchpoints) { - auto points = vtr::split(ch, ","); + std::vector points = vtr::split(ch, ","); if (points.empty()) { archfpga_throw(__FILE__, __LINE__, "parse_comma_separated_wire_points: found empty wireconn wire point entry\n"); } - for (const auto& point_str : points) { + for (const std::string& point_str : points) { int point = vtr::atoi(point_str); - for (auto& wire_switchpoint : wire_switchpoints) { + for (t_wire_switchpoints& wire_switchpoint : wire_switchpoints) { wire_switchpoint.switchpoints.push_back(point); } } @@ -265,7 +314,7 @@ static void parse_num_conns(std::string num_conns, t_wireconn_inf& wireconn) { } //set sides for a specific conn for custom switch block pattern -static void set_switch_func_type(SB_Side_Connection& conn, const char* func_type) { +static void set_switch_func_type(SBSideConnection& conn, const char* func_type) { if (0 == strcmp(func_type, "lt")) { conn.set_sides(LEFT, TOP); } else if (0 == strcmp(func_type, "lr")) { @@ -328,46 +377,38 @@ static void set_switch_func_type(SB_Side_Connection& conn, const char* func_type } } -/* Loads permutation funcs specified under Node into t_switchblock_inf. Node should be - * */ -void read_sb_switchfuncs(pugi::xml_node Node, t_switchblock_inf* sb, const pugiutil::loc_data& loc_data) { - /* Make sure the passed-in is correct */ - check_node(Node, "switchfuncs", loc_data); +void read_sb_switchfuncs(pugi::xml_node node, t_switchblock_inf& sb, const pugiutil::loc_data& loc_data) { + // Make sure the passed-in node is correct + check_node(node, "switchfuncs", loc_data); pugi::xml_node SubElem; - /* get the number of specified permutation functions */ - int num_funcs = count_children(Node, "func", loc_data, ReqOpt::OPTIONAL); - - const char* func_type; - const char* func_formula; - std::vector* func_ptr; + // Get the number of specified permutation functions + const int num_funcs = count_children(node, "func", loc_data, ReqOpt::OPTIONAL); - /* used to index into permutation map of switchblock */ - SB_Side_Connection conn; - - /* now we iterate through all the specified permutation functions, and - * load them into the switchblock structure as appropriate */ + // now we iterate through all the specified permutation functions, and + // load them into the switchblock structure as appropriate if (num_funcs > 0) { - SubElem = get_first_child(Node, "func", loc_data); + SubElem = get_first_child(node, "func", loc_data); } + for (int ifunc = 0; ifunc < num_funcs; ifunc++) { - /* get function type */ - func_type = get_attribute(SubElem, "type", loc_data).as_string(nullptr); + // Get function type + const char* func_type = get_attribute(SubElem, "type", loc_data).as_string(nullptr); - /* get function formula */ - func_formula = get_attribute(SubElem, "formula", loc_data).as_string(nullptr); + // Get function formula + const char* func_formula = get_attribute(SubElem, "formula", loc_data).as_string(nullptr); - /* go through all the possible cases of func_type */ - set_switch_func_type(conn, func_type); + // Used to index into permutation map of switchblock + SBSideConnection conn; - func_ptr = &(sb->permutation_map[conn]); + // go through all the possible cases of func_type + set_switch_func_type(conn, func_type); - /* Here we load the specified switch function(s) */ - func_ptr->push_back(std::string(func_formula)); + // Here we load the specified switch function(s) + sb.permutation_map[conn].emplace_back(func_formula); - func_ptr = nullptr; - /* get the next switchblock function */ + // get the next switchblock function SubElem = SubElem.next_sibling(SubElem.name()); } } @@ -391,20 +432,20 @@ static void parse_switch_override(const char* switch_override, t_wireconn_inf& w } /* checks for correctness of switch block read-in from the XML architecture file */ -void check_switchblock(const t_switchblock_inf* sb, const t_arch* arch) { +void check_switchblock(const t_switchblock_inf& sb, const t_arch* arch) { /* get directionality */ - enum e_directionality directionality = sb->directionality; + enum e_directionality directionality = sb.directionality; /* Check for errors in the switchblock descriptions */ if (UNI_DIRECTIONAL == directionality) { check_unidir_switchblock(sb); } else { VTR_ASSERT(BI_DIRECTIONAL == directionality); - check_bidir_switchblock(&(sb->permutation_map)); + check_bidir_switchblock(&(sb.permutation_map)); } /* check that specified wires exist */ - for (const auto& wireconn : sb->wireconns) { + for (const t_wireconn_inf& wireconn : sb.wireconns) { check_wireconn(arch, wireconn); } @@ -416,9 +457,9 @@ void check_switchblock(const t_switchblock_inf* sb, const t_arch* arch) { } /* checks for correctness of a unidirectional switchblock. hard exit if error found (to be changed to throw later) */ -static void check_unidir_switchblock(const t_switchblock_inf* sb) { +static void check_unidir_switchblock(const t_switchblock_inf& sb) { /* Check that the destination wire points are always the starting points (i.e. of wire point 0) */ - for (const t_wireconn_inf& wireconn : sb->wireconns) { + for (const t_wireconn_inf& wireconn : sb.wireconns) { for (const t_wire_switchpoints& wire_to_points : wireconn.to_switchpoint_set) { if (wire_to_points.switchpoints.size() > 1 || wire_to_points.switchpoints[0] != 0) { archfpga_throw(__FILE__, __LINE__, "Unidirectional switch blocks are currently only allowed to drive the start points of wire segments\n"); @@ -432,7 +473,7 @@ static void check_bidir_switchblock(const t_permutation_map* permutation_map) { /**** check that if side1->side2 is specified, then side2->side1 is not, as it is implicit ****/ /* variable used to index into the permutation map */ - SB_Side_Connection conn; + SBSideConnection conn; /* iterate over all combinations of from_side -> to side */ for (e_side from_side : TOTAL_2D_SIDES) { @@ -446,7 +487,7 @@ static void check_bidir_switchblock(const t_permutation_map* permutation_map) { conn.set_sides(from_side, to_side); /* check if a connection between these sides exists */ - t_permutation_map::const_iterator it = (*permutation_map).find(conn); + auto it = (*permutation_map).find(conn); if (it != (*permutation_map).end()) { /* the two sides are connected */ /* check if the opposite connection has been specified */ @@ -458,8 +499,6 @@ static void check_bidir_switchblock(const t_permutation_map* permutation_map) { } } } - - return; } static void check_wireconn(const t_arch* arch, const t_wireconn_inf& wireconn) { diff --git a/libs/libarchfpga/src/parse_switchblocks.h b/libs/libarchfpga/src/parse_switchblocks.h index fd5664818b..70516f7cd4 100644 --- a/libs/libarchfpga/src/parse_switchblocks.h +++ b/libs/libarchfpga/src/parse_switchblocks.h @@ -1,19 +1,49 @@ #pragma once -#include "physical_types.h" #include "pugixml.hpp" #include "pugixml_loc.hpp" #include "vtr_expr_eval.h" -/**** Function Declarations ****/ -/* Loads permutation funcs specified under Node into t_switchblock_inf */ -void read_sb_switchfuncs(pugi::xml_node Node, t_switchblock_inf* sb, const pugiutil::loc_data& loc_data); +/** + * @brief Loads permutation functions from an XML node into a switchblock structure. + * + * This function parses an XML `` node, extracts all `` child elements, + * and populates the corresponding entries in the `t_switchblock_inf::permutation_map`. + * Each `` element must have a `type` attribute indicating the connection type + * (e.g., side-to-side) and a `formula` attribute specifying the permutation function. + * + * @param node XML node containing the `` specification. + * @param sb The switchblock structure where permutation functions will be stored. + * @param loc_data Location data used for error reporting during XML parsing. + * + * The function expects the following XML structure: + * @code{.xml} + * + * + * ... + * + * @endcode + */ +void read_sb_switchfuncs(pugi::xml_node node, t_switchblock_inf& sb, const pugiutil::loc_data& loc_data); -/* Reads-in the wire connections specified for the switchblock in the xml arch file */ -void read_sb_wireconns(const std::vector& switches, pugi::xml_node Node, t_switchblock_inf* sb, const pugiutil::loc_data& loc_data); +/** + * @brief Reads wire connections for a switch block from the XML architecture file. + * + * This function parses all `` elements under the given `` XML node. + * Each parsed connection is stored in the provided `t_switchblock_inf` structure. + * + * @param switches List of architecture switch definitions. + * @param node XML node representing the switchblock. + * @param sb The switchblock structure to populate. + * @param loc_data Location data for error reporting. + */ +void read_sb_wireconns(const std::vector& switches, + pugi::xml_node node, + t_switchblock_inf& sb, + const pugiutil::loc_data& loc_data); /* checks for correctness of switch block read-in from the XML architecture file */ -void check_switchblock(const t_switchblock_inf* sb, const t_arch* arch); +void check_switchblock(const t_switchblock_inf& sb, const t_arch* arch); /* returns integer result according to the specified formula and data */ int get_sb_formula_raw_result(vtr::FormulaParser& formula_parser, const char* formula, const vtr::t_formula_data& mydata); diff --git a/libs/libarchfpga/src/physical_types.cpp b/libs/libarchfpga/src/physical_types.cpp index 162ff81f4e..0390f00f6d 100644 --- a/libs/libarchfpga/src/physical_types.cpp +++ b/libs/libarchfpga/src/physical_types.cpp @@ -126,8 +126,7 @@ static bool switch_type_is_configurable(SwitchType type) { } static e_directionality switch_type_directionality(SwitchType type) { - if (type == SwitchType::SHORT - || type == SwitchType::PASS_GATE) { + if (type == SwitchType::SHORT || type == SwitchType::PASS_GATE) { //Shorts and pass gates can conduct in either direction return e_directionality::BI_DIRECTIONAL; } else { diff --git a/libs/libarchfpga/src/physical_types.h b/libs/libarchfpga/src/physical_types.h index a3ca918d68..3b9c1b31c8 100644 --- a/libs/libarchfpga/src/physical_types.h +++ b/libs/libarchfpga/src/physical_types.h @@ -41,6 +41,7 @@ #include "logic_types.h" #include "clock_types.h" +#include "switchblock_types.h" //Forward declarations struct t_clock_network; @@ -171,24 +172,6 @@ enum e_interconnect { MUX_INTERC = 3 }; -/* Orientations. */ -enum e_side : unsigned char { - TOP = 0, - RIGHT = 1, - BOTTOM = 2, - LEFT = 3, - NUM_2D_SIDES = 4, - ABOVE = 5, - UNDER = 7, - NUM_3D_SIDES = 6, -}; - -constexpr std::array TOTAL_2D_SIDES = {{TOP, RIGHT, BOTTOM, LEFT}}; //Set of all side orientations -constexpr std::array TOTAL_2D_SIDE_STRINGS = {{"TOP", "RIGHT", "BOTTOM", "LEFT"}}; //String versions of side orientations - -constexpr std::array TOTAL_3D_SIDES = {{TOP, RIGHT, BOTTOM, LEFT, ABOVE, UNDER}}; //Set of all side orientations including different layers -constexpr std::array TOTAL_3D_SIDE_STRINGS = {{"TOP", "RIGHT", "BOTTOM", "LEFT", "ABOVE", "UNDER"}}; //String versions of side orientations including different layers - /* pin location distributions */ enum class e_pin_location_distr { SPREAD, @@ -253,26 +236,6 @@ enum e_power_estimation_method_ { typedef enum e_power_estimation_method_ e_power_estimation_method; typedef enum e_power_estimation_method_ t_power_estimation_method; -/* Specifies what part of the FPGA a custom switchblock should be built in (i.e. perimeter, core, everywhere) */ -enum class e_sb_location { - E_PERIMETER = 0, - E_CORNER, - E_FRINGE, /* perimeter minus corners */ - E_CORE, - E_EVERYWHERE, - E_XY_SPECIFIED -}; - -/** - * @brief Describes regions that a specific switch block specifications should be applied to - */ -struct t_sb_loc_spec { - int start = -1; - int repeat = -1; - int incr = -1; - int end = -1; -}; - /*************************************************************************************************/ /* FPGA grid layout data types */ /*************************************************************************************************/ @@ -614,9 +577,6 @@ enum class e_sb_type { }; -constexpr int NO_SWITCH = -1; -constexpr int DEFAULT_SWITCH = -2; - /* Describes the type for a physical tile * name: unique identifier for type * num_pins: Number of pins for the block @@ -1668,11 +1628,6 @@ struct t_chan_width_dist { t_chan chan_y_dist; }; -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 */ @@ -1730,51 +1685,45 @@ enum e_Fc_type { * used if the route_type is DETAILED. [0 .. det_routing_arch.num_segment] */ struct t_segment_inf { - /** - * @brief The name of the segment type - */ + /// The name of the segment type std::string name; - /** - * @brief ratio of tracks which are of this segment type. - */ + /// brief ratio of tracks which are of this segment type. int frequency; - /** - * @brief Length (in clbs) of the segment. - */ + /// Length (in clbs) of the segment. int length; /** - * @brief Index of the switch type that connects other wires to this segment. + * @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; /** - * @brief Index of the switch type that connects output pins to this segment. + * @brief Index of the switch type that connects output pins 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; /** - * @brief Same as arch_wire_switch but used only for decremental tracks if it is + * @brief Same as arch_wire_switch but used only for decremental tracks if it is * specified in the architecture file. If -1, this value was not set in the * architecture file and arch_wire_switch should be used for "DEC_DIR" wire segments. */ short arch_wire_switch_dec = -1; /** - * @brief Same as arch_opin_switch but used only for decremental tracks if + * @brief Same as arch_opin_switch but used only for decremental tracks if * it is specified in the architecture file. If -1, this value was not set in * the architecture file and arch_opin_switch should be used for "DEC_DIR" wire segments. */ short arch_opin_switch_dec = -1; /** - * @brief Index of the switch type that connects output pins (OPINs) to this + * @brief Index of the switch type that connects output pins (OPINs) to this * segment from another die (layer). 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. @@ -1782,43 +1731,37 @@ struct t_segment_inf { short arch_inter_die_switch = -1; /** - * @brief The fraction of logic blocks along its length to which this segment can connect. + * @brief The fraction of logic blocks along its length to which this segment can connect. * (i.e. internal population). */ float frac_cb; /** - * @brief The fraction of the length + 1 switch blocks along the segment to which the segment can connect. + * @brief The fraction of the length + 1 switch blocks along the segment to which the segment can connect. * Segments that aren't long lines must connect to at least two switch boxes. */ float frac_sb; bool longline; - /** - * @brief The resistance of a routing track, per unit logic block length. */ + /// The resistance of a routing track, per unit logic block length. float Rmetal; - /** - * @brief The capacitance of a routing track, per unit logic block length. */ + /// The capacitance of a routing track, per unit logic block length. float Cmetal; enum e_directionality directionality; /** - * @brief Defines what axis the segment is parallel to. See e_parallel_axis + * @brief Defines what axis the segment is parallel to. See e_parallel_axis * comments for more details on the values. */ enum e_parallel_axis parallel_axis; - /** - * @brief A vector of booleans indicating whether the segment can connect to a logic block. - */ + /// A vector of booleans indicating whether the segment can connect to a logic block. std::vector cb; - /** - * @brief A vector of booleans indicating whether the segment can connect to a switch block. - */ + /// A vector of booleans indicating whether the segment can connect to a switch block. std::vector sb; /** @@ -2084,101 +2027,6 @@ struct t_direct_inf { int line; }; -enum class SwitchPointOrder { - FIXED, //Switchpoints are ordered as specified in architecture - SHUFFLED //Switchpoints are shuffled (more diversity) -}; - -//A collection of switchpoints associated with a segment -struct t_wire_switchpoints { - std::string segment_name; //The type of segment - std::vector switchpoints; //The indices of wire points along the segment -}; - -/* Used to list information about a set of track segments that should connect through a switchblock */ -struct t_wireconn_inf { - std::vector from_switchpoint_set; //The set of segment/wirepoints representing the 'from' set (union of all t_wire_switchpoints in vector) - std::vector to_switchpoint_set; //The set of segment/wirepoints representing the 'to' set (union of all t_wire_switchpoints in vector) - SwitchPointOrder from_switchpoint_order = SwitchPointOrder::FIXED; //The desired from_switchpoint_set ordering - SwitchPointOrder to_switchpoint_order = SwitchPointOrder::FIXED; //The desired to_switchpoint_set ordering - int switch_override_indx = DEFAULT_SWITCH; // index in switch array of the switch used to override wire_switch of the 'to' set. - // DEFAULT_SWITCH is a sentinel value (i.e. the usual driving switch from a wire for the receiving wire will be used) - - std::string num_conns_formula; /* Specifies how many connections should be made for this wireconn. - * - * '': A specific number of connections - * 'from': The number of generated connections between the 'from' and 'to' sets equals the - * size of the 'from' set. This ensures every element in the from set is connected - * to an element of the 'to' set. - * Note: this it may result in 'to' elements being driven by multiple 'from' - * elements (if 'from' is larger than 'to'), or in some elements of 'to' having - * no driving connections (if 'to' is larger than 'from'). - * 'to': The number of generated connections is set equal to the size of the 'to' set. - * This ensures that each element of the 'to' set has precisely one incoming connection. - * Note: this may result in 'from' elements driving multiple 'to' elements (if 'to' is - * larger than 'from'), or some 'from' elements driving to 'to' elements (if 'from' is - * larger than 'to') - */ -}; - -/* represents a connection between two sides of a switchblock */ -class SB_Side_Connection { - public: - /* specify the two SB sides that form a connection */ - enum e_side from_side = TOP; - enum e_side to_side = TOP; - - void set_sides(enum e_side from, enum e_side to) { - from_side = from; - to_side = to; - } - - SB_Side_Connection() = default; - - SB_Side_Connection(enum e_side from, enum e_side to) - : from_side(from) - , to_side(to) { - } - - /* overload < operator which will be used by std::map */ - bool operator<(const SB_Side_Connection& obj) const { - bool result; - - if (from_side < obj.from_side) { - result = true; - } else { - if (from_side == obj.from_side) { - result = (to_side < obj.to_side) ? true : false; - } else { - result = false; - } - } - - return result; - } -}; - -/* Use a map to index into the string permutation functions used to connect from one side to another */ -typedef std::map> t_permutation_map; - -/* Lists all information about a particular switch block specified in the architecture file */ -struct t_switchblock_inf { - std::string name; /* the name of this switchblock */ - e_sb_location location; /* where on the FPGA this switchblock should be built (i.e. perimeter, core, everywhere) */ - e_directionality directionality; /* the directionality of this switchblock (unidir/bidir) */ - - int x = -1; /* The exact x-axis location that this SB is used, meaningful when type is set to E_XY_specified */ - int y = -1; /* The exact y-axis location that this SB is used, meaningful when type is set to E_XY_specified */ - - /* We can also define a region to apply this SB to all locations falls into this region using regular expression in the architecture file*/ - t_sb_loc_spec reg_x; - t_sb_loc_spec reg_y; - - t_permutation_map permutation_map; /* map holding the permutation functions attributed to this switchblock */ - - std::vector wireconns; /* list of wire types/groups this SB will connect */ -}; - /* Clock related data types used for building a dedicated clock network */ struct t_clock_arch_spec { std::vector clock_networks_arch; diff --git a/libs/libarchfpga/src/read_fpga_interchange_arch.cpp b/libs/libarchfpga/src/read_fpga_interchange_arch.cpp index 53760953a7..9a8acb2663 100644 --- a/libs/libarchfpga/src/read_fpga_interchange_arch.cpp +++ b/libs/libarchfpga/src/read_fpga_interchange_arch.cpp @@ -16,9 +16,9 @@ #include #include #include -#include +#include #include -#include +#include #include #include diff --git a/libs/libarchfpga/src/read_xml_arch_file.cpp b/libs/libarchfpga/src/read_xml_arch_file.cpp index dc76bff281..c265b7d59e 100644 --- a/libs/libarchfpga/src/read_xml_arch_file.cpp +++ b/libs/libarchfpga/src/read_xml_arch_file.cpp @@ -4123,7 +4123,7 @@ static void process_switch_blocks(pugi::xml_node Parent, t_arch* arch, const pug const char* tmp; /* get the number of switchblocks */ - int num_switchblocks = count_children(Parent, "switchblock", loc_data); + const int num_switchblocks = count_children(Parent, "switchblock", loc_data); arch->switchblocks.reserve(num_switchblocks); int layout_index = -1; @@ -4215,16 +4215,16 @@ static void process_switch_blocks(pugi::xml_node Parent, t_arch* arch, const pug } } - /* get switchblock permutation functions */ + // get switchblock permutation functions SubElem = get_first_child(Node, "switchfuncs", loc_data); - read_sb_switchfuncs(SubElem, &sb, loc_data); + read_sb_switchfuncs(SubElem, sb, loc_data); - read_sb_wireconns(arch->switches, Node, &sb, loc_data); + read_sb_wireconns(arch->switches, Node, sb, loc_data); - /* run error checks on switch blocks */ - check_switchblock(&sb, arch); + // run error checks on switch blocks + check_switchblock(sb, arch); - /* assign the sb to the switchblocks vector */ + // assign the sb to the switchblocks vector arch->switchblocks.push_back(sb); Node = Node.next_sibling(Node.name()); diff --git a/libs/libarchfpga/src/switchblock_types.h b/libs/libarchfpga/src/switchblock_types.h new file mode 100644 index 0000000000..24c7fdad02 --- /dev/null +++ b/libs/libarchfpga/src/switchblock_types.h @@ -0,0 +1,148 @@ +#pragma once + +#include +#include +#include + +constexpr int NO_SWITCH = -1; +constexpr int DEFAULT_SWITCH = -2; + +enum e_directionality { + UNI_DIRECTIONAL, + BI_DIRECTIONAL +}; + +/* Orientations. */ +enum e_side : unsigned char { + TOP = 0, + RIGHT = 1, + BOTTOM = 2, + LEFT = 3, + NUM_2D_SIDES = 4, + ABOVE = 5, + UNDER = 7, + NUM_3D_SIDES = 6, +}; + +constexpr std::array TOTAL_2D_SIDES = {{TOP, RIGHT, BOTTOM, LEFT}}; //Set of all side orientations +constexpr std::array TOTAL_2D_SIDE_STRINGS = {{"TOP", "RIGHT", "BOTTOM", "LEFT"}}; //String versions of side orientations + +constexpr std::array TOTAL_3D_SIDES = {{TOP, RIGHT, BOTTOM, LEFT, ABOVE, UNDER}}; //Set of all side orientations including different layers +constexpr std::array TOTAL_3D_SIDE_STRINGS = {{"TOP", "RIGHT", "BOTTOM", "LEFT", "ABOVE", "UNDER"}}; //String versions of side orientations including different layers + +/* Specifies what part of the FPGA a custom switchblock should be built in (i.e. perimeter, core, everywhere) */ +enum class e_sb_location { + E_PERIMETER = 0, + E_CORNER, + E_FRINGE, /* perimeter minus corners */ + E_CORE, + E_EVERYWHERE, + E_XY_SPECIFIED +}; + +/** + * @brief Describes regions that a specific switch block specifications should be applied to + */ +struct t_sb_loc_spec { + int start = -1; + int repeat = -1; + int incr = -1; + int end = -1; +}; + +/* represents a connection between two sides of a switchblock */ +class SBSideConnection { + public: + /* specify the two SB sides that form a connection */ + enum e_side from_side = TOP; + enum e_side to_side = TOP; + + void set_sides(enum e_side from, enum e_side to) { + from_side = from; + to_side = to; + } + + SBSideConnection() = default; + + SBSideConnection(enum e_side from, enum e_side to) + : from_side(from) + , to_side(to) { + } + + /* overload < operator which will be used by std::map */ + bool operator<(const SBSideConnection& obj) const { + bool result; + + if (from_side < obj.from_side) { + result = true; + } else { + if (from_side == obj.from_side) { + result = (to_side < obj.to_side) ? true : false; + } else { + result = false; + } + } + + return result; + } +}; + +enum class SwitchPointOrder { + FIXED, //Switchpoints are ordered as specified in architecture + SHUFFLED //Switchpoints are shuffled (more diversity) +}; + +//A collection of switchpoints associated with a segment +struct t_wire_switchpoints { + std::string segment_name; //The type of segment + std::vector switchpoints; //The indices of wire points along the segment +}; + +/* Used to list information about a set of track segments that should connect through a switchblock */ +struct t_wireconn_inf { + std::vector from_switchpoint_set; //The set of segment/wirepoints representing the 'from' set (union of all t_wire_switchpoints in vector) + std::vector to_switchpoint_set; //The set of segment/wirepoints representing the 'to' set (union of all t_wire_switchpoints in vector) + SwitchPointOrder from_switchpoint_order = SwitchPointOrder::FIXED; //The desired from_switchpoint_set ordering + SwitchPointOrder to_switchpoint_order = SwitchPointOrder::FIXED; //The desired to_switchpoint_set ordering + int switch_override_indx = DEFAULT_SWITCH; // index in switch array of the switch used to override wire_switch of the 'to' set. + // DEFAULT_SWITCH is a sentinel value (i.e. the usual driving switch from a wire for the receiving wire will be used) + + std::string num_conns_formula; /* Specifies how many connections should be made for this wireconn. + * + * '': A specific number of connections + * 'from': The number of generated connections between the 'from' and 'to' sets equals the + * size of the 'from' set. This ensures every element in the from set is connected + * to an element of the 'to' set. + * Note: this it may result in 'to' elements being driven by multiple 'from' + * elements (if 'from' is larger than 'to'), or in some elements of 'to' having + * no driving connections (if 'to' is larger than 'from'). + * 'to': The number of generated connections is set equal to the size of the 'to' set. + * This ensures that each element of the 'to' set has precisely one incoming connection. + * Note: this may result in 'from' elements driving multiple 'to' elements (if 'to' is + * larger than 'from'), or some 'from' elements driving to 'to' elements (if 'from' is + * larger than 'to') + */ +}; + +/* Use a map to index into the string permutation functions used to connect from one side to another */ +typedef std::map> t_permutation_map; + +/** + * @brief Lists all information about a particular switch block specified in the architecture file + */ +struct t_switchblock_inf { + std::string name; ///< the name of this switchblock + e_sb_location location; ///< where on the FPGA this switchblock should be built (i.e. perimeter, core, everywhere) + e_directionality directionality; ///< the directionality of this switchblock (unidir/bidir) + + int x = -1; ///< The exact x-axis location that this SB is used, meaningful when type is set to E_XY_specified + int y = -1; ///< The exact y-axis location that this SB is used, meaningful when type is set to E_XY_specified + + /* We can also define a region to apply this SB to all locations falls into this region using regular expression in the architecture file*/ + t_sb_loc_spec reg_x; + t_sb_loc_spec reg_y; + + t_permutation_map permutation_map; ///< map holding the permutation functions attributed to this switchblock + + std::vector wireconns; ///< list of wire types/groups this SB will connect +}; diff --git a/libs/librrgraph/src/base/check_rr_graph.cpp b/libs/librrgraph/src/base/check_rr_graph.cpp index 62cbb3f590..d774fe4c7e 100644 --- a/libs/librrgraph/src/base/check_rr_graph.cpp +++ b/libs/librrgraph/src/base/check_rr_graph.cpp @@ -165,7 +165,7 @@ void check_rr_graph(const RRGraphView& rr_graph, inode, rr_node_typename[rr_type], to_node, rr_node_typename[to_rr_type], num_edges_to_node); } - //Between two wire segments + // Between two wire segments VTR_ASSERT_MSG(to_rr_type == e_rr_type::CHANX || to_rr_type == e_rr_type::CHANY || to_rr_type == e_rr_type::IPIN, "Expect channel type or input pin type"); VTR_ASSERT_MSG(rr_type == e_rr_type::CHANX || rr_type == e_rr_type::CHANY || rr_type == e_rr_type::OPIN, "Expect channel type or output pin type"); @@ -190,7 +190,7 @@ void check_rr_graph(const RRGraphView& rr_graph, */ if ((to_rr_type == e_rr_type::CHANX || to_rr_type == e_rr_type::CHANY) && (rr_type == e_rr_type::CHANX || rr_type == e_rr_type::CHANY)) { - auto switch_type = rr_graph.rr_switch_inf(RRSwitchId(kv.first)).type(); + SwitchType switch_type = rr_graph.rr_switch_inf(RRSwitchId(kv.first)).type(); VPR_ERROR(VPR_ERROR_ROUTE, "in check_rr_graph: node %d has %d redundant connections to node %d of switch type %d (%s)", inode, kv.second, to_node, kv.first, SWITCH_TYPE_STRINGS[size_t(switch_type)]); @@ -202,14 +202,14 @@ void check_rr_graph(const RRGraphView& rr_graph, check_unbuffered_edges(rr_graph, inode); //Check that all config/non-config edges are appropriately organized - for (auto edge : rr_graph.configurable_edges(RRNodeId(inode))) { + for (t_edge_size edge : rr_graph.configurable_edges(RRNodeId(inode))) { if (!rr_graph.edge_is_configurable(RRNodeId(inode), edge)) { VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "in check_rr_graph: node %d edge %d is non-configurable, but in configurable edges", inode, edge); } } - for (auto edge : rr_graph.non_configurable_edges(RRNodeId(inode))) { + for (t_edge_size edge : rr_graph.non_configurable_edges(RRNodeId(inode))) { if (rr_graph.edge_is_configurable(RRNodeId(inode), edge)) { VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "in check_rr_graph: node %d edge %d is configurable, but in non-configurable edges", inode, edge); @@ -528,40 +528,33 @@ void check_rr_node(const RRGraphView& rr_graph, static void check_unbuffered_edges(const RRGraphView& rr_graph, int from_node) { /* This routine checks that all pass transistors in the routing truly are * * bidirectional. It may be a slow check, so don't use it all the time. */ - - int from_edge, to_node, to_edge, from_num_edges, to_num_edges; - e_rr_type from_rr_type, to_rr_type; - short from_switch_type; - bool trans_matched; - - from_rr_type = rr_graph.node_type(RRNodeId(from_node)); + e_rr_type from_rr_type = rr_graph.node_type(RRNodeId(from_node)); if (from_rr_type != e_rr_type::CHANX && from_rr_type != e_rr_type::CHANY) return; - from_num_edges = rr_graph.num_edges(RRNodeId(from_node)); + int from_num_edges = rr_graph.num_edges(RRNodeId(from_node)); - for (from_edge = 0; from_edge < from_num_edges; from_edge++) { - to_node = size_t(rr_graph.edge_sink_node(RRNodeId(from_node), from_edge)); - to_rr_type = rr_graph.node_type(RRNodeId(to_node)); + for (int from_edge = 0; from_edge < from_num_edges; from_edge++) { + RRNodeId to_node = rr_graph.edge_sink_node(RRNodeId(from_node), from_edge); + e_rr_type to_rr_type = rr_graph.node_type(to_node); if (to_rr_type != e_rr_type::CHANX && to_rr_type != e_rr_type::CHANY) continue; - from_switch_type = rr_graph.edge_switch(RRNodeId(from_node), from_edge); + short from_switch_type = rr_graph.edge_switch(RRNodeId(from_node), from_edge); if (rr_graph.rr_switch_inf(RRSwitchId(from_switch_type)).buffered()) continue; - /* We know that we have a pass transistor from from_node to to_node. Now * - * check that there is a corresponding edge from to_node back to * - * from_node. */ + // We know that we have a pass transistor from from_node to to_node. Now + // check that there is a corresponding edge from to_node back to from_node. - to_num_edges = rr_graph.num_edges(RRNodeId(to_node)); - trans_matched = false; + int to_num_edges = rr_graph.num_edges(to_node); + bool trans_matched = false; - for (to_edge = 0; to_edge < to_num_edges; to_edge++) { - if (size_t(rr_graph.edge_sink_node(RRNodeId(to_node), to_edge)) == size_t(from_node) - && rr_graph.edge_switch(RRNodeId(to_node), to_edge) == from_switch_type) { + for (int to_edge = 0; to_edge < to_num_edges; to_edge++) { + if (size_t(rr_graph.edge_sink_node(to_node, to_edge)) == size_t(from_node) + && rr_graph.edge_switch(to_node, to_edge) == from_switch_type) { trans_matched = true; break; } diff --git a/libs/librrgraph/src/base/rr_graph_obj.cpp b/libs/librrgraph/src/base/rr_graph_obj.cpp index 59654aa099..2955a65ea8 100644 --- a/libs/librrgraph/src/base/rr_graph_obj.cpp +++ b/libs/librrgraph/src/base/rr_graph_obj.cpp @@ -152,7 +152,7 @@ RRIndexedDataId RRGraph::node_cost_index(const RRNodeId& node) const { return RRIndexedDataId(node_cost_indices_[node]); } -Direction RRGraph::node_direction(const RRNodeId& node) const { +Direction RRGraph::node_direction(RRNodeId node) const { VTR_ASSERT_SAFE(valid_node_id(node)); VTR_ASSERT_MSG(node_type(node) == e_rr_type::CHANX || node_type(node) == e_rr_type::CHANY, "Direction valid only for CHANX/CHANY RR nodes"); return node_directions_[node]; diff --git a/libs/librrgraph/src/base/rr_graph_obj.h b/libs/librrgraph/src/base/rr_graph_obj.h index 59aa34edc1..02c98cc545 100644 --- a/libs/librrgraph/src/base/rr_graph_obj.h +++ b/libs/librrgraph/src/base/rr_graph_obj.h @@ -414,7 +414,7 @@ class RRGraph { * see node coordinate for details * only matters the routing track nodes (CHANX and CHANY) */ - Direction node_direction(const RRNodeId& node) const; + Direction node_direction(RRNodeId node) const; /* Get the side where the node physically locates on a logic block. * Mainly applicable to IPIN and OPIN nodes, which locates on the perimeter of logic block diff --git a/libs/librrgraph/src/base/rr_graph_storage.cpp b/libs/librrgraph/src/base/rr_graph_storage.cpp index fe23bbc248..7225f1892b 100644 --- a/libs/librrgraph/src/base/rr_graph_storage.cpp +++ b/libs/librrgraph/src/base/rr_graph_storage.cpp @@ -45,7 +45,7 @@ void t_rr_graph_storage::alloc_and_load_edges(const t_rr_edge_info_set* rr_edges edge_remapped_.reserve(new_capacity); } - for (const auto& new_edge : *rr_edges_to_create) { + for (const t_rr_edge_info& new_edge : *rr_edges_to_create) { emplace_back_edge( new_edge.from_node, new_edge.to_node, diff --git a/libs/libvtrutil/src/vtr_string_view.h b/libs/libvtrutil/src/vtr_string_view.h index cc76c40d85..9a80bb4416 100644 --- a/libs/libvtrutil/src/vtr_string_view.h +++ b/libs/libvtrutil/src/vtr_string_view.h @@ -31,6 +31,10 @@ class string_view { : data_(str) , size_(size) {} + explicit string_view(const std::string& other) + : data_(other.c_str()) + , size_(other.size()) {} + constexpr string_view(const string_view& other) noexcept = default; ///@brief copy constructor constexpr string_view& operator=(const string_view& view) noexcept { diff --git a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp index 92089dbe1d..d8b5749651 100644 --- a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp +++ b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp @@ -125,7 +125,6 @@ * */ -#include #include #include "vtr_assert.h" @@ -145,39 +144,32 @@ using vtr::FormulaParser; using vtr::t_formula_data; -/************ Defines ************/ -/* if defined, switch block patterns are loaded by first computing a row of switch blocks and then - * stamping out the row throughout the FPGA */ - -/* REF_X/REF_Y set a reference coordinate; some look-up structures in this file are computed relative to - * this reference */ -#define REF_X 1 //constexpr int REX_X = 1; <-- basically C++11 defines; more type-safe -#define REF_Y 1 - /************ Classes ************/ -/* contains info about a wire segment type */ -class Wire_Info { +/** Contains info about a wire segment type */ +class WireInfo { public: - int length; /* the length of this type of wire segment in tiles */ - int num_wires; /* total number of wires in a channel segment (basically W) */ - int start; /* the wire index at which this type starts in the channel segment (0..W-1) */ + int length; ///< the length of this type of wire segment in tiles + int num_wires; ///< total number of wires in a channel segment (basically W) + int start; ///< the wire index at which this type starts in the channel segment (0..W-1) void set(int len, int wires, int st) { length = len; num_wires = wires; start = st; } - Wire_Info() { + + WireInfo() { this->set(0, 0, 0); } - Wire_Info(int len, int wires, int st) { + + WireInfo(int len, int wires, int st) { this->set(len, wires, st); } }; struct t_wire_switchpoint { - int wire; //Wire index within the channel - int switchpoint; //Switchpoint of the wire + int wire; ///< Wire index within the channel + int switchpoint; ///< Switchpoint of the wire }; struct t_wireconn_scratchpad { @@ -190,55 +182,66 @@ struct t_wireconn_scratchpad { /************ Typedefs ************/ /* Used to get info about a given wire type based on the name */ -typedef vtr::flat_map t_wire_type_sizes; +typedef vtr::flat_map t_wire_type_sizes; /************ Function Declarations ************/ -/* Counts the number of wires in each wire type in the specified channel */ -static void count_wire_type_sizes(const t_chan_seg_details* channel, int nodes_per_chan, t_wire_type_sizes* wire_type_sizes); +/** + * @brief Counts and summarizes wire types in a routing channel. + * + * Iterates through the given array of segment details for a routing channel, + * grouping segments by wire type (as identified by `type_name()`). + * For each unique wire type, it records: + * - the wire segment length, + * - the number of wires of that type, + * - the start index of the first wire of that type in the array. + * + * @param channel Pointer to an array of `t_chan_seg_details` representing the wires in a channel. + * @param nodes_per_chan The total number of wire segments (i.e., size of the `channel` array). + * @return A map (`t_wire_type_sizes`) from wire type name to `WireInfo` containing size and indexing info for each type. + */ +static t_wire_type_sizes count_wire_type_sizes(const t_chan_seg_details* channel, int nodes_per_chan); /* Compute the wire(s) that the wire at (x, y, from_side, to_side, from_wire) should connect to. * sb_conns is updated with the result */ -static void compute_wire_connections( - int x_coord, - int y_coord, - int layer_coord, - enum e_side from_side, - enum e_side to_side, - const t_chan_details& chan_details_x, - const t_chan_details& chan_details_y, - t_switchblock_inf* sb, - const DeviceGrid& grid, - const t_wire_type_sizes* wire_type_sizes_x, - const t_wire_type_sizes* wire_type_sizes_y, - e_directionality directionality, - t_sb_connection_map* sb_conns, - vtr::RngContainer& rng, - t_wireconn_scratchpad* scratchpad); +static void compute_wire_connections(int x_coord, + int y_coord, + int layer_coord, + enum e_side from_side, + enum e_side to_side, + const t_chan_details& chan_details_x, + const t_chan_details& chan_details_y, + const t_switchblock_inf& sb, + const DeviceGrid& grid, + const t_wire_type_sizes& wire_type_sizes_x, + const t_wire_type_sizes& wire_type_sizes_y, + e_directionality directionality, + t_sb_connection_map* sb_conns, + vtr::RngContainer& rng, + t_wireconn_scratchpad* scratchpad); /* ... sb_conn represents the 'coordinates' of the desired switch block connections */ -static void compute_wireconn_connections( - const DeviceGrid& grid, - e_directionality directionality, - const t_chan_details& from_chan_details, - const t_chan_details& to_chan_details, - Switchblock_Lookup sb_conn, - int from_x, - int from_y, - int from_layer, - int to_x, - int to_y, - int to_layer, - e_rr_type from_chan_type, - e_rr_type to_chan_type, - const t_wire_type_sizes* wire_type_sizes_x, - const t_wire_type_sizes* wire_type_sizes_y, - const t_switchblock_inf* sb, - t_wireconn_inf* wireconn_ptr, - t_sb_connection_map* sb_conns, - vtr::RngContainer& rng, - t_wireconn_scratchpad* scratchpad); - -static int evaluate_num_conns_formula(t_wireconn_scratchpad* scratchpad, std::string num_conns_formula, int from_wire_count, int to_wire_count); +static void compute_wireconn_connections(const DeviceGrid& grid, + e_directionality directionality, + const t_chan_details& from_chan_details, + const t_chan_details& to_chan_details, + SwitchblockLookupKey sb_conn, + int from_x, + int from_y, + int from_layer, + int to_x, + int to_y, + int to_layer, + e_rr_type from_chan_type, + e_rr_type to_chan_type, + const t_wire_type_sizes& wire_type_sizes_from, + const t_wire_type_sizes& wire_type_sizes_to, + const t_switchblock_inf& sb, + const t_wireconn_inf& wireconn, + t_sb_connection_map* sb_conns, + vtr::RngContainer& rng, + t_wireconn_scratchpad* scratchpad); + +static int evaluate_num_conns_formula(t_wireconn_scratchpad* scratchpad, const std::string& num_conns_formula, int from_wire_count, int to_wire_count); /** * @@ -256,22 +259,20 @@ static int evaluate_num_conns_formula(t_wireconn_scratchpad* scratchpad, std::st * @param order switchpoint order (fixed, shuffled) specified in the architecture file * @param rand_state used to randomly shuffle switchpoint if required (shuffled order) * @param output_wires collected wire indices that matches the specified types and switchpoints - * */ -static void get_switchpoint_wires( - const DeviceGrid& grid, - const t_chan_seg_details* chan_details, - e_rr_type chan_type, - int x, - int y, - e_side side, - const std::vector& wire_switchpoints_vec, - const t_wire_type_sizes* wire_type_sizes, - bool is_dest, - SwitchPointOrder order, - vtr::RngContainer& rng, - std::vector* output_wires, - std::vector* scratch_wires); +static void get_switchpoint_wires(const DeviceGrid& grid, + const t_chan_seg_details* chan_details, + e_rr_type chan_type, + int x, + int y, + e_side side, + const std::vector& wire_switchpoints_vec, + const t_wire_type_sizes& wire_type_sizes, + bool is_dest, + SwitchPointOrder switchpoint_order, + vtr::RngContainer& rng, + std::vector* output_wires, + std::vector* scratch_wires); /** * @brief finds the correct channel (x or y), and the coordinates to index into it based on the @@ -281,7 +282,7 @@ static void get_switchpoint_wires( * @param tile_y y-coordinate of the tile * @param tile_layer layer-coordinate of the tile * @param src_side switch block source side - * @param dest_side swtich block destination side + * @param dest_side switch block destination side * @param chan_details_x x-channel segment details (length, start and end points, ...) * @param chan_details_y x-channel segment details (length, start and end points, ...) * @param chan_x x-coordinate of the channel @@ -291,7 +292,17 @@ static void get_switchpoint_wires( * * @return returns the type of channel that we are indexing into (ie, CHANX or CHANY) and channel coordinates and type */ -static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, int tile_layer, enum e_side src_side, enum e_side dest_side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int& chan_x, int& chan_y, int& chan_layer, e_rr_type& chan_type); +static const t_chan_details& index_into_correct_chan(int tile_x, + int tile_y, + int tile_layer, + enum e_side src_side, + enum e_side dest_side, + const t_chan_details& chan_details_x, + const t_chan_details& chan_details_y, + int& chan_x, + int& chan_y, + int& chan_layer, + e_rr_type& chan_type); /** * @brief check whether a specific track location is valid within the device grid @@ -313,7 +324,11 @@ int get_wire_segment_length(const DeviceGrid& grid, e_rr_type chan_type, const t /* Returns the switchpoint of the wire specified by wire_details at a segment coordinate * of seg_coord, and connection to the sb_side of the switchblock */ -static int get_switchpoint_of_wire(const DeviceGrid& grid, e_rr_type chan_type, const t_chan_seg_details& wire_details, int seg_coord, e_side sb_side); +static int get_switchpoint_of_wire(const DeviceGrid& grid, + e_rr_type chan_type, + const t_chan_seg_details& wire_details, + int seg_coord, + e_side sb_side); /** * @brief check whether a switch block exists in a specified coordinate within the device grid @@ -327,7 +342,12 @@ static int get_switchpoint_of_wire(const DeviceGrid& grid, e_rr_type chan_type, * * @return true if a switch block exists at the specified location, false otherwise. */ -static bool sb_not_here(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer, const t_switchblock_inf& sb); +static bool sb_not_here(const DeviceGrid& grid, + const std::vector& inter_cluster_rr, + int x, + int y, + int layer, + const t_switchblock_inf& sb); /** * @brief check whether specified coordinate is located at the device grid corner and a switch block exists there @@ -402,56 +422,51 @@ t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_detail const DeviceGrid& grid, const std::vector& inter_cluster_rr, const std::vector& switchblocks, - t_chan_width* nodes_per_chan, + const t_chan_width& nodes_per_chan, e_directionality directionality, vtr::RngContainer& rng) { - /* Holds temporary memory for parsing. */ + // Holds temporary memory for parsing. t_wireconn_scratchpad scratchpad; t_sb_connection_map* sb_conns = new t_sb_connection_map; /* We assume that x & y channels have the same ratios of wire types. i.e., looking at a single * channel is representative of all channels in the FPGA -- as of 3/9/2013 this is true in VPR */ - t_wire_type_sizes wire_type_sizes; - t_wire_type_sizes wire_type_sizes_x; - t_wire_type_sizes wire_type_sizes_y; /* Count the number of wires in each wire type in the specified channel. Note that this is representative of * the wire count for every channel in direction due to the assumption stated above. - * AA: This will not hold if we + * This will not hold if we * 1) support different horizontal and vertical segment distributions - * 2) support non-uniform channel distributions. - * - * Future action item ... + * 2) support non-uniform channel distributions. */ - - count_wire_type_sizes(chan_details_y[0][0].data(), nodes_per_chan->y_max, &wire_type_sizes_y); - count_wire_type_sizes(chan_details_x[0][0].data(), nodes_per_chan->x_max, &wire_type_sizes_x); - count_wire_type_sizes(chan_details_x[0][0].data(), nodes_per_chan->max, &wire_type_sizes); + t_wire_type_sizes wire_type_sizes_y = count_wire_type_sizes(chan_details_y[0][0].data(), nodes_per_chan.y_max); + t_wire_type_sizes wire_type_sizes_x = count_wire_type_sizes(chan_details_x[0][0].data(), nodes_per_chan.x_max); + t_wire_type_sizes wire_type_sizes = count_wire_type_sizes(chan_details_x[0][0].data(), nodes_per_chan.max); /******** slow switch block computation method; computes switchblocks at each coordinate ********/ - /* iterate over all the switchblocks specified in the architecture */ - for (auto sb : switchblocks) { + // Iterate over all the switchblocks specified in the architecture + for (const t_switchblock_inf& sb : switchblocks) { - /* verify that switchblock type matches specified directionality -- currently we have to stay consistent */ + // Verify that switchblock type matches specified directionality -- currently we have to stay consistent if (directionality != sb.directionality) { VPR_FATAL_ERROR(VPR_ERROR_ARCH, "alloc_and_load_switchblock_connections: Switchblock %s does not match directionality of architecture\n", sb.name.c_str()); } - /* Iterate over the x,y, layer coordinates spanning the FPGA, filling in all the switch blocks that exist */ + + // Iterate over the x,y, layer coordinates spanning the FPGA, filling in all the switch blocks that exist for (int layer_coord = 0; layer_coord < grid.get_num_layers(); layer_coord++) { for (size_t x_coord = 0; x_coord < grid.width(); x_coord++) { for (size_t y_coord = 0; y_coord <= grid.height(); y_coord++) { if (sb_not_here(grid, inter_cluster_rr, x_coord, y_coord, layer_coord, sb)) { continue; } - /* now we iterate over all the potential side1->side2 connections */ + + // now we iterate over all the potential side1->side2 connections for (e_side from_side : TOTAL_3D_SIDES) { for (e_side to_side : TOTAL_3D_SIDES) { - /* Fill appropriate entry of the sb_conns map with vector specifying the wires - * the current wire will connect to */ + // Fill appropriate entry of the sb_conns map with vector specifying the wires the current wire will connect to compute_wire_connections(x_coord, y_coord, layer_coord, from_side, to_side, - chan_details_x, chan_details_y, &sb, grid, - &wire_type_sizes_x, &wire_type_sizes_y, directionality, sb_conns, + chan_details_x, chan_details_y, sb, grid, + wire_type_sizes_x, wire_type_sizes_y, directionality, sb_conns, rng, &scratchpad); } } @@ -474,10 +489,14 @@ void free_switchblock_permutations(t_sb_connection_map* sb_conns) { * this significantly reduces memory usage during the routing stage when running multiple * large benchmark circuits in parallel. */ vtr::malloc_trim(0); - return; } -static bool sb_not_here(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer, const t_switchblock_inf& sb) { +static bool sb_not_here(const DeviceGrid& grid, + const std::vector& inter_cluster_rr, + int x, + int y, + int layer, + const t_switchblock_inf& sb) { bool sb_not_here = true; switch (sb.location) { @@ -627,25 +646,23 @@ static bool match_sb_xy(const DeviceGrid& grid, const std::vector& inter_c return false; } -/* Counts the number of wires in each wire type in the specified channel */ -static void count_wire_type_sizes(const t_chan_seg_details* channel, int nodes_per_chan, t_wire_type_sizes* wire_type_sizes) { - vtr::string_view wire_type; - vtr::string_view new_type; - int new_length, length; - int new_start, start; +static t_wire_type_sizes count_wire_type_sizes(const t_chan_seg_details* channel, int nodes_per_chan) { int num_wires = 0; - Wire_Info wire_info; + WireInfo wire_info; + + vtr::string_view wire_type = channel[0].type_name(); + int length = channel[0].length(); + int start = 0; + + t_wire_type_sizes wire_type_sizes; - wire_type = channel[0].type_name(); - length = channel[0].length(); - start = 0; for (int iwire = 0; iwire < nodes_per_chan; iwire++) { - new_type = channel[iwire].type_name(); - new_length = channel[iwire].length(); - new_start = iwire; + vtr::string_view new_type = channel[iwire].type_name(); + int new_length = channel[iwire].length(); + int new_start = iwire; if (new_type != wire_type) { wire_info.set(length, num_wires, start); - (*wire_type_sizes)[wire_type] = wire_info; + wire_type_sizes[wire_type] = wire_info; wire_type = new_type; length = new_length; start = new_start; @@ -653,52 +670,48 @@ static void count_wire_type_sizes(const t_chan_seg_details* channel, int nodes_p } num_wires++; } + wire_info.set(length, num_wires, start); - (*wire_type_sizes)[wire_type] = wire_info; + wire_type_sizes[wire_type] = wire_info; - return; + return wire_type_sizes; } -static void get_switchpoint_wires( - const DeviceGrid& grid, - const t_chan_seg_details* chan_details, - e_rr_type chan_type, - int x, - int y, - e_side side, - const std::vector& wire_switchpoints_vec, - const t_wire_type_sizes* wire_type_sizes, - bool is_dest, - SwitchPointOrder switchpoint_order, - vtr::RngContainer& rng, - std::vector* output_wires, - std::vector* scratch_wires) { +static void get_switchpoint_wires(const DeviceGrid& grid, + const t_chan_seg_details* chan_details, + e_rr_type chan_type, + int x, + int y, + e_side side, + const std::vector& wire_switchpoints_vec, + const t_wire_type_sizes& wire_type_sizes, + bool is_dest, + SwitchPointOrder switchpoint_order, + vtr::RngContainer& rng, + std::vector* output_wires, + std::vector* scratch_wires) { std::vector& all_collected_wire_switchpoints = *output_wires; all_collected_wire_switchpoints.clear(); std::vector& collected_wire_switchpoints = *scratch_wires; - int seg_coord = x; - if (chan_type == e_rr_type::CHANY) { - seg_coord = y; - } + int seg_coord = (chan_type == e_rr_type::CHANY) ? y : x; for (const t_wire_switchpoints& wire_switchpoints : wire_switchpoints_vec) { collected_wire_switchpoints.clear(); - auto wire_type = vtr::string_view( - wire_switchpoints.segment_name.data(), - wire_switchpoints.segment_name.size()); - const auto& points = wire_switchpoints.switchpoints; + auto wire_type = vtr::string_view(wire_switchpoints.segment_name); + const std::vector& points = wire_switchpoints.switchpoints; - if ((*wire_type_sizes).find(wire_type) == (*wire_type_sizes).end()) { + if (wire_type_sizes.find(wire_type) == wire_type_sizes.end()) { // wire_type_sizes may not contain wire_type if its seg freq is 0 continue; } - /* get the number of wires of given type */ - int num_type_wires = wire_type_sizes->at(wire_type).num_wires; - /* get the last wire belonging to this type */ - int first_type_wire = wire_type_sizes->at(wire_type).start; + + // Get the number of wires of given type + int num_type_wires = wire_type_sizes.at(wire_type).num_wires; + // Get the last wire belonging to this type + int first_type_wire = wire_type_sizes.at(wire_type).start; int last_type_wire = first_type_wire + num_type_wires - 1; /* Walk through each wire segment of specified type and check whether it matches one @@ -706,7 +719,7 @@ static void get_switchpoint_wires( * * Note that we walk through the points in order, this ensures that returned switchpoints * match the order specified in the architecture, which we assume is a priority order specified - * by the archtitect. + * by the architect. */ for (int valid_switchpoint : points) { for (int iwire = first_type_wire; iwire <= last_type_wire; iwire++) { @@ -734,7 +747,7 @@ static void get_switchpoint_wires( int wire_switchpoint = get_switchpoint_of_wire(grid, chan_type, chan_details[iwire], seg_coord, side); - /* check if this wire belongs to one of the specified switchpoints; add it to our 'wires' vector if so */ + // Check if this wire belongs to one of the specified switchpoints; add it to our 'wires' vector if so if (wire_switchpoint != valid_switchpoint) continue; collected_wire_switchpoints.push_back({iwire, wire_switchpoint}); @@ -746,12 +759,11 @@ static void get_switchpoint_wires( } if (switchpoint_order == SwitchPointOrder::SHUFFLED) { - //We new re-order the switchpoints to try to make adjacent switchpoints have different values - + // We new re-order the switchpoints to try to make adjacent switchpoints have different values vtr::shuffle(all_collected_wire_switchpoints.begin(), all_collected_wire_switchpoints.end(), rng); } else { VTR_ASSERT(switchpoint_order == SwitchPointOrder::FIXED); - //Already ordered so same switchpoints are adjacent by above collection loop + // Already ordered so same switchpoints are adjacent by above collection loop } } @@ -762,115 +774,111 @@ static void compute_wire_connections(int x_coord, enum e_side to_side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, - t_switchblock_inf* sb, + const t_switchblock_inf& sb, const DeviceGrid& grid, - const t_wire_type_sizes* wire_type_sizes_x, - const t_wire_type_sizes* wire_type_sizes_y, + const t_wire_type_sizes& wire_type_sizes_x, + const t_wire_type_sizes& wire_type_sizes_y, e_directionality directionality, t_sb_connection_map* sb_conns, vtr::RngContainer& rng, t_wireconn_scratchpad* scratchpad) { - int from_x, from_y, from_layer; /* index into source channel */ - int to_x, to_y, to_layer; /* index into destination channel */ - e_rr_type from_chan_type, to_chan_type; /* the type of channel - i.e. CHANX or CHANY */ + int from_x, from_y, from_layer; // index into source channel + int to_x, to_y, to_layer; // index into destination channel + e_rr_type from_chan_type, to_chan_type; // the type of channel - i.e. CHANX or CHANY from_x = from_y = to_x = to_y = from_layer = to_layer = UNDEFINED; - SB_Side_Connection side_conn(from_side, to_side); /* for indexing into this switchblock's permutation funcs */ - Switchblock_Lookup sb_conn(x_coord, y_coord, layer_coord, from_side, to_side); /* for indexing into FPGA's switchblock map */ + // For indexing into this switchblock's permutation funcs + SBSideConnection side_conn(from_side, to_side); + // For indexing into FPGA's switchblock map + SwitchblockLookupKey sb_conn(x_coord, y_coord, layer_coord, from_side, to_side); - /* can't connect a switchblock side to itself */ + // Can't connect a switchblock side to itself if (from_side == to_side) { return; } - /* check that the permutation map has an entry for this side combination */ - if (sb->permutation_map.count(side_conn) == 0) { - /* the specified switchblock does not have any permutation funcs for this side1->side2 connection */ + + // Check that the permutation map has an entry for this side combination + if (sb.permutation_map.count(side_conn) == 0) { + // The specified switchblock does not have any permutation funcs for `from_side` to `to_side` connection return; } /* find the correct channel, and the coordinates to index into it for both the source and * destination channels. also return the channel type (ie chanx/chany/both) into which we are * indexing */ - /* details for source channel */ + // Details for source channel const t_chan_details& from_chan_details = index_into_correct_chan(x_coord, y_coord, layer_coord, from_side, to_side, chan_details_x, chan_details_y, from_x, from_y, from_layer, from_chan_type); - /* details for destination channel */ + // Details for destination channel const t_chan_details& to_chan_details = index_into_correct_chan(x_coord, y_coord, layer_coord, to_side, from_side, chan_details_x, chan_details_y, to_x, to_y, to_layer, to_chan_type); - /* make sure from_x/y and to_x/y aren't out of bounds */ - if (coords_out_of_bounds(grid, to_x, to_y, to_layer, to_chan_type) || coords_out_of_bounds(grid, from_x, from_y, from_layer, from_chan_type)) { + // make sure from_x/y and to_x/y aren't out of bounds + if (coords_out_of_bounds(grid, to_x, to_y, to_layer, to_chan_type) + || coords_out_of_bounds(grid, from_x, from_y, from_layer, from_chan_type)) { return; } - const t_wire_type_sizes* wire_type_sizes_from = wire_type_sizes_x; - const t_wire_type_sizes* wire_type_sizes_to = wire_type_sizes_x; - if (from_chan_type == e_rr_type::CHANY) { - wire_type_sizes_from = wire_type_sizes_y; - } - if (to_chan_type == e_rr_type::CHANY) { - wire_type_sizes_to = wire_type_sizes_y; - } + const t_wire_type_sizes& wire_type_sizes_from = (from_chan_type == e_rr_type::CHANY) ? wire_type_sizes_y : wire_type_sizes_x; + const t_wire_type_sizes& wire_type_sizes_to = (to_chan_type == e_rr_type::CHANY) ? wire_type_sizes_y : wire_type_sizes_x; - /* iterate over all the wire connections specified for this switch block */ - for (int iconn = 0; iconn < (int)sb->wireconns.size(); iconn++) { - /* pointer to a connection specification between wire types/subsegment_nums */ - t_wireconn_inf* wireconn_ptr = &sb->wireconns[iconn]; + // Iterate over all the wire connections specified for this switch block + for (int iconn = 0; iconn < (int)sb.wireconns.size(); iconn++) { + // Pointer to a connection specification between wire types/subsegment_nums + const t_wireconn_inf& wireconn = sb.wireconns[iconn]; - /* compute the destination wire segments to which the source wire segment should connect based on the - * current wireconn */ + // compute the destination wire segments to which the source wire segment should connect based on the current wireconn compute_wireconn_connections(grid, directionality, from_chan_details, to_chan_details, sb_conn, from_x, from_y, from_layer, to_x, to_y, to_layer, from_chan_type, to_chan_type, wire_type_sizes_from, - wire_type_sizes_to, sb, wireconn_ptr, sb_conns, rng, scratchpad); + wire_type_sizes_to, sb, wireconn, sb_conns, rng, scratchpad); } } /* computes the destination wire segments that a source wire segment at the coordinate 'sb_conn' (in - * channel segment with coordinate from_x/from_y) should connect to based on the specified 'wireconn_ptr'. - * wireconn_ptr defines the source and destination sets of wire segments (based on wire segment type & switchpoint + * channel segment with coordinate from_x/from_y) should connect to based on the specified 'wireconn'. + * wireconn defines the source and destination sets of wire segments (based on wire segment type & switchpoint * as defined at the top of this file), and the indices of wires to connect to are relative to these sets */ -static void compute_wireconn_connections( - const DeviceGrid& grid, - e_directionality directionality, - const t_chan_details& from_chan_details, - const t_chan_details& to_chan_details, - Switchblock_Lookup sb_conn, - int from_x, - int from_y, - int from_layer, - int to_x, - int to_y, - int to_layer, - e_rr_type from_chan_type, - e_rr_type to_chan_type, - const t_wire_type_sizes* wire_type_sizes_from, - const t_wire_type_sizes* wire_type_sizes_to, - const t_switchblock_inf* sb, - t_wireconn_inf* wireconn_ptr, - t_sb_connection_map* sb_conns, - vtr::RngContainer& rng, - t_wireconn_scratchpad* scratchpad) { +static void compute_wireconn_connections(const DeviceGrid& grid, + e_directionality directionality, + const t_chan_details& from_chan_details, + const t_chan_details& to_chan_details, + SwitchblockLookupKey sb_conn, + int from_x, + int from_y, + int from_layer, + int to_x, + int to_y, + int to_layer, + e_rr_type from_chan_type, + e_rr_type to_chan_type, + const t_wire_type_sizes& wire_type_sizes_from, + const t_wire_type_sizes& wire_type_sizes_to, + const t_switchblock_inf& sb, + const t_wireconn_inf& wireconn, + t_sb_connection_map* sb_conns, + vtr::RngContainer& rng, + t_wireconn_scratchpad* scratchpad) { constexpr bool verbose = false; - //choose the from_side to be the same as to_side if the connection is travelling across dice in multi-die FPGAs - auto from_side = (sb_conn.from_side != ABOVE && sb_conn.from_side != UNDER) ? sb_conn.from_side : sb_conn.to_side; - //choose the to_side to be the same as from_side if the connection is travelling across dice in multi-die FPGAs - auto to_side = (sb_conn.to_side != ABOVE && sb_conn.to_side != UNDER) ? sb_conn.to_side : sb_conn.from_side; + // Choose the from_side to be the same as to_side if the connection is travelling across dice in multi-die FPGAs + e_side from_side = (sb_conn.from_side != ABOVE && sb_conn.from_side != UNDER) ? sb_conn.from_side : sb_conn.to_side; + // Choose the to_side to be the same as from_side if the connection is travelling across dice in multi-die FPGAs + e_side to_side = (sb_conn.to_side != ABOVE && sb_conn.to_side != UNDER) ? sb_conn.to_side : sb_conn.from_side; /* vectors that will contain indices of the wires belonging to the source/dest wire types/points */ get_switchpoint_wires(grid, from_chan_details[from_x][from_y].data(), from_chan_type, from_x, from_y, from_side, - wireconn_ptr->from_switchpoint_set, wire_type_sizes_from, false, wireconn_ptr->from_switchpoint_order, rng, + wireconn.from_switchpoint_set, wire_type_sizes_from, /*is_dest=*/false, wireconn.from_switchpoint_order, rng, &scratchpad->potential_src_wires, &scratchpad->scratch_wires); get_switchpoint_wires(grid, to_chan_details[to_x][to_y].data(), to_chan_type, to_x, to_y, to_side, - wireconn_ptr->to_switchpoint_set, wire_type_sizes_to, true, - wireconn_ptr->to_switchpoint_order, rng, &scratchpad->potential_dest_wires, + wireconn.to_switchpoint_set, wire_type_sizes_to, /*is_dest=*/true, + wireconn.to_switchpoint_order, rng, &scratchpad->potential_dest_wires, &scratchpad->scratch_wires); - const auto& potential_src_wires = scratchpad->potential_src_wires; - const auto& potential_dest_wires = scratchpad->potential_dest_wires; + const std::vector& potential_src_wires = scratchpad->potential_src_wires; + const std::vector& potential_dest_wires = scratchpad->potential_dest_wires; #ifdef VERBOSE_RR VTR_LOGV(verbose, "SB_LOC: %d,%d %s->%s\n", sb_conn.x_coord, sb_conn.y_coord, TOTAL_2D_SIDE_STRINGS[sb_conn.from_side], TOTAL_2D_SIDE_STRINGS[sb_conn.to_side]); @@ -908,7 +916,7 @@ static void compute_wireconn_connections( #endif if (potential_src_wires.empty() || potential_dest_wires.empty()) { - //Can't make any connections between empty sets + // Can't make any connections between empty sets return; } @@ -922,14 +930,14 @@ static void compute_wireconn_connections( // * randomly shuffle, or // * interleave (to ensure good diversity) - //Determine how many connections to make - int num_conns = evaluate_num_conns_formula(scratchpad, wireconn_ptr->num_conns_formula, potential_src_wires.size(), potential_dest_wires.size()); + // Determine how many connections to make + int num_conns = evaluate_num_conns_formula(scratchpad, wireconn.num_conns_formula, potential_src_wires.size(), potential_dest_wires.size()); VTR_ASSERT_MSG(num_conns >= 0, "Number of switchblock connections to create must be non-negative"); VTR_LOGV(verbose, " num_conns: %zu\n", num_conns); for (size_t iconn = 0; iconn < size_t(num_conns); ++iconn) { - //Select the from wire + // Select the from wire // We modulo by the src set size to wrap around if there are more connections that src wires int src_wire_ind = iconn % potential_src_wires.size(); //Index in src set int from_wire = potential_src_wires[src_wire_ind].wire; //Index in channel @@ -952,24 +960,24 @@ static void compute_wireconn_connections( VTR_ASSERT(from_wire_direction == Direction::BIDIR); } - //Evaluate permutation functions for the from_wire - SB_Side_Connection side_conn(sb_conn.from_side, sb_conn.to_side); - auto iter = sb->permutation_map.find(side_conn); - if (iter == sb->permutation_map.end()) { + // Evaluate permutation functions for the from_wire + SBSideConnection side_conn(sb_conn.from_side, sb_conn.to_side); + auto iter = sb.permutation_map.find(side_conn); + if (iter == sb.permutation_map.end()) { continue; } const std::vector& permutations_ref = iter->second; - for (int iperm = 0; iperm < (int)permutations_ref.size(); iperm++) { + for (const std::string& perm : permutations_ref) { /* Convert the symbolic permutation formula to a number */ t_formula_data& formula_data = scratchpad->formula_data; formula_data.clear(); formula_data.set_var_value("W", dest_W); formula_data.set_var_value("t", src_wire_ind); - int raw_dest_wire_ind = get_sb_formula_raw_result(scratchpad->formula_parser, permutations_ref[iperm].c_str(), formula_data); + int raw_dest_wire_ind = get_sb_formula_raw_result(scratchpad->formula_parser, perm.c_str(), formula_data); int dest_wire_ind = adjust_formula_result(raw_dest_wire_ind, src_W, dest_W, iconn); if (dest_wire_ind < 0) { - VPR_FATAL_ERROR(VPR_ERROR_ARCH, "Got a negative wire from switch block formula %s", permutations_ref[iperm].c_str()); + VPR_FATAL_ERROR(VPR_ERROR_ARCH, "Got a negative wire from switch block formula %s", perm.c_str()); } int to_wire = potential_dest_wires[dest_wire_ind].wire; //Index in channel @@ -983,8 +991,8 @@ static void compute_wireconn_connections( sb_edge.to_wire_layer = to_layer; // if the switch override has been set, use that, Otherwise use default - if (wireconn_ptr->switch_override_indx != DEFAULT_SWITCH) { - sb_edge.switch_ind = wireconn_ptr->switch_override_indx; + if (wireconn.switch_override_indx != DEFAULT_SWITCH) { + sb_edge.switch_ind = wireconn.switch_override_indx; } else if (from_layer == to_layer) { sb_edge.switch_ind = to_chan_details[to_x][to_y][to_wire].arch_wire_switch(); sb_edge.switch_ind_between_layers = -1; //the connection does not cross any layers @@ -995,10 +1003,10 @@ static void compute_wireconn_connections( } VTR_LOGV(verbose, " make_conn: %d -> %d switch=%d\n", sb_edge.from_wire, sb_edge.to_wire, sb_edge.switch_ind); - /* and now, finally, add this switchblock connection to the switchblock connections map */ + // and now, finally, add this switchblock connection to the switchblock connections map (*sb_conns)[sb_conn].push_back(sb_edge); - /* If bidir architecture, implement the reverse connection as well */ + // If bidir architecture, implement the reverse connection as well if (BI_DIRECTIONAL == directionality) { t_switchblock_edge sb_reverse_edge = sb_edge; std::swap(sb_reverse_edge.from_wire, sb_reverse_edge.to_wire); @@ -1006,14 +1014,14 @@ static void compute_wireconn_connections( // //Coverity flags this (false positive), so annotate coverity ignores it: // coverity[swapped_arguments : Intentional] - Switchblock_Lookup sb_conn_reverse(sb_conn.x_coord, sb_conn.y_coord, sb_conn.layer_coord, sb_conn.to_side, sb_conn.from_side); + SwitchblockLookupKey sb_conn_reverse(sb_conn.x_coord, sb_conn.y_coord, sb_conn.layer_coord, sb_conn.to_side, sb_conn.from_side); (*sb_conns)[sb_conn_reverse].push_back(sb_reverse_edge); } } } } -static int evaluate_num_conns_formula(t_wireconn_scratchpad* scratchpad, std::string num_conns_formula, int from_wire_count, int to_wire_count) { +static int evaluate_num_conns_formula(t_wireconn_scratchpad* scratchpad, const std::string& num_conns_formula, int from_wire_count, int to_wire_count) { t_formula_data& vars = scratchpad->formula_data; vars.clear(); @@ -1023,7 +1031,17 @@ static int evaluate_num_conns_formula(t_wireconn_scratchpad* scratchpad, std::st return scratchpad->formula_parser.parse_formula(num_conns_formula, vars); } -static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, int tile_layer, enum e_side src_side, enum e_side dest_side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int& chan_x, int& chan_y, int& chan_layer, e_rr_type& chan_type) { +static const t_chan_details& index_into_correct_chan(int tile_x, + int tile_y, + int tile_layer, + enum e_side src_side, + enum e_side dest_side, + const t_chan_details& chan_details_x, + const t_chan_details& chan_details_y, + int& chan_x, + int& chan_y, + int& chan_layer, + e_rr_type& chan_type) { chan_type = e_rr_type::CHANX; /* here we use the VPR convention that a tile 'owns' the channels directly to the right * and above it */ @@ -1176,9 +1194,13 @@ int get_wire_segment_length(const DeviceGrid& grid, e_rr_type chan_type, const t return wire_length; } -static int get_switchpoint_of_wire(const DeviceGrid& grid, e_rr_type chan_type, const t_chan_seg_details& wire_details, int seg_coord, e_side sb_side) { +static int get_switchpoint_of_wire(const DeviceGrid& grid, + e_rr_type chan_type, + const t_chan_seg_details& wire_details, + int seg_coord, + e_side sb_side) { /* this function calculates the switchpoint of a given wire by first calculating - * the subsegmennt number of the specified wire. For instance, for a wire with L=4: + * the subsegment number of the specified wire. For instance, for a wire with L=4: * * switchpoint: 0-------1-------2-------3-------0 * subsegment_num: 0 1 2 3 @@ -1188,8 +1210,6 @@ static int get_switchpoint_of_wire(const DeviceGrid& grid, e_rr_type chan_type, * */ - int switchpoint; - /* get the minimum and maximum segment coordinate which a wire in this channel type can take */ int min_seg = 1; int max_seg = grid.width() - 2; //-2 for no perim channels @@ -1204,6 +1224,7 @@ static int get_switchpoint_of_wire(const DeviceGrid& grid, e_rr_type chan_type, perimeter_connection = true; } + int switchpoint; if (perimeter_connection) { switchpoint = 0; } else { diff --git a/vpr/src/route/rr_graph_generation/build_switchblocks.h b/vpr/src/route/rr_graph_generation/build_switchblocks.h index 7c75e55358..a7e15ba339 100644 --- a/vpr/src/route/rr_graph_generation/build_switchblocks.h +++ b/vpr/src/route/rr_graph_generation/build_switchblocks.h @@ -10,33 +10,36 @@ /************ Classes, structs, typedefs ************/ -/* Holds the coordinates of a switch block source connection. Used to index into a - * map which specifies which destination wire segments this source wire should //TODO: what data structure does this index to? - * connect to */ -class Switchblock_Lookup { +/** + * @brief Holds the coordinates of a switch block source connection. + * + * Used to index into a map which specifies which destination wire segments this source wire should + * connect to. + */ +class SwitchblockLookupKey { public: - int x_coord; /* x coordinate of switchblock connection */ //TODO: redundant comment?? add range - int y_coord; /* y coordinate of switchblock connection */ - int layer_coord; /* layer number of switchblock */ - e_side from_side; /* source side of switchblock connection */ - e_side to_side; /* destination side of switchblock connection */ - - /* Empty constructor initializes everything to 0 */ - Switchblock_Lookup() { + int x_coord; ///< x coordinate of switchblock connection + int y_coord; ///< y coordinate of switchblock connection + int layer_coord; ///< layer number of switchblock + e_side from_side; ///< source side of switchblock connection + e_side to_side; ///< destination side of switchblock connection + + /// @brief Empty constructor initializes everything to 0 + SwitchblockLookupKey() { x_coord = y_coord = layer_coord = -1; //TODO: use set function } - /* Constructor for initializing member variables */ - Switchblock_Lookup(int set_x, int set_y, int set_layer, e_side set_from, e_side set_to) { - this->set_coords(set_x, set_y, set_layer, set_from, set_to); //TODO: use set function + /// @brief Constructor for initializing member variables + SwitchblockLookupKey(int set_x, int set_y, int set_layer, e_side set_from, e_side set_to) { + this->set_coords(set_x, set_y, set_layer, set_from, set_to); } - /* Constructor for initializing member variables with default layer number (0), used for single die FPGA */ - Switchblock_Lookup(int set_x, int set_y, e_side set_from, e_side set_to) { + /// @brief Constructor for initializing member variables with default layer number (0), used for single die FPGA + SwitchblockLookupKey(int set_x, int set_y, e_side set_from, e_side set_to) { this->set_coords(set_x, set_y, 0, set_from, set_to); } - /* Function for setting the segment coordinates */ + /// @brief Sets the coordinates void set_coords(int set_x, int set_y, int set_layer, e_side set_from, e_side set_to) { x_coord = set_x; y_coord = set_y; @@ -45,8 +48,8 @@ class Switchblock_Lookup { to_side = set_to; } - /* Overload == operator which is used by std::unordered_map */ - bool operator==(const Switchblock_Lookup& obj) const { + /// @brief Overload == operator which is used by std::unordered_map + bool operator==(const SwitchblockLookupKey& obj) const { bool result; if (x_coord == obj.x_coord && y_coord == obj.y_coord && from_side == obj.from_side && to_side == obj.to_side @@ -60,7 +63,7 @@ class Switchblock_Lookup { }; struct t_hash_Switchblock_Lookup { - size_t operator()(const Switchblock_Lookup& obj) const noexcept { + size_t operator()(const SwitchblockLookupKey& obj) const noexcept { std::size_t hash = std::hash{}(obj.x_coord); vtr::hash_combine(hash, obj.y_coord); vtr::hash_combine(hash, obj.layer_coord); @@ -71,37 +74,44 @@ struct t_hash_Switchblock_Lookup { }; /** - * @brief contains the required information to build an RR graph edge for a switch block connection - * - * @from_wire source wire ptc_num index in a channel - * @to_wire destination wire ptc_num index in a channel - * @switch_ind RR graph switch index that connects the source wire to the destination wire that connect two tracks in same layer - * @switch_ind_between_layers RR graph switch index that connects two tracks in different layers - * @from_wire_layer the layer index that the source wire is located at - * @to_wire_layer the layer index that the destination wire is located at - * + * @brief Contains the required information to build an RR graph edge for a switch block connection */ struct t_switchblock_edge { + /// Source wire ptc_num index in a channel short from_wire; + + /// Destination wire ptc_num index in a channel short to_wire; + + /// RR graph switch index that connects the source wire to the destination wire that connect two tracks in same layer short switch_ind; + + /// RR graph switch index that connects two tracks in different layers short switch_ind_between_layers; + + /// The layer index that the source wire is located at short from_wire_layer; + + /// The layer index that the destination wire is located at short to_wire_layer; }; -/* Switchblock connections are made as [x][y][from_layer][from_side][to_side][from_wire_idx]. +/** + * @brief Switchblock connections are made as [x][y][from_layer][from_side][to_side][from_wire_idx]. + * * The Switchblock_Lookup class specifies these dimensions. - * Furthermore, a source_wire at a given 6-d coordinate may connect to multiple destination wires so the value - * of the map is a vector of destination wires. - * A matrix specifying connections for all switchblocks in an FPGA would be sparse and possibly very large - * so we use an unordered map to take advantage of the sparsity. */ -typedef std::unordered_map, t_hash_Switchblock_Lookup> t_sb_connection_map; + * Furthermore, a source_wire at a given 6-d coordinate may connect to multiple destination wires + * so the value of the map is a vector of destination wires. + * + * A matrix specifying connections for all switchblocks in an FPGA would be sparse and possibly very large, + * so we use an unordered map to take advantage of the sparsity. + */ +typedef std::unordered_map, t_hash_Switchblock_Lookup> t_sb_connection_map; /************ Functions ************/ /** - * @brief allocates and builds switch block permutation map + * @brief Allocates and builds switch block permutation map * * @param chan_details_x channel-x details (length, start and end points, ...) * @param chan_details_y channel-y details (length, start and end points, ...) @@ -119,7 +129,7 @@ t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_detail const DeviceGrid& grid, const std::vector& inter_cluster_rr, const std::vector& switchblocks, - t_chan_width* nodes_per_chan, + const t_chan_width& nodes_per_chan, enum e_directionality directionality, vtr::RngContainer& rng); diff --git a/vpr/src/route/rr_graph_generation/rr_graph.cpp b/vpr/src/route/rr_graph_generation/rr_graph.cpp index 9ab6c86dc0..b116816210 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph.cpp +++ b/vpr/src/route/rr_graph_generation/rr_graph.cpp @@ -123,7 +123,7 @@ static vtr::NdMatrix alloc_and_load_pin_to_seg_type(const e_pin_type pin const int seg_index, const int max_Fc, const t_physical_tile_type_ptr tile_type, - const std::set type_layer, + const std::set& type_layer, const bool perturb_switch_pattern, const e_directionality directionality); @@ -1064,10 +1064,10 @@ static void build_rr_graph(e_graph_type graph_type, const int route_verbosity) { vtr::ScopedStartFinishTimer timer("Build routing resource graph"); - /* Reset warning flag */ + // Reset warning flag *Warnings = RR_GRAPH_NO_WARN; - /* Decode the graph_type */ + // Decode the graph_type 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; @@ -1103,7 +1103,7 @@ static void build_rr_graph(e_graph_type graph_type, std::vector seg_details_y; if (is_global_graph) { - /* Sets up a single unit length segment type for global routing. */ + // Sets up a single unit length segment type for global routing. 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); @@ -1117,7 +1117,7 @@ static void build_rr_graph(e_graph_type graph_type, size_t max_dim = std::max(grid.width(), grid.height()) - 2; //-2 for no perim channels - /*Get x & y segments separately*/ + // 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); @@ -1142,7 +1142,7 @@ static void build_rr_graph(e_graph_type graph_type, //} } - /*map the internal segment indices of the networks*/ + // Map the internal segment indices of the networks if (clock_modeling == DEDICATED_NETWORK) { ClockRRGraphBuilder::map_relative_seg_indices(segment_index_map); } @@ -1164,13 +1164,13 @@ static void build_rr_graph(e_graph_type graph_type, /* END CHAN_DETAILS */ /* START FC */ - /* Determine the actual value of Fc */ - std::vector> Fc_in; /* [0..device_ctx.num_block_types-1][0..num_pins-1][0..num_segments-1] */ - std::vector> Fc_out; /* [0..device_ctx.num_block_types-1][0..num_pins-1][0..num_segments-1] */ + // Determine the actual value of Fc + std::vector> Fc_in; // [0..device_ctx.num_block_types-1][0..num_pins-1][0..num_segments-1] + std::vector> Fc_out; // [0..device_ctx.num_block_types-1][0..num_pins-1][0..num_segments-1] - /* get maximum number of pins across all blocks */ + // Get maximum number of pins across all blocks int max_pins = types[0].num_pins; - for (const auto& type : types) { + for (const t_physical_tile_type& type : types) { if (is_empty_type(&type)) { continue; } @@ -1180,7 +1180,7 @@ static void build_rr_graph(e_graph_type graph_type, } } - /* get the number of 'sets' for each segment type -- unidirectional architectures have two tracks in a set, bidirectional have one */ + // Get the number of 'sets' for each segment type -- unidirectional architectures have two tracks in a set, bidirectional have one int total_sets = max_chan_width; int total_sets_x = max_chan_width_x; int total_sets_y = max_chan_width_y; @@ -1196,7 +1196,7 @@ static void build_rr_graph(e_graph_type graph_type, 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 + // All pins can connect during global routing auto ones = vtr::Matrix({size_t(max_pins), segment_inf.size()}, 1); Fc_in = std::vector>(types.size(), ones); Fc_out = std::vector>(types.size(), ones); @@ -1289,7 +1289,7 @@ static void build_rr_graph(e_graph_type graph_type, //is deterministic -- always producing the same RR graph. constexpr unsigned SWITCHPOINT_RNG_SEED = 1; vtr::RngContainer switchpoint_rng(SWITCHPOINT_RNG_SEED); - const auto inter_cluster_prog_rr = device_ctx.inter_cluster_prog_routing_resources; + const std::vector& inter_cluster_prog_rr = device_ctx.inter_cluster_prog_routing_resources; if (is_global_graph) { switch_block_conn = alloc_and_load_switch_block_conn(&nodes_per_chan, SUBSET, 3); @@ -1297,7 +1297,7 @@ static void build_rr_graph(e_graph_type graph_type, if (sb_type == CUSTOM) { sb_conn_map = alloc_and_load_switchblock_permutations(chan_details_x, chan_details_y, grid, inter_cluster_prog_rr, - switchblocks, &nodes_per_chan, directionality, + switchblocks, nodes_per_chan, directionality, switchpoint_rng); } else { switch_block_conn = alloc_and_load_switch_block_conn(&nodes_per_chan, sb_type, Fs); @@ -1309,7 +1309,7 @@ static void build_rr_graph(e_graph_type graph_type, sb_conn_map = alloc_and_load_switchblock_permutations(chan_details_x, chan_details_y, grid, inter_cluster_prog_rr, - switchblocks, &nodes_per_chan, directionality, + switchblocks, nodes_per_chan, directionality, switchpoint_rng); } else { /* it looks like we get unbalanced muxing from this switch block code with Fs > 3 */ @@ -1332,14 +1332,13 @@ static void build_rr_graph(e_graph_type graph_type, } /* END SB LOOKUP */ - /* check whether RR graph need to allocate new nodes for 3D custom switch blocks. - * To avoid wasting memory, the data structures are only allocated if a custom switch block - * is described in the architecture file and we have more than one die in device grid. - */ + // Check whether RR graph need to allocate new nodes for 3D custom switch blocks. + // To avoid wasting memory, the data structures are only allocated if a custom switch block + // is described in the architecture file, and we have more than one die in device grid. if (grid.get_num_layers() > 1 && sb_type == CUSTOM) { - //keep how many nodes each switchblock requires for each x,y location + // Keep how many nodes each switchblock requires for each x,y location vtr::NdMatrix extra_nodes_per_switchblock = get_number_track_to_track_inter_die_conn(sb_conn_map, custom_3d_sb_fanin_fanout, device_ctx.rr_graph_builder); - //allocate new nodes in each switchblocks + // Allocate new nodes in each switchblocks alloc_and_load_inter_die_rr_node_indices(device_ctx.rr_graph_builder, nodes_per_chan, grid, extra_nodes_per_switchblock, &num_rr_nodes); device_ctx.rr_graph_builder.resize_nodes(num_rr_nodes); } @@ -1354,7 +1353,7 @@ static void build_rr_graph(e_graph_type graph_type, t_track_to_pin_lookup track_to_pin_lookup_y(types.size()); for (unsigned int itype = 0; itype < types.size(); ++itype) { - auto type_layer = get_layers_of_physical_types(&types[itype]); + std::set type_layer = get_layers_of_physical_types(&types[itype]); ipin_to_track_map_x[itype] = alloc_and_load_pin_to_track_map(RECEIVER, Fc_in[itype], &types[itype], type_layer, @@ -1416,7 +1415,7 @@ static void build_rr_graph(e_graph_type graph_type, device_ctx.rr_graph_builder.reserve_switches(device_ctx.all_sw_inf.size()); // Create the switches for (const auto& sw_pair : device_ctx.all_sw_inf) { - const auto& arch_sw = sw_pair.second; + const t_arch_switch_inf& arch_sw = sw_pair.second; t_rr_switch_inf rr_switch = create_rr_switch_from_arch_switch(arch_sw, R_minW_nmos, R_minW_pmos); @@ -1868,11 +1867,11 @@ static std::vector> alloc_and_load_perturb_ipins(const int L_n const std::vector>& Fc_out, const enum e_directionality directionality) { std::vector> result(L_num_types); - for (auto& seg_type_bools : result) { + for (std::vector& seg_type_bools : result) { seg_type_bools.resize(num_seg_types, false); } - /* factor to account for unidir vs bidir */ + // factor to account for unidir vs bidir int fac = 1; if (directionality == UNI_DIRECTIONAL) { fac = 2; @@ -1895,15 +1894,13 @@ static std::vector> alloc_and_load_perturb_ipins(const int L_n } if ((Fc_in[itype][0][iseg] <= tracks_in_seg_type - 2) - && (fabs(Fc_ratio - vtr::nint(Fc_ratio)) - < (0.5 / (float)tracks_in_seg_type))) { + && (fabs(Fc_ratio - vtr::nint(Fc_ratio)) < (0.5 / (float)tracks_in_seg_type))) { result[itype][iseg] = true; } } } } else { - /* Unidirectional routing uses mux balancing patterns and - * thus shouldn't need perturbation. */ + // Unidirectional routing uses mux balancing patterns and thus shouldn't need perturbation. VTR_ASSERT(UNI_DIRECTIONAL == directionality); for (int itype = 0; itype < L_num_types; ++itype) { for (int iseg = 0; iseg < num_seg_types; ++iseg) { @@ -1948,13 +1945,13 @@ static std::vector> alloc_and_load_actual_fc(const std::vector< const enum e_directionality directionality, bool* Fc_clipped, bool is_flat) { - //Initialize Fc of all blocks to zero + // Initialize Fc of all blocks to zero auto zeros = vtr::Matrix({size_t(max_pins), segment_inf.size()}, 0); std::vector> Fc(types.size(), zeros); *Fc_clipped = false; - /* Unidir tracks formed in pairs, otherwise no effect. */ + // Unidir tracks formed in pairs, otherwise no effect. int fac = 1; if (UNI_DIRECTIONAL == directionality) { fac = 2; @@ -1962,7 +1959,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 t_physical_tile_type& 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) { @@ -1973,12 +1970,12 @@ static std::vector> alloc_and_load_actual_fc(const std::vector< int iseg = fc_spec.seg_index; if (fc_spec.fc_value == 0) { - /* Special case indicating that this pin does not connect to general-purpose routing */ + // Special case indicating that this pin does not connect to general-purpose routing for (int ipin : fc_spec.pins) { Fc[itype][ipin][iseg] = 0; } } else { - /* General case indicating that this pin connects to general-purpose routing */ + // General case indicating that this pin connects to general-purpose routing //Calculate how many connections there should be across all the pins in this fc_spec int total_connections = 0; @@ -2006,23 +2003,23 @@ static std::vector> alloc_and_load_actual_fc(const std::vector< total_connections = vtr::nint(fc_spec.fc_value) * fc_spec.pins.size(); } - //Ensure that there are at least fac connections, this ensures that low Fc ports - //targeting small sets of segs get connection(s), even if flt_total_connections < fac. + // Ensure that there are at least fac connections, this ensures that low Fc ports + // targeting small sets of segs get connection(s), even if flt_total_connections < fac. total_connections = std::max(total_connections, fac); - //Ensure total evenly divides fac by adding the remainder + // Ensure total evenly divides fac by adding the remainder total_connections += (total_connections % fac); VTR_ASSERT(total_connections > 0); VTR_ASSERT(total_connections % fac == 0); - //We walk through all the pins this fc_spec applies to, adding fac connections - //to each pin, until we run out of connections. This should distribute the connections - //as evenly as possible (if total_connections % pins.size() != 0, there will be - //some inevitable imbalance). + // We walk through all the pins this fc_spec applies to, adding fac connections + // to each pin, until we run out of connections. This should distribute the connections + // as evenly as possible (if total_connections % pins.size() != 0, there will be + // some inevitable imbalance). int connections_remaining = total_connections; while (connections_remaining != 0) { - //Add one set of connections to each pin + // Add one set of connections to each pin for (int ipin : fc_spec.pins) { if (connections_remaining >= fac) { Fc[itype][ipin][iseg] += fac; @@ -2035,8 +2032,8 @@ static std::vector> alloc_and_load_actual_fc(const std::vector< } for (int ipin : fc_spec.pins) { - //It is possible that we may want more connections that wires of this type exist; - //clip to the maximum number of wires + // It is possible that we may want more connections that wires of this type exist; + // clip to the maximum number of wires if (Fc[itype][ipin][iseg] > sets_per_seg_type[iseg] * fac) { *Fc_clipped = true; Fc[itype][ipin][iseg] = sets_per_seg_type[iseg] * fac; @@ -2104,7 +2101,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder /* If Fc gets clipped, this will be flagged to true */ *Fc_clipped = false; - /* This function is called to build the general routing graph resoruces. Thus, + /* This function is called to build the general routing graph resources. Thus, * the edges are not remapped yet.*/ bool switches_remapped = false; @@ -2113,12 +2110,11 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder for (int layer = 0; layer < grid.get_num_layers(); ++layer) { for (int i = 0; i < (int)grid.width(); ++i) { for (int j = 0; j < (int)grid.height(); ++j) { - if (grid.get_width_offset({i, j, layer}) == 0 && grid.get_height_offset({i, j, layer}) == 0) { + if (grid.is_root_location({i, j, layer})) { t_physical_tile_type_ptr physical_tile = grid.get_physical_type({i, j, layer}); - std::vector class_num_vec; - std::vector pin_num_vec; - class_num_vec = get_tile_root_classes(physical_tile); - pin_num_vec = get_tile_root_pins(physical_tile); + std::vector class_num_vec = get_tile_root_classes(physical_tile); + std::vector pin_num_vec = get_tile_root_pins(physical_tile); + add_classes_rr_graph(rr_graph_builder, class_num_vec, layer, @@ -2143,7 +2139,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder physical_tile, switches_remapped); - //Create the actual SOURCE->OPIN, IPIN->SINK edges + // Create the actual SOURCE->OPIN, IPIN->SINK edges uniquify_edges(rr_edges_to_create); alloc_and_load_edges(rr_graph_builder, rr_edges_to_create); num_edges += rr_edges_to_create.size(); @@ -2197,26 +2193,26 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder /* Build channels */ VTR_ASSERT(Fs % 3 == 0); - /* In case of multi-die FPGA and a custom 3D SB, we keep track of how many 3D connections have been already made for each x,y location */ + // In case of multi-die FPGA and a custom 3D SB, we keep track of how many 3D connections have been already made for each x,y location vtr::NdMatrix num_of_3d_conns_custom_SB; - - t_rr_edge_info_set des_3d_rr_edges_to_create; if (grid.get_num_layers() > 1 && sb_conn_map != nullptr) { - num_of_3d_conns_custom_SB.resize(std::array{grid.width(), grid.height()}, 0); + num_of_3d_conns_custom_SB.resize({grid.width(), grid.height()}, 0); } + t_rr_edge_info_set des_3d_rr_edges_to_create; + for (size_t i = 0; i < grid.width() - 1; ++i) { for (size_t j = 0; j < grid.height() - 1; ++j) { for (int layer = 0; layer < grid.get_num_layers(); ++layer) { - auto& device_ctx = g_vpr_ctx.device(); - /* Skip the current die if architecture file specifies that it doesn't require inter-cluster programmable resource routing */ + const auto& device_ctx = g_vpr_ctx.device(); + // Skip the current die if architecture file specifies that it doesn't require inter-cluster programmable resource routing if (!device_ctx.inter_cluster_prog_routing_resources.at(layer)) { continue; } - /* In multi-die FPGAs with track-to-track connections between layers, we need to load newly added length-0 CHANX nodes - * These extra nodes can be driven from many tracks in the source layer and can drive multiple tracks in the destination layer, - * since these die-crossing connections have more delays. - */ + + // In multi-die FPGAs with track-to-track connections between layers, we need to load newly added length-0 CHANX nodes + // These extra nodes can be driven from many tracks in the source layer and can drive multiple tracks in the destination layer, + // since these die-crossing connections have more delays. if (grid.get_num_layers() > 1 && sb_conn_map != nullptr) { //custom switch block defined in the architecture VTR_ASSERT(sblock_pattern.empty() && switch_block_conn.empty()); @@ -2429,8 +2425,8 @@ static void add_classes_rr_graph(RRGraphBuilder& rr_graph_builder, t_physical_tile_type_ptr physical_type) { auto& mutable_device_ctx = g_vpr_ctx.mutable_device(); - for (auto class_num : class_num_vec) { - auto class_type = get_class_type_from_class_physical_num(physical_type, class_num); + for (int class_num : class_num_vec) { + e_pin_type class_type = get_class_type_from_class_physical_num(physical_type, class_num); RRNodeId class_inode = get_class_rr_node_id(rr_graph_builder.node_lookup(), physical_type, layer, root_x, root_y, class_num); VTR_ASSERT(class_inode != RRNodeId::INVALID()); int class_num_pins = get_class_num_pins_from_class_physical_num(physical_type, class_num); @@ -2463,8 +2459,8 @@ static void add_pins_rr_graph(RRGraphBuilder& rr_graph_builder, const int j, t_physical_tile_type_ptr physical_type) { auto& mutable_device_ctx = g_vpr_ctx.mutable_device(); - const auto& node_lookup = rr_graph_builder.node_lookup(); - for (auto pin_num : pin_num_vec) { + const RRSpatialLookup& node_lookup = rr_graph_builder.node_lookup(); + for (int pin_num : pin_num_vec) { e_pin_type pin_type = get_pin_type_from_pin_physical_num(physical_type, pin_num); VTR_ASSERT(pin_type == DRIVER || pin_type == RECEIVER); std::vector x_offset_vec; @@ -2476,7 +2472,7 @@ static void add_pins_rr_graph(RRGraphBuilder& rr_graph_builder, int x_offset = x_offset_vec[pin_coord]; int y_offset = y_offset_vec[pin_coord]; e_side pin_side = pin_sides_vec[pin_coord]; - auto node_type = (pin_type == DRIVER) ? e_rr_type::OPIN : e_rr_type::IPIN; + e_rr_type node_type = (pin_type == DRIVER) ? e_rr_type::OPIN : e_rr_type::IPIN; RRNodeId node_id = node_lookup.find_node(layer, i + x_offset, j + y_offset, @@ -2501,7 +2497,7 @@ static void add_pins_rr_graph(RRGraphBuilder& rr_graph_builder, //which greatly simplifies the drawing code //For those pins located on multiple sides, we save the rr node index //for the pin on all sides at which it exists - //As such, multipler driver problem can be avoided. + //As such, multiple driver problem can be avoided. rr_graph_builder.set_node_coordinates(node_id, i + x_offset, j + y_offset, @@ -2563,12 +2559,12 @@ static void connect_src_sink_to_pins(RRGraphBuilder& rr_graph_builder, const int delayless_switch, t_physical_tile_type_ptr physical_type_ptr, bool switches_remapped) { - for (auto class_num : class_num_vec) { - const auto& pin_list = get_pin_list_from_class_physical_num(physical_type_ptr, class_num); + for (int class_num : class_num_vec) { + const std::vector& pin_list = get_pin_list_from_class_physical_num(physical_type_ptr, class_num); auto class_type = get_class_type_from_class_physical_num(physical_type_ptr, class_num); RRNodeId class_rr_node_id = get_class_rr_node_id(rr_graph_builder.node_lookup(), physical_type_ptr, layer, i, j, class_num); VTR_ASSERT(class_rr_node_id != RRNodeId::INVALID()); - for (auto pin_num : pin_list) { + for (int pin_num : pin_list) { RRNodeId pin_rr_node_id = get_pin_rr_node_id(rr_graph_builder.node_lookup(), physical_type_ptr, layer, i, j, pin_num); if (pin_rr_node_id == RRNodeId::INVALID()) { VTR_LOG_ERROR("In block (%d, %d, %d) pin num: %d doesn't exist to be connected to class %d\n", @@ -2579,7 +2575,7 @@ static void connect_src_sink_to_pins(RRGraphBuilder& rr_graph_builder, class_num); continue; } - auto pin_type = get_pin_type_from_pin_physical_num(physical_type_ptr, pin_num); + e_pin_type pin_type = get_pin_type_from_pin_physical_num(physical_type_ptr, pin_num); if (class_type == DRIVER) { VTR_ASSERT(pin_type == DRIVER); rr_edges_to_create.emplace_back(class_rr_node_id, pin_rr_node_id, delayless_switch, switches_remapped); @@ -3137,7 +3133,7 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, /* this function builds both x and y-directed channel segments, so set up our * coordinates based on channel type */ - auto& device_ctx = g_vpr_ctx.device(); + const auto& device_ctx = g_vpr_ctx.device(); auto& mutable_device_ctx = g_vpr_ctx.mutable_device(); //Initally assumes CHANX @@ -3176,8 +3172,9 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, int start = get_seg_start(seg_details, track, chan_coord, seg_coord); int end = get_seg_end(seg_details, track, start, chan_coord, seg_dimension); - if (seg_coord > start) - continue; /* Only process segments which start at this location */ + if (seg_coord > start) { + continue; // Only process segments which start at this location + } VTR_ASSERT(seg_coord == start); const t_chan_seg_details* from_seg_details = nullptr; @@ -3193,12 +3190,12 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, continue; } - /* Add the edges from this track to all it's connected pins into the list */ + // Add the edges from this track to all it's connected pins into the list get_track_to_pins(rr_graph_builder, layer, start, chan_coord, track, tracks_per_chan, node, rr_edges_to_create, track_to_pin_lookup, seg_details, chan_type, seg_dimension, wire_to_ipin_switch, wire_to_pin_between_dice_switch, directionality); - /* get edges going from the current track into channel segments which are perpendicular to it */ + // Add edges going from the current track into channel segments which are perpendicular to it if (chan_coord > 0) { const t_chan_seg_details* to_seg_details; int max_opposite_chan_width; @@ -3219,6 +3216,7 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, switch_block_conn, sb_conn_map); } } + if (chan_coord < chan_dimension) { const t_chan_seg_details* to_seg_details; int max_opposite_chan_width = 0; @@ -3314,20 +3312,20 @@ static void build_inter_die_custom_sb_rr_chan(RRGraphBuilder& rr_graph_builder, /* 3D connections within the switch blocks use some extra length-0 CHANX node to allow a single 3D connection to be driven * by multiple tracks in the source layer, and drives multiple tracks in the destination layer. - * These nodes has already been added to RRGraph builder, this function will go through all added nodes + * These nodes have already been added to RRGraph builder, this function will go through all added nodes * with specific location (layer, x_coord, y_coord) and sets their attributes. * - * The extra length-0 nodes have the following attributes to make them distinigushable form normal chanx wires (e.g., length-4): + * The extra length-0 nodes have the following attributes to make them distinguishable form normal chanx wires (e.g., length-4): * 1) type: CHANX (could have used either CHANX or CHANY, we used CHANX) * 2) ptc_num: [max_chan_width : max_chan_width + num_of_3d_connections - 1] * 3) length: 0 * 4) xhigh=xlow, yhigh=ylow * 5) directionality: NONE (neither incremental nor decremental in 2D space) */ - int start_track = nodes_per_chan.max; + const int start_track = nodes_per_chan.max; int offset = 0; - while (true) { //going through allocated nodes until no nodes are found within the RRGraph builder + while (true) { // Going through allocated nodes until no nodes are found within the RRGraph builder RRNodeId node = rr_graph_builder.node_lookup().find_node(layer, x_coord, y_coord, e_rr_type::CHANX, start_track + offset); if (node) { rr_graph_builder.set_node_layer(node, layer); @@ -3446,7 +3444,7 @@ static vtr::NdMatrix alloc_and_load_pin_to_seg_type(const e_pin_type pin const int seg_index, const int max_Fc, const t_physical_tile_type_ptr tile_type, - const std::set type_layer, + const std::set& type_layer, const bool perturb_switch_pattern, const e_directionality directionality) { /* Note: currently a single value of Fc is used across each pin. In the future @@ -4135,7 +4133,7 @@ static vtr::NdMatrix, 5> alloc_and_load_track_to_pin_lookup(vtr return track_to_pin_lookup; } -/*AA: +/*AA: * So I need to update this cause the Fc_xofs and Fc_yofs are size of * X and Y segment counts. When going through the side of the logic block, * need to consider what segments to build Fc nodes for. More on this: @@ -4174,7 +4172,7 @@ static void build_unidir_rr_opins(RRGraphBuilder& rr_graph_builder, */ *Fc_clipped = false; - auto type = grid.get_physical_type({i, j, layer}); + t_physical_tile_type_ptr type = grid.get_physical_type({i, j, layer}); int width_offset = grid.get_width_offset({i, j, layer}); int height_offset = grid.get_height_offset({i, j, layer}); @@ -4182,7 +4180,7 @@ static void build_unidir_rr_opins(RRGraphBuilder& rr_graph_builder, /* Go through each pin and find its fanout. */ for (int pin_index = 0; pin_index < type->num_pins; ++pin_index) { /* Skip global pins and pins that are not of DRIVER type */ - auto pin_type = get_pin_type_from_pin_physical_num(type, pin_index); + e_pin_type pin_type = get_pin_type_from_pin_physical_num(type, pin_index); if (pin_type != DRIVER) { continue; } @@ -4248,7 +4246,7 @@ static void build_unidir_rr_opins(RRGraphBuilder& rr_graph_builder, /* Get the list of opin to mux connections for that chan seg. */ bool clipped; - for (auto connected_layer : get_layers_pin_is_connected_to(type, layer, pin_index)) { + for (int connected_layer : get_layers_pin_is_connected_to(type, layer, pin_index)) { /* Check the pin physical layer and connect it to the same layer if necessary */ rr_edge_count += get_unidir_opin_connections(rr_graph_builder, layer, connected_layer, chan, seg, seg_type_Fc, seg_index, chan_type, seg_details, @@ -4276,7 +4274,7 @@ static void build_unidir_rr_opins(RRGraphBuilder& rr_graph_builder, */ 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 auto& device_ctx = g_vpr_ctx.device(); const int num_directs = directs.size(); std::vector clb_to_clb_directs(num_directs); @@ -4294,16 +4292,14 @@ static std::vector alloc_and_load_clb_to_clb_directs(const // 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 - physical_tile = find_tile_type_by_name(tile_name, device_ctx.physical_tile_types); + t_physical_tile_type_ptr 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); + t_physical_tile_port tile_port = find_tile_port_by_name(physical_tile, port_name); if (start_pin_index == OPEN) { VTR_ASSERT(start_pin_index == end_pin_index); diff --git a/vpr/src/route/rr_graph_generation/rr_graph2.cpp b/vpr/src/route/rr_graph_generation/rr_graph2.cpp index d65482ac36..7cef8d589a 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph2.cpp +++ b/vpr/src/route/rr_graph_generation/rr_graph2.cpp @@ -92,7 +92,7 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, const int switch_override, const int custom_3d_sb_fanin_fanout, const int delayless_switch, - t_sb_connection_map* sb_conn_map, + const t_sb_connection_map& sb_conn_map, vtr::NdMatrix& num_of_3d_conns_custom_SB, t_rr_edge_info_set& rr_edges_to_create, t_rr_edge_info_set& des_3d_rr_edges_to_create, @@ -130,7 +130,7 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, const int swtich_override, const int custom_3d_sb_fanin_fanout, const int delayless_switch, - t_sb_connection_map* sb_conn_map, + const t_sb_connection_map& sb_conn_map, vtr::NdMatrix& num_of_3d_conns_custom_SB, RRNodeId from_rr_node, t_rr_edge_info_set& rr_edges_to_create, @@ -736,9 +736,7 @@ int get_bidir_opin_connections(RRGraphBuilder& rr_graph_builder, * Note that this seg_inf vector is NOT the segment_info vectored as stored in the device variable. This index is w.r.t to seg_inf_x * or seg_inf_y for x-adjacent and y-adjacent segments respectively. This index is assigned in get_seg_details earlier * in the rr_graph_builder routine. This t_seg_detail is then used to build t_chan_seg_details which is passed in to label_wire mux - * routine used in this function. - * - * + * routine used in this function. */ int get_unidir_opin_connections(RRGraphBuilder& rr_graph_builder, const int opin_layer, @@ -758,11 +756,7 @@ int get_unidir_opin_connections(RRGraphBuilder& rr_graph_builder, /* 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. */ - int num_inc_muxes, num_dec_muxes, iconn; - int inc_mux, dec_mux; - int inc_track, dec_track; - int x, y; - int num_edges; + int num_inc_muxes, num_dec_muxes; *Fc_clipped = false; @@ -770,14 +764,14 @@ int get_unidir_opin_connections(RRGraphBuilder& rr_graph_builder, VTR_ASSERT(Fc % 2 == 0); /* get_rr_node_indices needs x and y coords. */ - x = ((e_rr_type::CHANX == chan_type) ? seg : chan); - y = ((e_rr_type::CHANX == chan_type) ? chan : seg); + int x = ((e_rr_type::CHANX == chan_type) ? seg : chan); + int y = ((e_rr_type::CHANX == chan_type) ? chan : seg); /* Get the lists of possible muxes. */ int dummy; std::vector inc_muxes; std::vector dec_muxes; - /* AA: Determine the channel width instead of using max channels to not create hanging nodes*/ + // Determine the channel width instead of using max channels to not create hanging nodes int max_chan_width = (e_rr_type::CHANX == chan_type) ? nodes_per_chan.x_list[y] : nodes_per_chan.y_list[x]; label_wire_muxes(chan, seg, seg_details, seg_type_index, max_len, @@ -792,16 +786,16 @@ int get_unidir_opin_connections(RRGraphBuilder& rr_graph_builder, } /* Assign tracks to meet Fc demand */ - num_edges = 0; - for (iconn = 0; iconn < (Fc / 2); ++iconn) { + int num_edges = 0; + for (int iconn = 0; iconn < (Fc / 2); ++iconn) { /* Figure of the next mux to use for the 'inc' and 'dec' connections */ - inc_mux = Fc_ofs[chan][seg][seg_type_index] % num_inc_muxes; - dec_mux = Fc_ofs[chan][seg][seg_type_index] % num_dec_muxes; + int inc_mux = Fc_ofs[chan][seg][seg_type_index] % num_inc_muxes; + int dec_mux = Fc_ofs[chan][seg][seg_type_index] % num_dec_muxes; ++Fc_ofs[chan][seg][seg_type_index]; /* Figure out the track it corresponds to. */ - inc_track = inc_muxes[inc_mux]; - dec_track = dec_muxes[dec_mux]; + int inc_track = inc_muxes[inc_mux]; + int dec_track = dec_muxes[dec_mux]; /* Figure the inodes of those muxes */ RRNodeId inc_inode_index = rr_graph_builder.node_lookup().find_node(track_layer, x, y, chan_type, inc_track); @@ -812,7 +806,7 @@ int get_unidir_opin_connections(RRGraphBuilder& rr_graph_builder, } /* Add to the list. */ - auto to_switch = (opin_layer == track_layer) ? seg_details[inc_track].arch_opin_switch() : seg_details[inc_track].arch_inter_die_switch(); + short to_switch = (opin_layer == track_layer) ? seg_details[inc_track].arch_opin_switch() : seg_details[inc_track].arch_inter_die_switch(); rr_edges_to_create.emplace_back(from_rr_node, inc_inode_index, to_switch, false); ++num_edges; @@ -1058,7 +1052,15 @@ static bool is_sb_conn_layer_crossing(enum e_side src_side, enum e_side dest_sid return true; } -static bool check_3d_SB_RRnodes(RRGraphBuilder& rr_graph_builder, int x, int y, int from_wire, int from_wire_layer, e_rr_type from_wire_type, int to_wire, int to_wire_layer, e_rr_type to_wire_type) { +static bool check_3d_SB_RRnodes(RRGraphBuilder& rr_graph_builder, + int x, + int y, + int from_wire, + int from_wire_layer, + e_rr_type from_wire_type, + int to_wire, + int to_wire_layer, + e_rr_type to_wire_type) { RRNodeId from_inode = rr_graph_builder.node_lookup().find_node(from_wire_layer, x, y, from_wire_type, from_wire); RRNodeId to_inode = rr_graph_builder.node_lookup().find_node(to_wire_layer, x, y, to_wire_type, to_wire); @@ -1072,38 +1074,38 @@ static bool check_3d_SB_RRnodes(RRGraphBuilder& rr_graph_builder, int x, int y, vtr::NdMatrix get_number_track_to_track_inter_die_conn(t_sb_connection_map* sb_conn_map, const int custom_3d_sb_fanin_fanout, RRGraphBuilder& rr_graph_builder) { - auto& grid_ctx = g_vpr_ctx.device().grid; - vtr::NdMatrix extra_nodes_per_switchblocks; - extra_nodes_per_switchblocks.resize(std::array{grid_ctx.width(), grid_ctx.height()}, 0); + const auto& grid_ctx = g_vpr_ctx.device().grid; + vtr::NdMatrix extra_nodes_per_switchblocks{{grid_ctx.width(), grid_ctx.height()}, 0}; for (size_t y = 0; y < grid_ctx.height(); y++) { for (size_t x = 0; x < grid_ctx.width(); x++) { - for (auto layer = 0; layer < grid_ctx.get_num_layers(); layer++) { + for (int layer = 0; layer < grid_ctx.get_num_layers(); layer++) { + int num_of_3d_conn = 0; - for (auto from_side : TOTAL_3D_SIDES) { - for (auto to_side : TOTAL_3D_SIDES) { - if (!is_sb_conn_layer_crossing(from_side, to_side)) { //this connection is not crossing any layer + for (e_side from_side : TOTAL_3D_SIDES) { + for (e_side to_side : TOTAL_3D_SIDES) { + if (!is_sb_conn_layer_crossing(from_side, to_side)) { // this connection is not crossing any layer continue; - } else { - Switchblock_Lookup sb_coord(x, y, layer, from_side, to_side); - if (sb_conn_map->count(sb_coord) > 0) { - std::vector& conn_vector = (*sb_conn_map)[sb_coord]; - for (int iconn = 0; iconn < (int)conn_vector.size(); ++iconn) { - //check if both from_node and to_node exists in the rr-graph - //CHANY -> CHANX connection - if (check_3d_SB_RRnodes(rr_graph_builder, x, y, conn_vector[iconn].from_wire, - conn_vector[iconn].from_wire_layer, e_rr_type::CHANY, - conn_vector[iconn].to_wire, conn_vector[iconn].to_wire_layer, - e_rr_type::CHANX)) { - num_of_3d_conn++; - } - //CHANX -> CHANY connection - if (check_3d_SB_RRnodes(rr_graph_builder, x, y, conn_vector[iconn].from_wire, - conn_vector[iconn].from_wire_layer, e_rr_type::CHANX, - conn_vector[iconn].to_wire, conn_vector[iconn].to_wire_layer, - e_rr_type::CHANY)) { - num_of_3d_conn++; - } + } + + SwitchblockLookupKey sb_coord(x, y, layer, from_side, to_side); + if (sb_conn_map->count(sb_coord) > 0) { + std::vector& conn_vector = (*sb_conn_map)[sb_coord]; + for (const t_switchblock_edge& iconn : conn_vector) { + // check if both from_node and to_node exists in the rr-graph + // CHANY -> CHANX connection + if (check_3d_SB_RRnodes(rr_graph_builder, x, y, iconn.from_wire, + iconn.from_wire_layer, e_rr_type::CHANY, + iconn.to_wire, iconn.to_wire_layer, + e_rr_type::CHANX)) { + num_of_3d_conn++; + } + // CHANX -> CHANY connection + if (check_3d_SB_RRnodes(rr_graph_builder, x, y, iconn.from_wire, + iconn.from_wire_layer, e_rr_type::CHANX, + iconn.to_wire, iconn.to_wire_layer, + e_rr_type::CHANY)) { + num_of_3d_conn++; } } } @@ -1242,16 +1244,15 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, const int custom_3d_sb_fanin_fanout, const int delayless_switch, const vtr::NdMatrix, 3>& switch_block_conn, - t_sb_connection_map* sb_conn_map) { + const t_sb_connection_map* sb_conn_map) { int to_chan, to_sb; std::vector conn_tracks; bool from_is_sblock, is_behind, Fs_clipped; - enum e_side from_side_a, from_side_b, to_side; - bool custom_switch_block; + enum e_side to_side; /* check whether a custom switch block will be used */ - custom_switch_block = false; - if (sb_conn_map) { + bool custom_switch_block = false; + if (sb_conn_map != nullptr) { custom_switch_block = true; VTR_ASSERT(switch_block_conn.empty()); } @@ -1268,7 +1269,8 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, //end of the current wire segment is located int end_sb_seg = get_seg_end(from_seg_details, from_track, from_seg, from_chan, chan_len); - /* Figure out the sides of SB the from_wire will use */ + // Figure out the sides of SB the from_wire will use + e_side from_side_a, from_side_b; if (e_rr_type::CHANX == from_type) { from_side_a = RIGHT; from_side_b = LEFT; @@ -1278,13 +1280,12 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, from_side_b = BOTTOM; } - //Set the loop bounds so we iterate over the whole wire segment + // Set the loop bounds, so we iterate over the whole wire segment int start = start_sb_seg; int end = end_sb_seg; - //If source and destination segments both lie along the same channel - //we clip the loop bounds to the switch blocks of interest and proceed - //normally + // If source and destination segments both lie along the same channel + // we clip the loop bounds to the switch blocks of interest and proceed normally if (to_type == from_type) { start = to_seg - 1; end = to_seg; @@ -1306,7 +1307,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, from_is_sblock = true; } - auto switch_override = should_create_switchblock(grid, layer, from_chan, sb_seg, from_type, to_type); + int switch_override = should_create_switchblock(grid, layer, from_chan, sb_seg, from_type, to_type); if (switch_override == NO_SWITCH) { continue; //Do not create an SB here } @@ -1373,7 +1374,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, num_conn += get_track_to_chan_seg(rr_graph_builder, layer, max_chan_width, from_track, to_chan, to_seg, to_type, from_side_a, to_side, switch_override, custom_3d_sb_fanin_fanout, delayless_switch, - sb_conn_map, num_of_3d_conns_custom_SB, from_rr_node, rr_edges_to_create, des_3d_rr_edges_to_create); + *sb_conn_map, num_of_3d_conns_custom_SB, from_rr_node, rr_edges_to_create, des_3d_rr_edges_to_create); } } else { if (BI_DIRECTIONAL == directionality) { @@ -1411,7 +1412,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, num_conn += get_track_to_chan_seg(rr_graph_builder, layer, max_chan_width, from_track, to_chan, to_seg, to_type, from_side_b, to_side, switch_override, custom_3d_sb_fanin_fanout, delayless_switch, - sb_conn_map, num_of_3d_conns_custom_SB, from_rr_node, rr_edges_to_create, des_3d_rr_edges_to_create); + *sb_conn_map, num_of_3d_conns_custom_SB, from_rr_node, rr_edges_to_create, des_3d_rr_edges_to_create); } } else { if (BI_DIRECTIONAL == directionality) { @@ -1525,38 +1526,39 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, const int switch_override, const int custom_3d_sb_fanin_fanout, const int delayless_switch, - t_sb_connection_map* sb_conn_map, + const t_sb_connection_map& sb_conn_map, vtr::NdMatrix& num_of_3d_conns_custom_SB, t_rr_edge_info_set& rr_edges_to_create, t_rr_edge_info_set& des_3d_rr_edges_to_create, int& edge_count) { - auto& device_ctx = g_vpr_ctx.device(); - - /* get coordinate to index into the SB map */ - Switchblock_Lookup sb_coord(tile_x, tile_y, layer, from_side, to_side); - if (sb_conn_map->count(sb_coord) > 0) { - /* get reference to the connections vector which lists all destination wires for a given source wire - * at a specific coordinate sb_coord */ - std::vector& conn_vector = (*sb_conn_map)[sb_coord]; - - /* go through the connections... */ - for (int iconn = 0; iconn < (int)conn_vector.size(); ++iconn) { - if (conn_vector.at(iconn).from_wire != from_wire) continue; - - int to_wire = conn_vector.at(iconn).to_wire; - int to_layer = conn_vector.at(iconn).to_wire_layer; - /* Get the index of the switch connecting the two wires */ - int src_switch = conn_vector[iconn].switch_ind; - /* Get the index of the switch connecting the two wires in two layers */ - int src_switch_betwen_layers = conn_vector[iconn].switch_ind_between_layers; - - if (to_layer == layer) { //track-to-track connection within the same layer + const auto& device_ctx = g_vpr_ctx.device(); + + // Coordinate to index into the SB map + SwitchblockLookupKey sb_coord(tile_x, tile_y, layer, from_side, to_side); + if (sb_conn_map.count(sb_coord) > 0) { + // Reference to the connections vector which lists all destination wires for a given source wire + // at a specific coordinate sb_coord + const std::vector& sb_edges = sb_conn_map.at(sb_coord); + + // Go through the connections... + for (const t_switchblock_edge& sb_edge : sb_edges) { + if (sb_edge.from_wire != from_wire) continue; + + int to_wire = sb_edge.to_wire; + int to_layer = sb_edge.to_wire_layer; + // Get the index of the switch connecting the two wires + int src_switch = sb_edge.switch_ind; + // Get the index of the switch connecting the two wires in two layers + int src_switch_betwen_layers = sb_edge.switch_ind_between_layers; + + if (to_layer == layer) { // track-to-track connection within the same layer RRNodeId to_node = rr_graph_builder.node_lookup().find_node(to_layer, to_x, to_y, to_chan_type, to_wire); if (!to_node) { continue; } - //Apply any switch overrides + + // Apply any switch overrides if (should_apply_switch_override(switch_override)) { src_switch = switch_override; } @@ -1565,15 +1567,16 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, ++edge_count; if (device_ctx.arch_switch_inf[src_switch].directionality() == BI_DIRECTIONAL) { - //Add reverse edge since bi-directional + // Add reverse edge since bidirectional rr_edges_to_create.emplace_back(to_node, from_rr_node, src_switch, false); ++edge_count; } - } else { //track-to_track connection crossing layer + } else { // track-to_track connection crossing layer VTR_ASSERT(to_layer != layer); - //check if current connection is valid, since switch block pattern is very general, - //we might see invalid layer in connection, so we just skip those - if ((layer < 0 || layer >= device_ctx.grid.get_num_layers()) || (to_layer < 0 || to_layer >= device_ctx.grid.get_num_layers())) { + // Check if current connection is valid, since switch block pattern is very general, + // we might see invalid layer in connection, so we just skip those + if ((layer < 0 || layer >= device_ctx.grid.get_num_layers()) + || (to_layer < 0 || to_layer >= device_ctx.grid.get_num_layers())) { continue; } @@ -1581,18 +1584,15 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, continue; } - /* - * In order to connect two tracks in different layers, we need to follow these three steps: - * 1) connect "from_tracks" to extra "chanx" node in the same switch blocks - * 2) connect extra "chanx" node located in from_layer to another extra "chanx" node located in to_layer - * 3) connect "chanx" node located in to_layer to "to_track" - * - * +-------------+ +-------------+ +--------------+ +--------------+ - * | from_wire | -----> | extra_chanx | ------> | extra_chanx | ------> | to_wire | - * | (src_layer) | | (src_layer) | | (dest_layer) | | (dest_layer) | - * +-------------+ +-------------+ +--------------+ +--------------+ - * - * */ + // In order to connect two tracks in different layers, we need to follow these three steps: + // 1) connect "from_tracks" to extra "chanx" node in the same switch blocks + // 2) connect extra "chanx" node located in from_layer to another extra "chanx" node located in to_layer + // 3) connect "chanx" node located in to_layer to "to_track" + // +-------------+ +-------------+ +--------------+ +--------------+ + // | from_wire | -----> | extra_chanx | ------> | extra_chanx | ------> | to_wire | + // | (src_layer) | | (src_layer) | | (dest_layer) | | (dest_layer) | + // +-------------+ +-------------+ +--------------+ +--------------+ + int offset = num_of_3d_conns_custom_SB[tile_x][tile_y] / custom_3d_sb_fanin_fanout; RRNodeId track_to_chanx_node = rr_graph_builder.node_lookup().find_node(layer, tile_x, tile_y, e_rr_type::CHANX, max_chan_width + offset); RRNodeId diff_layer_chanx_node = rr_graph_builder.node_lookup().find_node(to_layer, tile_x, tile_y, e_rr_type::CHANX, max_chan_width + offset); @@ -1602,21 +1602,21 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, continue; } - //Apply any switch overrides + // Apply any switch overrides if (should_apply_switch_override(switch_override)) { src_switch = switch_override; } - //add edge between source node at from layer to intermediate node + // Add edge between source node at from layer to intermediate node rr_edges_to_create.emplace_back(from_rr_node, track_to_chanx_node, delayless_switch, false); ++edge_count; - //add edge between intermediate node to destination node at to layer - //might add the same edge more than once + // Add edge between intermediate node to destination node at to layer + // might add the same edge more than once, but redundant edges will be removed before updating the RR graph des_3d_rr_edges_to_create.emplace_back(diff_layer_chanx_node, chanx_to_track_node, src_switch_betwen_layers, false); ++edge_count; - //we only add the following edge between intermediate nodes once for the first 3D connection for each pair of intermediate nodes + // We only add the following edge between intermediate nodes once for the first 3D connection for each pair of intermediate nodes if (num_of_3d_conns_custom_SB[tile_x][tile_y] % custom_3d_sb_fanin_fanout == 0) { rr_edges_to_create.emplace_back(track_to_chanx_node, diff_layer_chanx_node, delayless_switch, false); ++edge_count; @@ -1640,7 +1640,7 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, const int switch_override, const int custom_3d_sb_fanin_fanout, const int delayless_switch, - t_sb_connection_map* sb_conn_map, + const t_sb_connection_map& sb_conn_map, vtr::NdMatrix& num_of_3d_conns_custom_SB, RRNodeId from_rr_node, t_rr_edge_info_set& rr_edges_to_create, @@ -1649,7 +1649,7 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, int to_x, to_y; int tile_x, tile_y; - /* get x/y coordinates from seg/chan coordinates */ + // Get x/y coordinates from seg/chan coordinates if (e_rr_type::CHANX == to_chan_type) { to_x = tile_x = to_seg; to_y = tile_y = to_chan; @@ -1686,7 +1686,7 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, des_3d_rr_edges_to_create, edge_count); - //check sb_conn_map for connections between two layers + // Check sb_conn_map for connections between two layers for (e_side to_another_die_side : {ABOVE, UNDER}) { get_switchblocks_edges(rr_graph_builder, tile_x, @@ -1796,9 +1796,9 @@ static int get_unidir_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, rr_edges_to_create.emplace_back(from_rr_node, to_node, iswitch, false); ++count; - auto& device_ctx = g_vpr_ctx.device(); + const auto& device_ctx = g_vpr_ctx.device(); if (device_ctx.arch_switch_inf[iswitch].directionality() == BI_DIRECTIONAL) { - //Add reverse edge since bi-directional + // Add reverse edge since bidirectional rr_edges_to_create.emplace_back(to_node, from_rr_node, iswitch, false); ++count; } @@ -1998,9 +1998,7 @@ void load_sblock_pattern_lookup(const int i, VTR_ASSERT(j >= 0); VTR_ASSERT(j <= int(grid.height()) - 2); - /* May 12 - 15, 2007 - * - * I identify three types of sblocks in the chip: 1) The core sblock, whose special + /* I identify three types of sblocks in the chip: 1) The core sblock, whose special * property is that the number of muxes (and ending wires) on each side is the same (very useful * property, since it leads to a N-to-N assignment problem with ending wires). 2) The corner sblock * which is same as a L=1 core sblock with 2 sides only (again N-to-N assignment problem). 3) The @@ -2223,7 +2221,6 @@ void load_sblock_pattern_lookup(const int i, * 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. */ - static void label_wire_muxes(const int chan_num, const int seg_num, const t_chan_seg_details* seg_details, @@ -2235,13 +2232,10 @@ static void label_wire_muxes(const int chan_num, std::vector& labels, int* num_wire_muxes, int* num_wire_muxes_cb_restricted) { - int itrack, start, end, num_labels, num_labels_restricted, pass; - bool is_endpoint; - /* COUNT pass then a LOAD pass */ - num_labels = 0; - num_labels_restricted = 0; - for (pass = 0; pass < 2; ++pass) { + int num_labels = 0; + int num_labels_restricted = 0; + for (int pass = 0; pass < 2; ++pass) { /* Alloc the list on LOAD pass */ if (pass > 0) { labels.resize(num_labels); @@ -2250,9 +2244,9 @@ static void label_wire_muxes(const int chan_num, } /* Find the tracks that are starting. */ - for (itrack = 0; itrack < max_chan_width; ++itrack) { - start = get_seg_start(seg_details, itrack, chan_num, seg_num); - end = get_seg_end(seg_details, itrack, start, chan_num, max_len); + for (int itrack = 0; itrack < max_chan_width; ++itrack) { + int start = get_seg_start(seg_details, itrack, chan_num, seg_num); + int end = get_seg_end(seg_details, itrack, start, chan_num, max_len); /* Skip tracks that are undefined */ if (seg_details[itrack].length() == 0) { @@ -2272,7 +2266,7 @@ static void label_wire_muxes(const int chan_num, } /* Determine if we are a wire startpoint */ - is_endpoint = (seg_num == start); + bool is_endpoint = (seg_num == start); if (Direction::DEC == seg_details[itrack].direction()) { is_endpoint = (seg_num == end); } @@ -2316,35 +2310,32 @@ static void label_incoming_wires(const int chan_num, * 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) */ - int itrack, start, end, num_passing, num_ending, pass; - bool sblock_exists, is_endpoint; - /* Alloc the list of labels for the tracks */ labels.resize(max_chan_width); std::fill(labels.begin(), labels.end(), UN_SET); - num_ending = 0; - num_passing = 0; - for (pass = 0; pass < 2; ++pass) { - for (itrack = 0; itrack < max_chan_width; ++itrack) { + int num_ending = 0; + int num_passing = 0; + for (int pass = 0; pass < 2; ++pass) { + for (int itrack = 0; itrack < max_chan_width; ++itrack) { /* Skip tracks that are undefined */ if (seg_details[itrack].length() == 0) { continue; } if (seg_details[itrack].direction() == dir) { - start = get_seg_start(seg_details, itrack, chan_num, seg_num); - end = get_seg_end(seg_details, itrack, start, chan_num, max_len); + int start = get_seg_start(seg_details, itrack, chan_num, seg_num); + int end = get_seg_end(seg_details, itrack, start, chan_num, max_len); /* Determine if we are a wire endpoint */ - is_endpoint = (seg_num == end); + bool is_endpoint = (seg_num == end); if (Direction::DEC == seg_details[itrack].direction()) { is_endpoint = (seg_num == start); } /* Determine if we have a sblock on the wire */ - sblock_exists = is_sblock(chan_num, seg_num, sb_seg, itrack, - seg_details, UNI_DIRECTIONAL); + bool sblock_exists = is_sblock(chan_num, seg_num, sb_seg, itrack, + seg_details, UNI_DIRECTIONAL); switch (pass) { /* On first pass, only load ending wire labels. */ @@ -2358,7 +2349,7 @@ static void label_incoming_wires(const int chan_num, /* On second pass, load the passing wire labels. They * will follow after the ending wire labels. */ case 1: - if ((false == is_endpoint) && sblock_exists) { + if (!is_endpoint && sblock_exists) { labels[itrack] = num_ending + num_passing; ++num_passing; } diff --git a/vpr/src/route/rr_graph_generation/rr_graph2.h b/vpr/src/route/rr_graph_generation/rr_graph2.h index b362c120b5..63df666f2a 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph2.h +++ b/vpr/src/route/rr_graph_generation/rr_graph2.h @@ -12,7 +12,7 @@ /******************* Subroutines exported by rr_graph2.c *********************/ /** - * @brief goes through 3D custom switch blocks and counts how many connections are crossing dice for each switch block. + * @brief Goes through 3D custom switch blocks and counts how many connections are crossing dice for each switch block. * * @param sb_conn_map switch block permutation map * @param rr_graph_builder RRGraphBuilder data structure which allows data modification on a routing resource graph @@ -143,7 +143,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, const int custom_3d_sb_fanin_fanout, const int delayless_switch, const vtr::NdMatrix, 3>& switch_block_conn, - t_sb_connection_map* sb_conn_map); + const t_sb_connection_map* sb_conn_map); t_sblock_pattern alloc_sblock_pattern_lookup(const DeviceGrid& grid, const t_chan_width& nodes_per_chan); diff --git a/vpr/src/route/rr_graph_generation/rr_node_indices.cpp b/vpr/src/route/rr_graph_generation/rr_node_indices.cpp index 4c30959779..eeac71308b 100644 --- a/vpr/src/route/rr_graph_generation/rr_node_indices.cpp +++ b/vpr/src/route/rr_graph_generation/rr_node_indices.cpp @@ -329,15 +329,13 @@ void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, const DeviceGrid& grid, const vtr::NdMatrix& extra_nodes_per_switchblock, int* index) { - /* - * In case of multi-die FPGAs, we add extra nodes (could have used either CHANX or CHANY; we chose to use all CHANX) to - * support inter-die communication coming from switch blocks (connection between two tracks in different layers) - * The extra nodes have the following attribute: - * 1) type = CHANX - * 2) length = 0 (xhigh = xlow, yhigh = ylow) - * 3) ptc = [max_chanx_width:max_chanx_width+number_of_connection-1] - * 4) direction = NONE - */ + // In case of multi-die FPGAs, we add extra nodes (could have used either CHANX or CHANY; we chose to use all CHANX) to + // support inter-die communication coming from switch blocks (connection between two tracks in different layers) + // The extra nodes have the following attribute: + // 1) type = CHANX + // 2) length = 0 (xhigh = xlow, yhigh = ylow) + // 3) ptc = [max_chanx_width:max_chanx_width+number_of_connection-1] + // 4) direction = NONE const auto& device_ctx = g_vpr_ctx.device(); for (int layer = 0; layer < grid.get_num_layers(); layer++) { diff --git a/vpr/src/route/rr_graph_generation/rr_types.h b/vpr/src/route/rr_graph_generation/rr_types.h index 12854d26e1..ab8f4ffca6 100644 --- a/vpr/src/route/rr_graph_generation/rr_types.h +++ b/vpr/src/route/rr_graph_generation/rr_types.h @@ -13,15 +13,13 @@ * * The matrix should be accessed as follows as a result after allocation in rr_graph.cpp: alloc_pin_to_track_lookup (used by unidir and bidir) * [0..device_ctx.physical_tile_types.size()-1][0..num_pins-1][0..width][0..height][0..layer-1][0..3][0..Fc-1] */ - typedef std::vector, 5>> t_pin_to_track_lookup; /* AA: t_pin_to_track_lookup is alloacted first and is then converted to t_track_to_pin lookup by simply redefining the accessing order. * As a result, the matrix should be accessed as follow as a result after allocation in rr_graph.cpp: alloc_track_to_pin_lookup (used by unidir and bidir) * [0..device_ctx.physical_tile_types.size()-1][0..max_chan_width-1][0..width][0..height][0..layer-1][0..3] * - * Note that when we modell different channels based on position not axis, we can't use this anymore and need to have a lookup for each grid location. */ - + * Note that when we model different channels based on position not axis, we can't use this anymore and need to have a lookup for each grid location. */ typedef std::vector, 5>> t_track_to_pin_lookup; /** @@ -157,13 +155,12 @@ class t_chan_seg_details { 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. + // The only unique information about a channel segment is its 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;