From 8c2a4bb23bdc8596bc7bcbe76dd9963963af6919 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Fri, 5 Sep 2025 12:44:32 -0400 Subject: [PATCH 01/58] add build_scatter_gather.cpp/.h files --- libs/libarchfpga/src/scatter_gather_types.h | 3 --- .../build_scatter_gathers.cpp | 14 ++++++++++ .../build_scatter_gathers.h | 7 +++++ .../build_switchblocks.cpp | 26 +++++++++---------- .../rr_graph_generation/build_switchblocks.h | 4 +-- .../3d_SB_inter_die_stratixiv_arch.timing.xml | 25 ++++++++++++++++++ 6 files changed, 61 insertions(+), 18 deletions(-) create mode 100644 vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp create mode 100644 vpr/src/route/rr_graph_generation/build_scatter_gathers.h diff --git a/libs/libarchfpga/src/scatter_gather_types.h b/libs/libarchfpga/src/scatter_gather_types.h index dabc0e50998..5408cf560f0 100644 --- a/libs/libarchfpga/src/scatter_gather_types.h +++ b/libs/libarchfpga/src/scatter_gather_types.h @@ -7,7 +7,6 @@ * @brief Enumeration for the type field of an tag. With UNIDIR the gather pattern makes a mux which is connected by a node * to the scatter pattern of edges. With BIDIR, the structure is made symmetric with a gather mux and a scatter edge pattern on each end * of the node linking them. - * */ enum class e_scatter_gather_type { UNIDIR, ///< Unidirectional connection @@ -16,7 +15,6 @@ enum class e_scatter_gather_type { /** * @brief Struct containing information of an tag. An tag instantiates the scatter-gather pattern in some switchblock locations around the device. - * */ struct t_sg_location { e_sb_location type; ///< Type of locations that the pattern is instantiated at. @@ -41,7 +39,6 @@ struct t_sg_link { * @brief Struct containing information of a tag. When instantiated in the device using sg_locations, * a scatter-gather pattern defined by this struct gathers connections according to gather_pattern, moves through * the device using one of the sg_links and fans out or scatters the connections according to scatter_pattern. - * */ struct t_scatter_gather_pattern { std::string name; diff --git a/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp b/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp new file mode 100644 index 00000000000..5b473d3e262 --- /dev/null +++ b/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp @@ -0,0 +1,14 @@ + +#include "build_scatter_gathers.h" + +#include "scatter_gather_types.h" +#include "vtr_assert.h" + +void alloc_and_load_scatter_gather_connections(const std::vector& scatter_gather_patterns) { + + for (const t_scatter_gather_pattern& sg_pattern : scatter_gather_patterns) { + VTR_ASSERT(sg_pattern.type == e_scatter_gather_type::UNIDIR); + VTR_ASSERT(sg_pattern.sg_locations.size() == 1); + VTR_ASSERT(sg_pattern.sg_locations[0].type == e_sb_location::E_EVERYWHERE); + } +} diff --git a/vpr/src/route/rr_graph_generation/build_scatter_gathers.h b/vpr/src/route/rr_graph_generation/build_scatter_gathers.h new file mode 100644 index 00000000000..3c0808c55c0 --- /dev/null +++ b/vpr/src/route/rr_graph_generation/build_scatter_gathers.h @@ -0,0 +1,7 @@ +#pragma once + +#include "scatter_gather_types.h" + +#include + +void alloc_and_load_scatter_gather_connections(const std::vector& scatter_gather_patterns); \ No newline at end of file diff --git a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp index d8b57496514..2c4b2fa6007 100644 --- a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp +++ b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp @@ -206,8 +206,8 @@ static t_wire_type_sizes count_wire_type_sizes(const t_chan_seg_details* channel static void compute_wire_connections(int x_coord, int y_coord, int layer_coord, - enum e_side from_side, - enum e_side to_side, + e_side from_side, + e_side to_side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, const t_switchblock_inf& sb, @@ -256,8 +256,8 @@ static int evaluate_num_conns_formula(t_wireconn_scratchpad* scratchpad, const s * @param wire_switchpoints_vec valid switch points at the given channel segment * @param wire_type_sizes valid wire types * @param is_dest whether wires are source or destination within a switch block connection - * @param order switchpoint order (fixed, shuffled) specified in the architecture file - * @param rand_state used to randomly shuffle switchpoint if required (shuffled order) + * @param switchpoint_order switchpoint order (fixed, shuffled) specified in the architecture file + * @param rng 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, @@ -295,8 +295,8 @@ static void get_switchpoint_wires(const DeviceGrid& grid, 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, + e_side src_side, + e_side dest_side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int& chan_x, @@ -770,8 +770,8 @@ static void get_switchpoint_wires(const DeviceGrid& grid, static void compute_wire_connections(int x_coord, int y_coord, int layer_coord, - enum e_side from_side, - enum e_side to_side, + e_side from_side, + e_side to_side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, const t_switchblock_inf& sb, @@ -1034,8 +1034,8 @@ static int evaluate_num_conns_formula(t_wireconn_scratchpad* scratchpad, const s 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, + e_side src_side, + e_side dest_side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int& chan_x, @@ -1249,14 +1249,14 @@ static int get_switchpoint_of_wire(const DeviceGrid& grid, return switchpoint; } -/* adjusts the destination wire calculated from a permutation formula to account for negative indicies, +/* adjusts the destination wire calculated from a permutation formula to account for negative indices, * source wire set offset, and modulo by destination wire set size * */ static int adjust_formula_result(int dest_wire, int src_W, int dest_W, int connection_ind) { int result = dest_wire; if (dest_wire < 0) { - //Adjust for negative indicies + //Adjust for negative indices int mult = (-1 * dest_wire) / dest_W + 1; result = dest_wire + mult * dest_W; } @@ -1266,7 +1266,7 @@ static int adjust_formula_result(int dest_wire, int src_W, int dest_W, int conne // The permutation formula produce a 1-to-1 mapping from src track to dest track (i.e. each source // track is mapped to precisely one destination track). This is problematic if we are processing // a wireconn which goes through the source set multiple times (e.g. dest set larger than src set while - // processing a WireConnType::TO), since the permutation formula will only generate src_W track indicies + // processing a WireConnType::TO), since the permutation formula will only generate src_W track indices // (leaving some of the destination tracks unconnected). To ensure we get different destination tracks on // subsequent passes through the same source set, we offset the raw track by a multiple of src_W. Note the // use of integer division; src_mult will equal 0 on the first pass, 1 on the second etc. diff --git a/vpr/src/route/rr_graph_generation/build_switchblocks.h b/vpr/src/route/rr_graph_generation/build_switchblocks.h index a7e15ba3399..589ea0e5ce2 100644 --- a/vpr/src/route/rr_graph_generation/build_switchblocks.h +++ b/vpr/src/route/rr_graph_generation/build_switchblocks.h @@ -120,7 +120,7 @@ typedef std::unordered_map * @param switchblocks switch block information extracted from the architecture file * @param nodes_per_chan number of track in each channel (x,y) * @param directionality specifies the switch block edges direction (unidirectional or bidirectional) - * @param rand_state initialize the random number generator (RNG) + * @param rng the random number generator (RNG) * * @return creates a map between switch blocks (key) and their corresponding edges (value). */ @@ -130,7 +130,7 @@ t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_detail const std::vector& inter_cluster_rr, const std::vector& switchblocks, const t_chan_width& nodes_per_chan, - enum e_directionality directionality, + e_directionality directionality, vtr::RngContainer& rng); /** diff --git a/vtr_flow/arch/multi_die/stratixiv_3d/3d_SB_inter_die_stratixiv_arch.timing.xml b/vtr_flow/arch/multi_die/stratixiv_3d/3d_SB_inter_die_stratixiv_arch.timing.xml index d2dc23f5005..4a7bdb4f2e2 100644 --- a/vtr_flow/arch/multi_die/stratixiv_3d/3d_SB_inter_die_stratixiv_arch.timing.xml +++ b/vtr_flow/arch/multi_die/stratixiv_3d/3d_SB_inter_die_stratixiv_arch.timing.xml @@ -48368,4 +48368,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + From 7101847977c639f421466b594b4033865169fe3b Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Fri, 5 Sep 2025 14:11:07 -0400 Subject: [PATCH 02/58] move sb_not_here() and related function to a new file --- libs/libarchfpga/src/read_xml_arch_file.cpp | 48 ++-- libs/libarchfpga/src/switchblock_types.h | 18 +- .../build_scatter_gathers.cpp | 7 + .../build_switchblocks.cpp | 242 +----------------- ...witchblock_scatter_gather_common_utils.cpp | 219 ++++++++++++++++ .../switchblock_scatter_gather_common_utils.h | 26 ++ 6 files changed, 292 insertions(+), 268 deletions(-) create mode 100644 vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp create mode 100644 vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h diff --git a/libs/libarchfpga/src/read_xml_arch_file.cpp b/libs/libarchfpga/src/read_xml_arch_file.cpp index 676c78d0d35..297c6d577a2 100644 --- a/libs/libarchfpga/src/read_xml_arch_file.cpp +++ b/libs/libarchfpga/src/read_xml_arch_file.cpp @@ -4164,7 +4164,11 @@ static void process_bend(pugi::xml_node Node, t_segment_inf& segment, const int part_len.push_back(list.size() + 1 - sum_len); } -static void calculate_custom_SB_locations(const pugiutil::loc_data& loc_data, const pugi::xml_node& SubElem, const int grid_width, const int grid_height, t_switchblock_inf& sb) { +static void calculate_custom_SB_locations(const pugiutil::loc_data& loc_data, + const pugi::xml_node& SubElem, + const int grid_width, + const int grid_height, + t_switchblock_inf& sb) { auto startx_attr = get_attribute(SubElem, "startx", loc_data, ReqOpt::OPTIONAL); auto endx_attr = get_attribute(SubElem, "endx", loc_data, ReqOpt::OPTIONAL); @@ -4177,24 +4181,24 @@ static void calculate_custom_SB_locations(const pugiutil::loc_data& loc_data, co auto incrx_attr = get_attribute(SubElem, "incrx", loc_data, ReqOpt::OPTIONAL); auto incry_attr = get_attribute(SubElem, "incry", loc_data, ReqOpt::OPTIONAL); - //parse the values from the architecture file and fill out SB region information + // parse the values from the architecture file and fill out SB region information vtr::FormulaParser p; vtr::t_formula_data vars; vars.set_var_value("W", grid_width); vars.set_var_value("H", grid_height); - sb.reg_x.start = startx_attr.empty() ? 0 : p.parse_formula(startx_attr.value(), vars); - sb.reg_y.start = starty_attr.empty() ? 0 : p.parse_formula(starty_attr.value(), vars); + sb.specified_loc.reg_x.start = startx_attr.empty() ? 0 : p.parse_formula(startx_attr.value(), vars); + sb.specified_loc.reg_y.start = starty_attr.empty() ? 0 : p.parse_formula(starty_attr.value(), vars); - sb.reg_x.end = endx_attr.empty() ? (grid_width - 1) : p.parse_formula(endx_attr.value(), vars); - sb.reg_y.end = endy_attr.empty() ? (grid_height - 1) : p.parse_formula(endy_attr.value(), vars); + sb.specified_loc.reg_x.end = endx_attr.empty() ? (grid_width - 1) : p.parse_formula(endx_attr.value(), vars); + sb.specified_loc.reg_y.end = endy_attr.empty() ? (grid_height - 1) : p.parse_formula(endy_attr.value(), vars); - sb.reg_x.repeat = repeatx_attr.empty() ? 0 : p.parse_formula(repeatx_attr.value(), vars); - sb.reg_y.repeat = repeaty_attr.empty() ? 0 : p.parse_formula(repeaty_attr.value(), vars); + sb.specified_loc.reg_x.repeat = repeatx_attr.empty() ? 0 : p.parse_formula(repeatx_attr.value(), vars); + sb.specified_loc.reg_y.repeat = repeaty_attr.empty() ? 0 : p.parse_formula(repeaty_attr.value(), vars); - sb.reg_x.incr = incrx_attr.empty() ? 1 : p.parse_formula(incrx_attr.value(), vars); - sb.reg_y.incr = incry_attr.empty() ? 1 : p.parse_formula(incry_attr.value(), vars); + sb.specified_loc.reg_x.incr = incrx_attr.empty() ? 1 : p.parse_formula(incrx_attr.value(), vars); + sb.specified_loc.reg_y.incr = incry_attr.empty() ? 1 : p.parse_formula(incry_attr.value(), vars); } /* Processes the switchblocklist section from the xml architecture file. @@ -4255,7 +4259,7 @@ static void process_switch_blocks(pugi::xml_node Parent, t_arch* arch, const pug } } - /* get the switchblock coordinate only if sb.location is set to E_XY_SPECIFIED*/ + // Get the switchblock coordinate only if sb.location is set to E_XY_SPECIFIED if (sb.location == e_sb_location::E_XY_SPECIFIED) { if (arch->device_layout == "auto") { archfpga_throw(loc_data.filename_c_str(), loc_data.line(SubElem), @@ -4270,21 +4274,21 @@ static void process_switch_blocks(pugi::xml_node Parent, t_arch* arch, const pug int grid_width = arch->grid_layouts.at(layout_index).width; int grid_height = arch->grid_layouts.at(layout_index).height; - /* Absolute location that this SB must be applied to, -1 if not specified*/ - sb.x = get_attribute(SubElem, "x", loc_data, ReqOpt::OPTIONAL).as_int(-1); - sb.y = get_attribute(SubElem, "y", loc_data, ReqOpt::OPTIONAL).as_int(-1); + // Absolute location that this SB must be applied to, -1 if not specified + sb.specified_loc.x = get_attribute(SubElem, "x", loc_data, ReqOpt::OPTIONAL).as_int(ARCH_FPGA_UNDEFINED_VAL); + sb.specified_loc.y = get_attribute(SubElem, "y", loc_data, ReqOpt::OPTIONAL).as_int(ARCH_FPGA_UNDEFINED_VAL); - //check if the absolute value is within the device grid width and height - if (sb.x >= grid_width || sb.y >= grid_height) { + // Check if the absolute value is within the device grid width and height + if (sb.specified_loc.x >= grid_width || sb.specified_loc.y >= grid_height) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(SubElem), - vtr::string_fmt("Location (%d,%d) is not valid within the grid! grid dimensions are: (%d,%d)\n", sb.x, sb.y, grid_width, grid_height).c_str()); + vtr::string_fmt("Location (%d,%d) is not valid within the grid! grid dimensions are: (%d,%d)\n", + sb.specified_loc.x, sb.specified_loc.y, grid_width, grid_height).c_str()); } - /* if the the switchblock exact location is not specified and a region is specified within the architecture file, - * we have to parse the region specification and apply the SB pattern to all the locations fall into the specified - * region based on device width and height. - */ - if (sb.x == -1 && sb.y == -1) { + // if the switchblock exact location is not specified and a region is specified within the architecture file, + // we have to parse the region specification and apply the SB pattern to all the locations fall into the specified + // region based on device width and height. + if (sb.specified_loc.x == ARCH_FPGA_UNDEFINED_VAL && sb.specified_loc.y == ARCH_FPGA_UNDEFINED_VAL) { calculate_custom_SB_locations(loc_data, SubElem, grid_width, grid_height, sb); } } diff --git a/libs/libarchfpga/src/switchblock_types.h b/libs/libarchfpga/src/switchblock_types.h index 90e3519bf0a..735d5838c38 100644 --- a/libs/libarchfpga/src/switchblock_types.h +++ b/libs/libarchfpga/src/switchblock_types.h @@ -169,6 +169,15 @@ struct t_wireconn_inf { /* Use a map to index into the string permutation functions used to connect from one side to another */ typedef std::map> t_permutation_map; +struct t_specified_loc { + 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; +}; + /** * @brief Lists all information about a particular switch block specified in the architecture file */ @@ -177,14 +186,9 @@ struct t_switchblock_inf { 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 + t_specified_loc specified_loc; + std::vector wireconns; ///< list of wire types/groups this SB will connect }; diff --git a/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp b/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp index 5b473d3e262..1c8f255d16e 100644 --- a/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp +++ b/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp @@ -1,14 +1,21 @@ #include "build_scatter_gathers.h" +#include "globals.h" #include "scatter_gather_types.h" #include "vtr_assert.h" void alloc_and_load_scatter_gather_connections(const std::vector& scatter_gather_patterns) { + const DeviceGrid& grid = g_vpr_ctx.device().grid; + for (const t_scatter_gather_pattern& sg_pattern : scatter_gather_patterns) { VTR_ASSERT(sg_pattern.type == e_scatter_gather_type::UNIDIR); VTR_ASSERT(sg_pattern.sg_locations.size() == 1); VTR_ASSERT(sg_pattern.sg_locations[0].type == e_sb_location::E_EVERYWHERE); + + + + } } diff --git a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp index 2c4b2fa6007..4c19bcf7b56 100644 --- a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp +++ b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp @@ -140,6 +140,7 @@ #include "parse_switchblocks.h" #include "vtr_expr_eval.h" #include "rr_types.h" +#include "switchblock_scatter_gather_common_utils.h" using vtr::FormulaParser; using vtr::t_formula_data; @@ -330,88 +331,6 @@ static int get_switchpoint_of_wire(const DeviceGrid& grid, int seg_coord, e_side sb_side); -/** - * @brief check whether a switch block exists in a specified coordinate within the device grid - * - * @param grid device grid - * @param inter_cluster_rr used to check whether inter-cluster programmable routing resources exist in the current layer - * @param x x-coordinate of the location - * @param y y-coordinate of the location - * @param layer layer-coordinate of the location - * @param sb switchblock information specified in the architecture file - * - * @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); - -/** - * @brief check whether specified coordinate is located at the device grid corner and a switch block exists there - * - * @param grid device grid - * @param inter_cluster_rr used to check whether inter-cluster programmable routing resources exist in the current layer - * @param x x-coordinate of the location - * @param y y-coordinate of the location - * @param layer layer-coordinate of the location - * - * @return true if the specified coordinate represents a corner location within the device grid and a switch block exists there, false otherwise. - */ -static bool is_corner_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer); - -/** - * @brief check whether specified coordinate is located at one of the perimeter device grid locations and a switch block exists there - * - * @param grid device grid - * @param inter_cluster_rr used to check whether inter-cluster programmable routing resources exist in the current layer - * @param x x-coordinate of the location - * @param y y-coordinate of the location - * @param layer layer-coordinate of the location - * - * @return true if the specified coordinate represents a perimeter location within the device grid and a switch block exists there, false otherwise. - */ -static bool is_perimeter_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer); - -/** - * @brief check whether specified coordinate is located at core of the device grid (not perimeter) and a switch block exists there - * - * @param grid device grid - * @param inter_cluster_rr used to check whether inter-cluster programmable routing resources exist in the current layer - * @param x x-coordinate of the location - * @param y y-coordinate of the location - * @param layer layer-coordinate of the location - * - * @return true if the specified coordinate represents a core location within the device grid and a switch block exists there, false otherwise. - */ -static bool is_core_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer); - -/** - * @brief check whether specified coordinate is located in the architecture-specified regions that the switchblock should be applied to - * - * @param grid device grid - * @param inter_cluster_rr used to check whether inter-cluster programmable routing resources exist in the current layer - * @param x x-coordinate of the location - * @param y y-coordinate of the location - * @param sb switchblock information specified in the architecture file - * - * @return true if the specified coordinate falls into the architecture-specified location for this switchblock, false otherwise. - */ -static bool match_sb_xy(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer, const t_switchblock_inf& sb); - -/** - * @brief check whether specified layer has inter-cluster programmable routing resources or not. - * - * @param grid device grid - * @param inter_cluster_rr inter-cluster programmable routing resources availability within different layers in multi-die FPGAs - * @param layer a valid layer index within the device grid, must be between [0..num_layer-1] - * - * @return true if the specified layer contain inter-cluster programmable routing resources, false otherwise. - */ -static bool is_prog_routing_avail(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int layer); - /* adjusts a negative destination wire index calculated from a permutation formula */ static int adjust_formula_result(int dest_wire, int src_W, int dest_W, int connection_ind); @@ -452,11 +371,11 @@ t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_detail 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 all 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)) { + if (sb_not_here(grid, inter_cluster_rr, x_coord, y_coord, layer_coord, sb.location, sb.specified_loc)) { continue; } @@ -491,161 +410,6 @@ void free_switchblock_permutations(t_sb_connection_map* sb_conns) { vtr::malloc_trim(0); } -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) { - case e_sb_location::E_EVERYWHERE: - sb_not_here = false; - break; - case e_sb_location::E_PERIMETER: - if (is_perimeter_sb(grid, inter_cluster_rr, x, y, layer)) { - sb_not_here = false; - } - break; - case e_sb_location::E_CORNER: - if (is_corner_sb(grid, inter_cluster_rr, x, y, layer)) { - sb_not_here = false; - } - break; - case e_sb_location::E_CORE: - if (is_core_sb(grid, inter_cluster_rr, x, y, layer)) { - sb_not_here = false; - } - break; - case e_sb_location::E_FRINGE: - if (is_perimeter_sb(grid, inter_cluster_rr, x, y, layer) && !is_corner_sb(grid, inter_cluster_rr, x, y, layer)) { - sb_not_here = false; - } - break; - case e_sb_location::E_XY_SPECIFIED: - if (match_sb_xy(grid, inter_cluster_rr, x, y, layer, sb)) { - sb_not_here = false; - } - - break; - default: - VPR_FATAL_ERROR(VPR_ERROR_ARCH, "sb_not_here: unrecognized location enum: %d\n", sb.location); - break; - } - return sb_not_here; -} - -static bool is_corner_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer) { - if (!is_prog_routing_avail(grid, inter_cluster_rr, layer)) { - return false; - } - bool is_corner = false; - if ((x == 0 && y == 0) || (x == 0 && y == int(grid.height()) - 2) || //-2 for no perim channels - (x == int(grid.width()) - 2 && y == 0) || //-2 for no perim channels - (x == int(grid.width()) - 2 && y == int(grid.height()) - 2)) { //-2 for no perim channels - is_corner = true; - } - return is_corner; -} - -static bool is_perimeter_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer) { - if (!is_prog_routing_avail(grid, inter_cluster_rr, layer)) { - return false; - } - bool is_perimeter = false; - if (x == 0 || x == int(grid.width()) - 2 || y == 0 || y == int(grid.height()) - 2) { - is_perimeter = true; - } - return is_perimeter; -} - -static bool is_core_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer) { - if (!is_prog_routing_avail(grid, inter_cluster_rr, layer)) { - return false; - } - bool is_core = !is_perimeter_sb(grid, inter_cluster_rr, x, y, layer); - return is_core; -} - -static bool is_prog_routing_avail(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int layer) { - bool is_prog_avail = true; - //make sure layer number is legal - VTR_ASSERT(layer >= 0 && layer < grid.get_num_layers()); - //check if the current layer has programmable routing resources before trying to build a custom switch blocks - if (!inter_cluster_rr.at(layer)) { - is_prog_avail = false; - } - return is_prog_avail; -} - -static bool match_sb_xy(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer, const t_switchblock_inf& sb) { - if (!is_prog_routing_avail(grid, inter_cluster_rr, layer)) { - return false; - } - //if one of sb_x and sb_y is defined, we either know the exact location (x,y) or the exact x location (will apply it to all rows) - //or the exact y location (will apply it to all columns) - if (sb.x != -1 || sb.y != -1) { - if (x == sb.x && y == sb.y) { - return true; - } - - if (x == sb.x && sb.y == -1) { - return true; - } - - if (sb.x == -1 && y == sb.y) { - return true; - } - } - - //if both sb_x and sb_y is not defined, we have a region that we should apply this SB pattern to, we just need to check - //whether the location passed into this function falls within this region or not - //calculate the appropriate region based on the repeatx/repeaty and current location. - //This is to determine whether the given location is part of the current SB specified region with regular expression or not - //After region calculation, the current SB will apply to this location if: - // 1) the given (x,y) location falls into the calculated region - // *AND* - // 2) incrx/incry are respected within the region, this means all locations within the calculated region do - // not necessarily crosspond to the current SB. If incrx/incry is equal to 1, then all locations within the - // calculated region are valid. - - //calculate the region - int x_reg_step = (sb.reg_x.repeat != 0) ? (x - sb.reg_x.start) / sb.reg_x.repeat : sb.reg_x.start; - int y_reg_step = (sb.reg_y.repeat != 0) ? (y - sb.reg_y.start) / sb.reg_y.repeat : sb.reg_y.start; - - //step must be non-negative - x_reg_step = std::max(0, x_reg_step); - y_reg_step = std::max(0, y_reg_step); - - int reg_startx = sb.reg_x.start + (x_reg_step * sb.reg_x.repeat); - int reg_endx = sb.reg_x.end + (x_reg_step * sb.reg_x.repeat); - reg_endx = std::min(reg_endx, int(grid.width() - 1)); - - int reg_starty = sb.reg_y.start + (y_reg_step * sb.reg_y.repeat); - int reg_endy = sb.reg_y.end + (y_reg_step * sb.reg_y.repeat); - reg_endy = std::min(reg_endy, int(grid.height() - 1)); - - //check x coordinate - if (x >= reg_startx && x <= reg_endx) { //should fall into the region - //we also should respect the incrx - //if incrx is not equal to 1, all locations within this region are *NOT* valid - if ((x + reg_startx) % sb.reg_x.incr == 0) { - //valid x coordinate, check for y value - if (y >= reg_starty && y <= reg_endy) { - //check for incry, similar as incrx - if ((y + reg_starty) % sb.reg_y.incr == 0) { - //both x and y are valid - return true; - } - } - } - } - - //if reach here, we don't have sb in this location - return false; -} - static t_wire_type_sizes count_wire_type_sizes(const t_chan_seg_details* channel, int nodes_per_chan) { int num_wires = 0; WireInfo wire_info; diff --git a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp new file mode 100644 index 00000000000..0f4a61b16a0 --- /dev/null +++ b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp @@ -0,0 +1,219 @@ + +#include "switchblock_scatter_gather_common_utils.h" + +#include "vpr_error.h" + +/** + * @brief Check whether specified coordinate is located at the device grid corner and a switch block exists there + * + * @param grid device grid + * @param inter_cluster_rr used to check whether inter-cluster programmable routing resources exist in the current layer + * @param x x-coordinate of the location + * @param y y-coordinate of the location + * @param layer layer-coordinate of the location + * + * @return true if the specified coordinate represents a corner location within the device grid and a switch block exists there, false otherwise. + */ +static bool is_corner_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer); + +/** + * @brief check whether specified coordinate is located at one of the perimeter device grid locations and a switch block exists there + * + * @param grid device grid + * @param inter_cluster_rr used to check whether inter-cluster programmable routing resources exist in the current layer + * @param x x-coordinate of the location + * @param y y-coordinate of the location + * @param layer layer-coordinate of the location + * + * @return true if the specified coordinate represents a perimeter location within the device grid and a switch block exists there, false otherwise. + */ +static bool is_perimeter_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer); + +/** + * @brief check whether specified coordinate is located at core of the device grid (not perimeter) and a switch block exists there + * + * @param grid device grid + * @param inter_cluster_rr used to check whether inter-cluster programmable routing resources exist in the current layer + * @param x x-coordinate of the location + * @param y y-coordinate of the location + * @param layer layer-coordinate of the location + * + * @return true if the specified coordinate represents a core location within the device grid and a switch block exists there, false otherwise. + */ +static bool is_core_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer); + + +/** + * @brief check whether specified coordinate is located in the architecture-specified regions that the switchblock should be applied to + * + * @param grid device grid + * @param inter_cluster_rr used to check whether inter-cluster programmable routing resources exist in the current layer + * @param x x-coordinate of the location + * @param y y-coordinate of the location + * @param sb switchblock information specified in the architecture file + * + * @return true if the specified coordinate falls into the architecture-specified location for this switchblock, false otherwise. + */ +static bool match_sb_xy(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer, const t_specified_loc& sb); + + +static bool is_corner_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer) { + if (!inter_cluster_rr[layer]) { + return false; + } + + bool is_corner = false; + if ((x == 0 && y == 0) || (x == 0 && y == int(grid.height()) - 2) || //-2 for no perim channels + (x == int(grid.width()) - 2 && y == 0) || //-2 for no perim channels + (x == int(grid.width()) - 2 && y == int(grid.height()) - 2)) { //-2 for no perim channels + is_corner = true; + } + return is_corner; +} + +static bool is_perimeter_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer) { + if (!inter_cluster_rr[layer]) { + return false; + } + + bool is_perimeter = false; + if (x == 0 || x == int(grid.width()) - 2 || y == 0 || y == int(grid.height()) - 2) { + is_perimeter = true; + } + return is_perimeter; +} + +static bool is_core_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer) { + if (!inter_cluster_rr[layer]) { + return false; + } + + bool is_core = !is_perimeter_sb(grid, inter_cluster_rr, x, y, layer); + return is_core; +} + +static bool match_sb_xy(const DeviceGrid& grid, + const std::vector& inter_cluster_rr, + int x, + int y, + int layer, + const t_specified_loc& specified_loc) { + if (!inter_cluster_rr[layer]) { + return false; + } + + // if one of sb_x and sb_y is defined, we either know the exact location (x,y) or the exact x location (will apply it to all rows) + // or the exact y location (will apply it to all columns) + if (specified_loc.x != -1 || specified_loc.y != -1) { + if (x == specified_loc.x && y == specified_loc.y) { + return true; + } + + if (x == specified_loc.x && specified_loc.y == -1) { + return true; + } + + if (specified_loc.x == -1 && y == specified_loc.y) { + return true; + } + } + + // if both sb_x and sb_y is not defined, we have a region that we should apply this SB pattern to, we just need to check + // whether the location passed into this function falls within this region or not + // calculate the appropriate region based on the repeatx/repeaty and current location. + // This is to determine whether the given location is part of the current SB specified region with regular expression or not + // After region calculation, the current SB will apply to this location if: + // 1) the given (x,y) location falls into the calculated region + // *AND* + // 2) incrx/incry are respected within the region, this means all locations within the calculated region do + // not necessarily crosspond to the current SB. If incrx/incry is equal to 1, then all locations within the + // calculated region are valid. + + // calculate the region + int x_reg_step = (sb.reg_x.repeat != 0) ? (x - sb.reg_x.start) / sb.reg_x.repeat : sb.reg_x.start; + int y_reg_step = (sb.reg_y.repeat != 0) ? (y - sb.reg_y.start) / sb.reg_y.repeat : sb.reg_y.start; + + // step must be non-negative + x_reg_step = std::max(0, x_reg_step); + y_reg_step = std::max(0, y_reg_step); + + int reg_startx = sb.reg_x.start + (x_reg_step * sb.reg_x.repeat); + int reg_endx = sb.reg_x.end + (x_reg_step * sb.reg_x.repeat); + reg_endx = std::min(reg_endx, int(grid.width() - 1)); + + int reg_starty = sb.reg_y.start + (y_reg_step * sb.reg_y.repeat); + int reg_endy = sb.reg_y.end + (y_reg_step * sb.reg_y.repeat); + reg_endy = std::min(reg_endy, int(grid.height() - 1)); + + // check x coordinate + if (x >= reg_startx && x <= reg_endx) { //should fall into the region + // we also should respect the incrx + // if incrx is not equal to 1, all locations within this region are *NOT* valid + if ((x + reg_startx) % sb.reg_x.incr == 0) { + // valid x coordinate, check for y value + if (y >= reg_starty && y <= reg_endy) { + // check for incry, similar as incrx + if ((y + reg_starty) % sb.reg_y.incr == 0) { + // both x and y are valid + return true; + } + } + } + } + + // if reach here, we don't have sb in this location + return false; +} + + +bool sb_not_here(const DeviceGrid& grid, + const std::vector& inter_cluster_rr, + int x, + int y, + int layer, + e_sb_location sb_location, + const t_specified_loc& specified_loc/*=t_specified_loc()*/) { + bool sb_not_here = true; + + switch (sb_location) { + case e_sb_location::E_EVERYWHERE: + sb_not_here = false; + break; + + case e_sb_location::E_PERIMETER: + if (is_perimeter_sb(grid, inter_cluster_rr, x, y, layer)) { + sb_not_here = false; + } + break; + + case e_sb_location::E_CORNER: + if (is_corner_sb(grid, inter_cluster_rr, x, y, layer)) { + sb_not_here = false; + } + break; + + case e_sb_location::E_CORE: + if (is_core_sb(grid, inter_cluster_rr, x, y, layer)) { + sb_not_here = false; + } + break; + + case e_sb_location::E_FRINGE: + if (is_perimeter_sb(grid, inter_cluster_rr, x, y, layer) && !is_corner_sb(grid, inter_cluster_rr, x, y, layer)) { + sb_not_here = false; + } + break; + + case e_sb_location::E_XY_SPECIFIED: + if (match_sb_xy(grid, inter_cluster_rr, x, y, layer, specified_loc)) { + sb_not_here = false; + } + break; + + default: + VPR_FATAL_ERROR(VPR_ERROR_ARCH, "sb_not_here: unrecognized location enum: %d\n", sb_location); + break; + } + + return sb_not_here; +} \ No newline at end of file diff --git a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h new file mode 100644 index 00000000000..d0752578db0 --- /dev/null +++ b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h @@ -0,0 +1,26 @@ + +#pragma once + +#include "device_grid.h" + +#include + +/** + * @brief check whether a switch block exists in a specified coordinate within the device grid + * + * @param grid device grid + * @param inter_cluster_rr used to check whether inter-cluster programmable routing resources exist in the current layer + * @param x x-coordinate of the location + * @param y y-coordinate of the location + * @param layer layer-coordinate of the location + * @param sb switchblock information specified in the architecture file + * + * @return true if a switch block exists at the specified location, false otherwise. + */ +bool sb_not_here(const DeviceGrid& grid, + const std::vector& inter_cluster_rr, + int x, + int y, + int layer, + e_sb_location sb_location, + const t_specified_loc& specified_loc = t_specified_loc()); \ No newline at end of file From 5572ec7f1ac974d07ec34b5f1e9f85b7d40c3a6d Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Fri, 5 Sep 2025 15:11:47 -0400 Subject: [PATCH 03/58] use t_physical_loc instead of x, y, layer arguments --- .../build_scatter_gathers.cpp | 3 +- .../build_switchblocks.cpp | 92 +++++++-------- .../rr_graph_generation/build_switchblocks.h | 4 + ...witchblock_scatter_gather_common_utils.cpp | 106 ++++++------------ .../switchblock_scatter_gather_common_utils.h | 8 +- 5 files changed, 84 insertions(+), 129 deletions(-) diff --git a/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp b/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp index 1c8f255d16e..819967927d7 100644 --- a/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp +++ b/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp @@ -1,8 +1,9 @@ #include "build_scatter_gathers.h" -#include "globals.h" +#include "switchblock_scatter_gather_common_utils.h" #include "scatter_gather_types.h" +#include "globals.h" #include "vtr_assert.h" void alloc_and_load_scatter_gather_connections(const std::vector& scatter_gather_patterns) { diff --git a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp index a62dc7c725a..7063643945e 100644 --- a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp +++ b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp @@ -204,9 +204,7 @@ static t_wire_type_sizes count_wire_type_sizes(const t_chan_seg_details* channel /* 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, +static void compute_wire_connections(const t_physical_tile_loc& sb_loc, e_side from_side, e_side to_side, const t_chan_details& chan_details_x, @@ -279,9 +277,7 @@ static void get_switchpoint_wires(const DeviceGrid& grid, * @brief finds the correct channel (x or y), and the coordinates to index into it based on the * specified tile coordinates (x,y,layer) and the switch block side. * - * @param tile_x x-coordinate of the tile - * @param tile_y y-coordinate of the tile - * @param tile_layer layer-coordinate of the tile + * @param sb_loc Coordinates of the switch-box * @param src_side switch block source side * @param dest_side switch block destination side * @param chan_details_x x-channel segment details (length, start and end points, ...) @@ -293,9 +289,7 @@ static void get_switchpoint_wires(const DeviceGrid& grid, * * @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, +static const t_chan_details& index_into_correct_chan(const t_physical_tile_loc& sb_loc, e_side src_side, e_side dest_side, const t_chan_details& chan_details_x, @@ -371,24 +365,20 @@ t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_detail 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 - for (size_t 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.location, sb.specified_loc)) { - continue; - } + // Iterate over all locations in the grid, filling in all the switch blocks that exist + for (const t_physical_tile_loc sb_loc : grid.all_locations()) { + if (sb_not_here(grid, inter_cluster_rr, sb_loc, sb.location, sb.specified_loc)) { + continue; + } - // 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 - 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, - rng, &scratchpad); - } - } + // 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 + compute_wire_connections(sb_loc, from_side, to_side, + chan_details_x, chan_details_y, sb, grid, + wire_type_sizes_x, wire_type_sizes_y, directionality, sb_conns, + rng, &scratchpad); } } } @@ -531,9 +521,7 @@ static void get_switchpoint_wires(const DeviceGrid& grid, } } -static void compute_wire_connections(int x_coord, - int y_coord, - int layer_coord, +static void compute_wire_connections(const t_physical_tile_loc& sb_loc, e_side from_side, e_side to_side, const t_chan_details& chan_details_x, @@ -554,7 +542,7 @@ static void compute_wire_connections(int x_coord, // 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); + SwitchblockLookupKey sb_conn(sb_loc, from_side, to_side); // Can't connect a switchblock side to itself if (from_side == to_side) { @@ -571,11 +559,11 @@ static void compute_wire_connections(int x_coord, * destination channels. also return the channel type (ie chanx/chany/both) into which we are * indexing */ // 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, + const t_chan_details& from_chan_details = index_into_correct_chan(sb_loc, from_side, to_side, chan_details_x, chan_details_y, from_x, from_y, from_layer, from_chan_type); // 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, + const t_chan_details& to_chan_details = index_into_correct_chan(sb_loc, 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 @@ -795,9 +783,7 @@ static int evaluate_num_conns_formula(t_wireconn_scratchpad* scratchpad, const s 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, +static const t_chan_details& index_into_correct_chan(const t_physical_tile_loc& sb_loc, e_side src_side, e_side dest_side, const t_chan_details& chan_details_x, @@ -812,49 +798,49 @@ static const t_chan_details& index_into_correct_chan(int tile_x, switch (src_side) { case TOP: /* this is y-channel belonging to tile above in the same layer */ - chan_x = tile_x; - chan_y = tile_y + 1; - chan_layer = tile_layer; + chan_x = sb_loc.x; + chan_y = sb_loc.y + 1; + chan_layer = sb_loc.layer_num; chan_type = e_rr_type::CHANY; return chan_details_y; break; case RIGHT: /* this is x-channel belonging to tile to the right in the same layer */ - chan_x = tile_x + 1; - chan_y = tile_y; - chan_layer = tile_layer; + chan_x = sb_loc.x + 1; + chan_y = sb_loc.y; + chan_layer = sb_loc.layer_num; chan_type = e_rr_type::CHANX; return chan_details_x; break; case BOTTOM: /* this is y-channel on the right of the tile in the same layer */ - chan_x = tile_x; - chan_y = tile_y; + chan_x = sb_loc.x; + chan_y = sb_loc.y; chan_type = e_rr_type::CHANY; - chan_layer = tile_layer; + chan_layer = sb_loc.layer_num; return chan_details_y; break; case LEFT: /* this is x-channel on top of the tile in the same layer*/ - chan_x = tile_x; - chan_y = tile_y; + chan_x = sb_loc.x; + chan_y = sb_loc.y; chan_type = e_rr_type::CHANX; - chan_layer = tile_layer; + chan_layer = sb_loc.layer_num; return chan_details_x; break; case ABOVE: /* this is x-channel and y-channel on the same tile location in layer above the current layer */ - chan_x = tile_x; - chan_y = tile_y; - chan_layer = tile_layer + 1; + chan_x = sb_loc.x; + chan_y = sb_loc.y; + chan_layer = sb_loc.layer_num + 1; chan_type = (dest_side == RIGHT || dest_side == LEFT) ? e_rr_type::CHANX : e_rr_type::CHANY; return (dest_side == RIGHT || dest_side == LEFT) ? chan_details_x : chan_details_y; break; case UNDER: /* this is x-channel and y-channel on the same tile location in layer under the current layer */ - chan_x = tile_x; - chan_y = tile_y; - chan_layer = tile_layer - 1; + chan_x = sb_loc.x; + chan_y = sb_loc.y; + chan_layer = sb_loc.layer_num - 1; chan_type = (dest_side == RIGHT || dest_side == LEFT) ? e_rr_type::CHANX : e_rr_type::CHANY; return (dest_side == RIGHT || dest_side == LEFT) ? chan_details_x : chan_details_y; break; diff --git a/vpr/src/route/rr_graph_generation/build_switchblocks.h b/vpr/src/route/rr_graph_generation/build_switchblocks.h index 589ea0e5ce2..08fd2fc7b76 100644 --- a/vpr/src/route/rr_graph_generation/build_switchblocks.h +++ b/vpr/src/route/rr_graph_generation/build_switchblocks.h @@ -34,6 +34,10 @@ class SwitchblockLookupKey { this->set_coords(set_x, set_y, set_layer, set_from, set_to); } + SwitchblockLookupKey(const t_physical_tile_loc& set_loc, e_side set_from, e_side set_to) { + this->set_coords(set_loc.x, set_loc.y, set_loc.layer_num, set_from, 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); diff --git a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp index 0f4a61b16a0..b0dfb7704cb 100644 --- a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp +++ b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp @@ -5,115 +5,85 @@ /** * @brief Check whether specified coordinate is located at the device grid corner and a switch block exists there - * - * @param grid device grid - * @param inter_cluster_rr used to check whether inter-cluster programmable routing resources exist in the current layer - * @param x x-coordinate of the location - * @param y y-coordinate of the location - * @param layer layer-coordinate of the location - * * @return true if the specified coordinate represents a corner location within the device grid and a switch block exists there, false otherwise. */ -static bool is_corner_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer); +static bool is_corner_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, const t_physical_tile_loc& loc); /** - * @brief check whether specified coordinate is located at one of the perimeter device grid locations and a switch block exists there - * - * @param grid device grid - * @param inter_cluster_rr used to check whether inter-cluster programmable routing resources exist in the current layer - * @param x x-coordinate of the location - * @param y y-coordinate of the location - * @param layer layer-coordinate of the location - * + * @brief check whether specified coordinate is located at one of the perimeter device grid locations and a switch block exists there * * @return true if the specified coordinate represents a perimeter location within the device grid and a switch block exists there, false otherwise. */ -static bool is_perimeter_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer); +static bool is_perimeter_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, const t_physical_tile_loc& loc); /** * @brief check whether specified coordinate is located at core of the device grid (not perimeter) and a switch block exists there - * - * @param grid device grid - * @param inter_cluster_rr used to check whether inter-cluster programmable routing resources exist in the current layer - * @param x x-coordinate of the location - * @param y y-coordinate of the location - * @param layer layer-coordinate of the location - * * @return true if the specified coordinate represents a core location within the device grid and a switch block exists there, false otherwise. */ -static bool is_core_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer); +static bool is_core_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, const t_physical_tile_loc& loc); /** * @brief check whether specified coordinate is located in the architecture-specified regions that the switchblock should be applied to - * - * @param grid device grid - * @param inter_cluster_rr used to check whether inter-cluster programmable routing resources exist in the current layer - * @param x x-coordinate of the location - * @param y y-coordinate of the location - * @param sb switchblock information specified in the architecture file - * * @return true if the specified coordinate falls into the architecture-specified location for this switchblock, false otherwise. */ -static bool match_sb_xy(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer, const t_specified_loc& sb); +static bool match_sb_xy(const DeviceGrid& grid, const std::vector& inter_cluster_rr, const t_physical_tile_loc& loc, const t_specified_loc& sb); -static bool is_corner_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer) { - if (!inter_cluster_rr[layer]) { +static bool is_corner_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, const t_physical_tile_loc& loc) { + if (!inter_cluster_rr[loc.layer_num]) { return false; } bool is_corner = false; - if ((x == 0 && y == 0) || (x == 0 && y == int(grid.height()) - 2) || //-2 for no perim channels - (x == int(grid.width()) - 2 && y == 0) || //-2 for no perim channels - (x == int(grid.width()) - 2 && y == int(grid.height()) - 2)) { //-2 for no perim channels + if ((loc.x == 0 && loc.y == 0) || (loc.x == 0 && loc.y == int(grid.height()) - 2) || //-2 for no perim channels + (loc.x == int(grid.width()) - 2 && loc.y == 0) || //-2 for no perim channels + (loc.x == int(grid.width()) - 2 && loc.y == int(grid.height()) - 2)) { //-2 for no perim channels is_corner = true; } return is_corner; } -static bool is_perimeter_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer) { - if (!inter_cluster_rr[layer]) { +static bool is_perimeter_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, const t_physical_tile_loc& loc) { + if (!inter_cluster_rr[loc.layer_num]) { return false; } bool is_perimeter = false; - if (x == 0 || x == int(grid.width()) - 2 || y == 0 || y == int(grid.height()) - 2) { + if (loc.x == 0 || loc.x == int(grid.width()) - 2 || loc.y == 0 || loc.y == int(grid.height()) - 2) { is_perimeter = true; } return is_perimeter; } -static bool is_core_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer) { - if (!inter_cluster_rr[layer]) { +static bool is_core_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, const t_physical_tile_loc& loc) { + if (!inter_cluster_rr[loc.layer_num]) { return false; } - bool is_core = !is_perimeter_sb(grid, inter_cluster_rr, x, y, layer); + bool is_core = !is_perimeter_sb(grid, inter_cluster_rr, loc); return is_core; } static bool match_sb_xy(const DeviceGrid& grid, const std::vector& inter_cluster_rr, - int x, - int y, - int layer, + const t_physical_tile_loc& loc, const t_specified_loc& specified_loc) { - if (!inter_cluster_rr[layer]) { + if (!inter_cluster_rr[loc.layer_num]) { return false; } // if one of sb_x and sb_y is defined, we either know the exact location (x,y) or the exact x location (will apply it to all rows) // or the exact y location (will apply it to all columns) if (specified_loc.x != -1 || specified_loc.y != -1) { - if (x == specified_loc.x && y == specified_loc.y) { + if (loc.x == specified_loc.x && loc.y == specified_loc.y) { return true; } - if (x == specified_loc.x && specified_loc.y == -1) { + if (loc.x == specified_loc.x && specified_loc.y == -1) { return true; } - if (specified_loc.x == -1 && y == specified_loc.y) { + if (specified_loc.x == -1 && loc.y == specified_loc.y) { return true; } } @@ -130,30 +100,30 @@ static bool match_sb_xy(const DeviceGrid& grid, // calculated region are valid. // calculate the region - int x_reg_step = (sb.reg_x.repeat != 0) ? (x - sb.reg_x.start) / sb.reg_x.repeat : sb.reg_x.start; - int y_reg_step = (sb.reg_y.repeat != 0) ? (y - sb.reg_y.start) / sb.reg_y.repeat : sb.reg_y.start; + int x_reg_step = (specified_loc.reg_x.repeat != 0) ? (loc.x - specified_loc.reg_x.start) / specified_loc.reg_x.repeat : specified_loc.reg_x.start; + int y_reg_step = (specified_loc.reg_y.repeat != 0) ? (loc.y - specified_loc.reg_y.start) / specified_loc.reg_y.repeat : specified_loc.reg_y.start; // step must be non-negative x_reg_step = std::max(0, x_reg_step); y_reg_step = std::max(0, y_reg_step); - int reg_startx = sb.reg_x.start + (x_reg_step * sb.reg_x.repeat); - int reg_endx = sb.reg_x.end + (x_reg_step * sb.reg_x.repeat); + int reg_startx = specified_loc.reg_x.start + (x_reg_step * specified_loc.reg_x.repeat); + int reg_endx = specified_loc.reg_x.end + (x_reg_step * specified_loc.reg_x.repeat); reg_endx = std::min(reg_endx, int(grid.width() - 1)); - int reg_starty = sb.reg_y.start + (y_reg_step * sb.reg_y.repeat); - int reg_endy = sb.reg_y.end + (y_reg_step * sb.reg_y.repeat); + int reg_starty = specified_loc.reg_y.start + (y_reg_step * specified_loc.reg_y.repeat); + int reg_endy = specified_loc.reg_y.end + (y_reg_step * specified_loc.reg_y.repeat); reg_endy = std::min(reg_endy, int(grid.height() - 1)); // check x coordinate - if (x >= reg_startx && x <= reg_endx) { //should fall into the region + if (loc.x >= reg_startx && loc.x <= reg_endx) { //should fall into the region // we also should respect the incrx // if incrx is not equal to 1, all locations within this region are *NOT* valid - if ((x + reg_startx) % sb.reg_x.incr == 0) { + if ((loc.x + reg_startx) % specified_loc.reg_x.incr == 0) { // valid x coordinate, check for y value - if (y >= reg_starty && y <= reg_endy) { + if (loc.y >= reg_starty && loc.y <= reg_endy) { // check for incry, similar as incrx - if ((y + reg_starty) % sb.reg_y.incr == 0) { + if ((loc.y + reg_starty) % specified_loc.reg_y.incr == 0) { // both x and y are valid return true; } @@ -168,9 +138,7 @@ static bool match_sb_xy(const DeviceGrid& grid, bool sb_not_here(const DeviceGrid& grid, const std::vector& inter_cluster_rr, - int x, - int y, - int layer, + const t_physical_tile_loc& loc, e_sb_location sb_location, const t_specified_loc& specified_loc/*=t_specified_loc()*/) { bool sb_not_here = true; @@ -181,31 +149,31 @@ bool sb_not_here(const DeviceGrid& grid, break; case e_sb_location::E_PERIMETER: - if (is_perimeter_sb(grid, inter_cluster_rr, x, y, layer)) { + if (is_perimeter_sb(grid, inter_cluster_rr, loc)) { sb_not_here = false; } break; case e_sb_location::E_CORNER: - if (is_corner_sb(grid, inter_cluster_rr, x, y, layer)) { + if (is_corner_sb(grid, inter_cluster_rr, loc)) { sb_not_here = false; } break; case e_sb_location::E_CORE: - if (is_core_sb(grid, inter_cluster_rr, x, y, layer)) { + if (is_core_sb(grid, inter_cluster_rr, loc)) { sb_not_here = false; } break; case e_sb_location::E_FRINGE: - if (is_perimeter_sb(grid, inter_cluster_rr, x, y, layer) && !is_corner_sb(grid, inter_cluster_rr, x, y, layer)) { + if (is_perimeter_sb(grid, inter_cluster_rr, loc) && !is_corner_sb(grid, inter_cluster_rr, loc)) { sb_not_here = false; } break; case e_sb_location::E_XY_SPECIFIED: - if (match_sb_xy(grid, inter_cluster_rr, x, y, layer, specified_loc)) { + if (match_sb_xy(grid, inter_cluster_rr, loc, specified_loc)) { sb_not_here = false; } break; diff --git a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h index d0752578db0..80be1a580a0 100644 --- a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h +++ b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h @@ -10,17 +10,13 @@ * * @param grid device grid * @param inter_cluster_rr used to check whether inter-cluster programmable routing resources exist in the current layer - * @param x x-coordinate of the location - * @param y y-coordinate of the location - * @param layer layer-coordinate of the location + * @param loc Coordinates of the given location to be evaluated. * @param sb switchblock information specified in the architecture file * * @return true if a switch block exists at the specified location, false otherwise. */ bool sb_not_here(const DeviceGrid& grid, const std::vector& inter_cluster_rr, - int x, - int y, - int layer, + const t_physical_tile_loc& loc, e_sb_location sb_location, const t_specified_loc& specified_loc = t_specified_loc()); \ No newline at end of file From 557769c056ec1cdd2ac7342e53ade82f75be7987 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Fri, 5 Sep 2025 15:17:38 -0400 Subject: [PATCH 04/58] check inter_cluster_rr in sb_not_here() instead of inside every single function that it calls --- ...witchblock_scatter_gather_common_utils.cpp | 49 +++++++------------ 1 file changed, 17 insertions(+), 32 deletions(-) diff --git a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp index b0dfb7704cb..c7649518d46 100644 --- a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp +++ b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp @@ -7,33 +7,28 @@ * @brief Check whether specified coordinate is located at the device grid corner and a switch block exists there * @return true if the specified coordinate represents a corner location within the device grid and a switch block exists there, false otherwise. */ -static bool is_corner_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, const t_physical_tile_loc& loc); +static bool is_corner_sb(const DeviceGrid& grid, const t_physical_tile_loc& loc); /** * @brief check whether specified coordinate is located at one of the perimeter device grid locations and a switch block exists there * * @return true if the specified coordinate represents a perimeter location within the device grid and a switch block exists there, false otherwise. */ -static bool is_perimeter_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, const t_physical_tile_loc& loc); +static bool is_perimeter_sb(const DeviceGrid& grid, const t_physical_tile_loc& loc); /** * @brief check whether specified coordinate is located at core of the device grid (not perimeter) and a switch block exists there * @return true if the specified coordinate represents a core location within the device grid and a switch block exists there, false otherwise. */ -static bool is_core_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, const t_physical_tile_loc& loc); - +static bool is_core_sb(const DeviceGrid& grid, const t_physical_tile_loc& loc); /** * @brief check whether specified coordinate is located in the architecture-specified regions that the switchblock should be applied to * @return true if the specified coordinate falls into the architecture-specified location for this switchblock, false otherwise. */ -static bool match_sb_xy(const DeviceGrid& grid, const std::vector& inter_cluster_rr, const t_physical_tile_loc& loc, const t_specified_loc& sb); +static bool match_sb_xy(const DeviceGrid& grid, const t_physical_tile_loc& loc, const t_specified_loc& sb); -static bool is_corner_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, const t_physical_tile_loc& loc) { - if (!inter_cluster_rr[loc.layer_num]) { - return false; - } - +static bool is_corner_sb(const DeviceGrid& grid, const t_physical_tile_loc& loc) { bool is_corner = false; if ((loc.x == 0 && loc.y == 0) || (loc.x == 0 && loc.y == int(grid.height()) - 2) || //-2 for no perim channels (loc.x == int(grid.width()) - 2 && loc.y == 0) || //-2 for no perim channels @@ -43,11 +38,7 @@ static bool is_corner_sb(const DeviceGrid& grid, const std::vector& inter_ return is_corner; } -static bool is_perimeter_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, const t_physical_tile_loc& loc) { - if (!inter_cluster_rr[loc.layer_num]) { - return false; - } - +static bool is_perimeter_sb(const DeviceGrid& grid, const t_physical_tile_loc& loc) { bool is_perimeter = false; if (loc.x == 0 || loc.x == int(grid.width()) - 2 || loc.y == 0 || loc.y == int(grid.height()) - 2) { is_perimeter = true; @@ -55,23 +46,14 @@ static bool is_perimeter_sb(const DeviceGrid& grid, const std::vector& int return is_perimeter; } -static bool is_core_sb(const DeviceGrid& grid, const std::vector& inter_cluster_rr, const t_physical_tile_loc& loc) { - if (!inter_cluster_rr[loc.layer_num]) { - return false; - } - - bool is_core = !is_perimeter_sb(grid, inter_cluster_rr, loc); +static bool is_core_sb(const DeviceGrid& grid, const t_physical_tile_loc& loc) { + bool is_core = !is_perimeter_sb(grid, loc); return is_core; } static bool match_sb_xy(const DeviceGrid& grid, - const std::vector& inter_cluster_rr, const t_physical_tile_loc& loc, const t_specified_loc& specified_loc) { - if (!inter_cluster_rr[loc.layer_num]) { - return false; - } - // if one of sb_x and sb_y is defined, we either know the exact location (x,y) or the exact x location (will apply it to all rows) // or the exact y location (will apply it to all columns) if (specified_loc.x != -1 || specified_loc.y != -1) { @@ -141,39 +123,42 @@ bool sb_not_here(const DeviceGrid& grid, const t_physical_tile_loc& loc, e_sb_location sb_location, const t_specified_loc& specified_loc/*=t_specified_loc()*/) { - bool sb_not_here = true; + if (!inter_cluster_rr[loc.layer_num]) { + return true; + } + bool sb_not_here = true; switch (sb_location) { case e_sb_location::E_EVERYWHERE: sb_not_here = false; break; case e_sb_location::E_PERIMETER: - if (is_perimeter_sb(grid, inter_cluster_rr, loc)) { + if (is_perimeter_sb(grid, loc)) { sb_not_here = false; } break; case e_sb_location::E_CORNER: - if (is_corner_sb(grid, inter_cluster_rr, loc)) { + if (is_corner_sb(grid, loc)) { sb_not_here = false; } break; case e_sb_location::E_CORE: - if (is_core_sb(grid, inter_cluster_rr, loc)) { + if (is_core_sb(grid, loc)) { sb_not_here = false; } break; case e_sb_location::E_FRINGE: - if (is_perimeter_sb(grid, inter_cluster_rr, loc) && !is_corner_sb(grid, inter_cluster_rr, loc)) { + if (is_perimeter_sb(grid, loc) && !is_corner_sb(grid, loc)) { sb_not_here = false; } break; case e_sb_location::E_XY_SPECIFIED: - if (match_sb_xy(grid, inter_cluster_rr, loc, specified_loc)) { + if (match_sb_xy(grid, loc, specified_loc)) { sb_not_here = false; } break; From 70bea1c5ac2695f4646960b939f27a6ace5f5094 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Fri, 5 Sep 2025 16:37:34 -0400 Subject: [PATCH 05/58] rename SwitchPointOrder to e_switch_point_order --- libs/libarchfpga/src/parse_switchblocks.cpp | 10 +++++----- libs/libarchfpga/src/switchblock_types.h | 6 +++--- .../rr_graph_generation/build_scatter_gathers.cpp | 9 +++++++-- .../route/rr_graph_generation/build_scatter_gathers.h | 3 ++- .../route/rr_graph_generation/build_switchblocks.cpp | 8 ++++---- 5 files changed, 21 insertions(+), 15 deletions(-) diff --git a/libs/libarchfpga/src/parse_switchblocks.cpp b/libs/libarchfpga/src/parse_switchblocks.cpp index 747cd4687c7..b1006ceb02b 100644 --- a/libs/libarchfpga/src/parse_switchblocks.cpp +++ b/libs/libarchfpga/src/parse_switchblocks.cpp @@ -35,7 +35,7 @@ using vtr::t_formula_data; /*---- Functions for Parsing Switchblocks from Architecture ----*/ //Process the desired order of a wireconn -static void parse_switchpoint_order(const char* order, SwitchPointOrder& switchpoint_order); +static void parse_switchpoint_order(const char* order, e_switch_point_order& switchpoint_order); /** * @brief Parses an inline `` node using its attributes. @@ -282,13 +282,13 @@ static t_wire_switchpoints parse_wireconn_from_to_node(pugi::xml_node node, cons return wire_switchpoints; } -static void parse_switchpoint_order(const char* order, SwitchPointOrder& switchpoint_order) { +static void parse_switchpoint_order(const char* order, e_switch_point_order& switchpoint_order) { if (order == std::string("")) { - switchpoint_order = SwitchPointOrder::SHUFFLED; //Default + switchpoint_order = e_switch_point_order::SHUFFLED; //Default } else if (order == std::string("fixed")) { - switchpoint_order = SwitchPointOrder::FIXED; + switchpoint_order = e_switch_point_order::FIXED; } else if (order == std::string("shuffled")) { - switchpoint_order = SwitchPointOrder::SHUFFLED; + switchpoint_order = e_switch_point_order::SHUFFLED; } else { archfpga_throw(__FILE__, __LINE__, "Unrecognized switchpoint order '%s'", order); } diff --git a/libs/libarchfpga/src/switchblock_types.h b/libs/libarchfpga/src/switchblock_types.h index 735d5838c38..cda89219f20 100644 --- a/libs/libarchfpga/src/switchblock_types.h +++ b/libs/libarchfpga/src/switchblock_types.h @@ -121,7 +121,7 @@ class SBSideConnection { } }; -enum class SwitchPointOrder { +enum class e_switch_point_order { FIXED, ///< Switchpoints are ordered as specified in architecture SHUFFLED ///< Switchpoints are shuffled (more diversity) }; @@ -142,8 +142,8 @@ struct t_wire_switchpoints { 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 + e_switch_point_order from_switchpoint_order = e_switch_point_order::FIXED; ///< The desired from_switchpoint_set ordering + e_switch_point_order to_switchpoint_order = e_switch_point_order::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) diff --git a/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp b/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp index 819967927d7..d40b2ec1b8e 100644 --- a/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp +++ b/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp @@ -6,7 +6,8 @@ #include "globals.h" #include "vtr_assert.h" -void alloc_and_load_scatter_gather_connections(const std::vector& scatter_gather_patterns) { +void alloc_and_load_scatter_gather_connections(const std::vector& scatter_gather_patterns, + const std::vector& inter_cluster_rr) { const DeviceGrid& grid = g_vpr_ctx.device().grid; @@ -15,7 +16,11 @@ void alloc_and_load_scatter_gather_connections(const std::vector -void alloc_and_load_scatter_gather_connections(const std::vector& scatter_gather_patterns); \ No newline at end of file +void alloc_and_load_scatter_gather_connections(const std::vector& scatter_gather_patterns, + const std::vector& inter_cluster_rr); \ No newline at end of file diff --git a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp index 7063643945e..f39bf5d31c2 100644 --- a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp +++ b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp @@ -268,7 +268,7 @@ static void get_switchpoint_wires(const DeviceGrid& grid, const std::vector& wire_switchpoints_vec, const t_wire_type_sizes& wire_type_sizes, bool is_dest, - SwitchPointOrder switchpoint_order, + e_switch_point_order switchpoint_order, vtr::RngContainer& rng, std::vector* output_wires, std::vector* scratch_wires); @@ -440,7 +440,7 @@ static void get_switchpoint_wires(const DeviceGrid& grid, const std::vector& wire_switchpoints_vec, const t_wire_type_sizes& wire_type_sizes, bool is_dest, - SwitchPointOrder switchpoint_order, + e_switch_point_order switchpoint_order, vtr::RngContainer& rng, std::vector* output_wires, std::vector* scratch_wires) { @@ -512,11 +512,11 @@ static void get_switchpoint_wires(const DeviceGrid& grid, collected_wire_switchpoints.begin(), collected_wire_switchpoints.end()); } - if (switchpoint_order == SwitchPointOrder::SHUFFLED) { + if (switchpoint_order == e_switch_point_order::SHUFFLED) { // 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); + VTR_ASSERT(switchpoint_order == e_switch_point_order::FIXED); // Already ordered so same switchpoints are adjacent by above collection loop } } From cc44a8effb988647fea6c8db594e6de69c6d2939 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Sat, 6 Sep 2025 10:02:37 -0400 Subject: [PATCH 06/58] find scatter/gather src/dst channels --- .../build_scatter_gathers.cpp | 60 ++++++++++++-- .../build_scatter_gathers.h | 5 +- ...witchblock_scatter_gather_common_utils.cpp | 82 +++++++++++++++++++ .../switchblock_scatter_gather_common_utils.h | 12 ++- 4 files changed, 151 insertions(+), 8 deletions(-) diff --git a/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp b/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp index d40b2ec1b8e..82a8413a756 100644 --- a/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp +++ b/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp @@ -6,19 +6,67 @@ #include "globals.h" #include "vtr_assert.h" +#include + +static void index_to_correct_channels(const t_wireconn_inf& pattern, + const t_physical_tile_loc& loc, + const t_chan_details& chan_details_x, + const t_chan_details& chan_details_y, + std::vector>& correct_channels) { + correct_channels.clear(); + + for (e_side side : pattern.sides) { + t_physical_tile_loc chan_loc; + e_rr_type chan_type; + + index_into_correct_chan(loc, side, chan_details_x, chan_details_y,chan_loc, chan_type); + + if (!chan_coords_out_of_bounds(chan_loc, chan_type)) { + correct_channels.push_back({chan_loc, chan_type}); + } + } +} + void alloc_and_load_scatter_gather_connections(const std::vector& scatter_gather_patterns, - const std::vector& inter_cluster_rr) { + const std::vector& inter_cluster_rr, + const t_chan_details& chan_details_x, + const t_chan_details& chan_details_y) { const DeviceGrid& grid = g_vpr_ctx.device().grid; + std::vector> gather_channels; + std::vector> scatter_channels; for (const t_scatter_gather_pattern& sg_pattern : scatter_gather_patterns) { VTR_ASSERT(sg_pattern.type == e_scatter_gather_type::UNIDIR); - VTR_ASSERT(sg_pattern.sg_locations.size() == 1); - VTR_ASSERT(sg_pattern.sg_locations[0].type == e_sb_location::E_EVERYWHERE); - for (const t_physical_tile_loc loc : grid.all_locations()) { - if (sb_not_here(grid, inter_cluster_rr, loc, sg_pattern.sg_locations[0].type)) { - continue; + for (const t_sg_location& sg_loc_info : sg_pattern.sg_locations) { + + for (const t_physical_tile_loc gather_loc : grid.all_locations()) { + if (sb_not_here(grid, inter_cluster_rr, gather_loc, sg_loc_info.type)) { + continue; + } + + auto it = std::find_if(sg_pattern.sg_links.begin(), sg_pattern.sg_links.end(), + [&](const t_sg_link& link) { + return link.name == sg_loc_info.sg_link_name; + }); + + VTR_ASSERT_SAFE(it != sg_pattern.sg_links.end()); + const t_sg_link& sg_link = *it; + + t_physical_tile_loc scatter_loc; + scatter_loc.x = gather_loc.x + sg_link.x_offset; + scatter_loc.y = gather_loc.y + sg_link.y_offset; + scatter_loc.layer_num = gather_loc.layer_num + sg_link.z_offset; + + + index_to_correct_channels(sg_pattern.gather_pattern, gather_loc, chan_details_x, chan_details_y, gather_channels); + index_to_correct_channels(sg_pattern.scatter_pattern, scatter_loc, chan_details_x, chan_details_y, scatter_channels); + + if (gather_channels.empty() || scatter_channels.empty()) { + continue; + } + } } diff --git a/vpr/src/route/rr_graph_generation/build_scatter_gathers.h b/vpr/src/route/rr_graph_generation/build_scatter_gathers.h index 7177fce273e..b5a89a7b01e 100644 --- a/vpr/src/route/rr_graph_generation/build_scatter_gathers.h +++ b/vpr/src/route/rr_graph_generation/build_scatter_gathers.h @@ -1,8 +1,11 @@ #pragma once #include "scatter_gather_types.h" +#include "rr_types.h" #include void alloc_and_load_scatter_gather_connections(const std::vector& scatter_gather_patterns, - const std::vector& inter_cluster_rr); \ No newline at end of file + const std::vector& inter_cluster_rr, + const t_chan_details& chan_details_x, + const t_chan_details& chan_details_y); \ No newline at end of file diff --git a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp index c7649518d46..956b309b472 100644 --- a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp +++ b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp @@ -1,7 +1,11 @@ #include "switchblock_scatter_gather_common_utils.h" +#include "globals.h" #include "vpr_error.h" +#include "rr_node_types.h" +#include "rr_types.h" + /** * @brief Check whether specified coordinate is located at the device grid corner and a switch block exists there @@ -169,4 +173,82 @@ bool sb_not_here(const DeviceGrid& grid, } return sb_not_here; +} + +const t_chan_details& index_into_correct_chan(const t_physical_tile_loc& sb_loc, + e_side src_side, + const t_chan_details& chan_details_x, + const t_chan_details& chan_details_y, + t_physical_tile_loc& chan_loc, + 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 + switch (src_side) { + case TOP: + // this is y-channel belonging to tile above in the same layer + chan_loc.x = sb_loc.x; + chan_loc.y = sb_loc.y + 1; + chan_loc.layer_num = sb_loc.layer_num; + chan_type = e_rr_type::CHANY; + return chan_details_y; + break; + case RIGHT: + // this is x-channel belonging to tile to the right in the same layer + chan_loc.x = sb_loc.x + 1; + chan_loc.y = sb_loc.y; + chan_loc.layer_num = sb_loc.layer_num; + chan_type = e_rr_type::CHANX; + return chan_details_x; + break; + case BOTTOM: + // this is y-channel on the right of the tile in the same layer + chan_loc.x = sb_loc.x; + chan_loc.y = sb_loc.y; + chan_loc.layer_num = sb_loc.layer_num; + chan_type = e_rr_type::CHANY; + return chan_details_y; + break; + case LEFT: + // this is x-channel on top of the tile in the same layer + chan_loc.x = sb_loc.x; + chan_loc.y = sb_loc.y; + chan_loc.layer_num = sb_loc.layer_num; + chan_type = e_rr_type::CHANX; + return chan_details_x; + break; + default: + VPR_FATAL_ERROR(VPR_ERROR_ARCH, "index_into_correct_chan: unknown side specified: %d\n", src_side); + break; + } + VTR_ASSERT(false); + return chan_details_x; // Unreachable +} + +bool chan_coords_out_of_bounds(const t_physical_tile_loc& loc, e_rr_type chan_type) { + const DeviceGrid& grid = g_vpr_ctx.device().grid; + + const int grid_width = grid.width(); + const int grid_height = grid.height(); + const int grid_layers = grid.get_num_layers(); + + // the layer that channel is located at must be legal regardless of chan_type + if (loc.layer_num < 0 || loc.layer_num > grid_layers) { + return true; + } + + if (e_rr_type::CHANX == chan_type) { + // there is no x-channel at x=0 + if (loc.x <= 0 || loc.x >= grid_width - 1 || loc.y < 0 || loc.y >= grid_height - 1) { + return true; + } + } else if (e_rr_type::CHANY == chan_type) { + // there is no y-channel at y=0 + if (loc.x < 0 || loc.x >= grid_width - 1 || loc.y <= 0 || loc.y >= grid_height - 1) { + return true; + } + } else { + VPR_FATAL_ERROR(VPR_ERROR_ARCH, "chan_coords_out_of_bounds(): illegal channel type %d\n", chan_type); + } + + return false; } \ No newline at end of file diff --git a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h index 80be1a580a0..edbd82b5dcc 100644 --- a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h +++ b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h @@ -2,6 +2,7 @@ #pragma once #include "device_grid.h" +#include "rr_types.h" #include @@ -19,4 +20,13 @@ bool sb_not_here(const DeviceGrid& grid, const std::vector& inter_cluster_rr, const t_physical_tile_loc& loc, e_sb_location sb_location, - const t_specified_loc& specified_loc = t_specified_loc()); \ No newline at end of file + const t_specified_loc& specified_loc = t_specified_loc()); + +const t_chan_details& index_into_correct_chan(const t_physical_tile_loc& sb_loc, + e_side src_side, + const t_chan_details& chan_details_x, + const t_chan_details& chan_details_y, + t_physical_tile_loc& chan_loc, + e_rr_type& chan_type); + +bool chan_coords_out_of_bounds(const t_physical_tile_loc& loc, e_rr_type chan_type); \ No newline at end of file From 7b5475c52910cb4a9674597648bd57f282af2e3b Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Sun, 7 Sep 2025 15:12:24 -0400 Subject: [PATCH 07/58] remove redundant call to count_wire_type_sizes --- vpr/src/route/rr_graph_generation/build_switchblocks.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp index f39bf5d31c2..305ba9b283c 100644 --- a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp +++ b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp @@ -354,7 +354,6 @@ t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_detail */ 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 @@ -618,7 +617,7 @@ static void compute_wireconn_connections(const DeviceGrid& grid, // 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 */ + // 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.from_switchpoint_set, wire_type_sizes_from, /*is_dest=*/false, wireconn.from_switchpoint_order, rng, &scratchpad->potential_src_wires, From 57c3348a5afe6e63ab4f4fd9e4a30abba4cfc013 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Sun, 7 Sep 2025 15:14:29 -0400 Subject: [PATCH 08/58] rename WireInfo to t_wire_info --- .../route/rr_graph_generation/build_switchblocks.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp index 305ba9b283c..5ca6238a2f3 100644 --- a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp +++ b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp @@ -145,10 +145,8 @@ using vtr::FormulaParser; using vtr::t_formula_data; -/************ Classes ************/ /** Contains info about a wire segment type */ -class WireInfo { - public: +struct t_wire_info { 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) @@ -159,11 +157,11 @@ class WireInfo { start = st; } - WireInfo() { + t_wire_info() { this->set(0, 0, 0); } - WireInfo(int len, int wires, int st) { + t_wire_info(int len, int wires, int st) { this->set(len, wires, st); } }; @@ -183,7 +181,7 @@ 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 ************/ /** @@ -401,7 +399,7 @@ void free_switchblock_permutations(t_sb_connection_map* sb_conns) { static t_wire_type_sizes count_wire_type_sizes(const t_chan_seg_details* channel, int nodes_per_chan) { int num_wires = 0; - WireInfo wire_info; + t_wire_info wire_info; vtr::string_view wire_type = channel[0].type_name(); int length = channel[0].length(); From 642427be48a9780afe512868d13636ad12aadeb4 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Sun, 7 Sep 2025 15:34:46 -0400 Subject: [PATCH 09/58] move count_wire_type_sizes() to utils --- .../build_switchblocks.cpp | 82 +------------------ ...witchblock_scatter_gather_common_utils.cpp | 64 +++++++++++++++ .../switchblock_scatter_gather_common_utils.h | 31 ++++++- 3 files changed, 95 insertions(+), 82 deletions(-) diff --git a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp index 5ca6238a2f3..75ddf19bc35 100644 --- a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp +++ b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp @@ -145,27 +145,6 @@ using vtr::FormulaParser; using vtr::t_formula_data; -/** Contains info about a wire segment type */ -struct t_wire_info { - 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; - } - - t_wire_info() { - this->set(0, 0, 0); - } - - t_wire_info(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 @@ -179,26 +158,8 @@ struct t_wireconn_scratchpad { std::vector scratch_wires; }; -/************ Typedefs ************/ -/* Used to get info about a given wire type based on the name */ -typedef vtr::flat_map t_wire_type_sizes; /************ Function Declarations ************/ -/** - * @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 */ @@ -341,17 +302,7 @@ t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_detail 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 */ - - /* 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. - * This will not hold if we - * 1) support different horizontal and vertical segment distributions - * 2) support non-uniform channel distributions. - */ - 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); + const auto [wire_type_sizes_x, wire_type_sizes_y] = count_wire_type_sizes(chan_details_x, chan_details_y, nodes_per_chan); /******** slow switch block computation method; computes switchblocks at each coordinate ********/ // Iterate over all the switchblocks specified in the architecture @@ -397,37 +348,6 @@ void free_switchblock_permutations(t_sb_connection_map* sb_conns) { vtr::malloc_trim(0); } -static t_wire_type_sizes count_wire_type_sizes(const t_chan_seg_details* channel, int nodes_per_chan) { - int num_wires = 0; - t_wire_info 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; - - for (int iwire = 0; iwire < nodes_per_chan; 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 = new_type; - length = new_length; - start = new_start; - num_wires = 0; - } - num_wires++; - } - - wire_info.set(length, num_wires, start); - wire_type_sizes[wire_type] = wire_info; - - return wire_type_sizes; -} - static void get_switchpoint_wires(const DeviceGrid& grid, const t_chan_seg_details* chan_details, e_rr_type chan_type, diff --git a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp index 956b309b472..fa907aef337 100644 --- a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp +++ b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp @@ -6,6 +6,21 @@ #include "rr_node_types.h" #include "rr_types.h" +/** + * @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_chan_wire_type_sizes(const t_chan_seg_details* channel, int nodes_per_chan); /** * @brief Check whether specified coordinate is located at the device grid corner and a switch block exists there @@ -121,6 +136,36 @@ static bool match_sb_xy(const DeviceGrid& grid, return false; } +static t_wire_type_sizes count_chan_wire_type_sizes(const t_chan_seg_details* channel, int nodes_per_chan) { + int num_wires = 0; + t_wire_info 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; + + for (int iwire = 0; iwire < nodes_per_chan; 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 = new_type; + length = new_length; + start = new_start; + num_wires = 0; + } + num_wires++; + } + + wire_info.set(length, num_wires, start); + wire_type_sizes[wire_type] = wire_info; + + return wire_type_sizes; +} bool sb_not_here(const DeviceGrid& grid, const std::vector& inter_cluster_rr, @@ -251,4 +296,23 @@ bool chan_coords_out_of_bounds(const t_physical_tile_loc& loc, e_rr_type chan_ty } return false; +} + +std::pair count_wire_type_sizes(const t_chan_details& chan_details_x, + const t_chan_details& chan_details_y, + const t_chan_width& nodes_per_chan) { + + // 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. + + // 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. + // This will not hold if we + // 1) support different horizontal and vertical segment distributions + // 2) support non-uniform channel distributions. + + t_wire_type_sizes wire_type_sizes_x = count_chan_wire_type_sizes(chan_details_x[0][0].data(), nodes_per_chan.x_max); + t_wire_type_sizes wire_type_sizes_y = count_chan_wire_type_sizes(chan_details_y[0][0].data(), nodes_per_chan.y_max); + + return {wire_type_sizes_x, wire_type_sizes_y}; } \ No newline at end of file diff --git a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h index edbd82b5dcc..87dcc3a199f 100644 --- a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h +++ b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h @@ -3,9 +3,34 @@ #include "device_grid.h" #include "rr_types.h" +#include "rr_graph_type.h" #include +/** Contains info about a wire segment type */ +struct t_wire_info { + 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; + } + + t_wire_info() { + this->set(0, 0, 0); + } + + t_wire_info(int len, int wires, int st) { + this->set(len, wires, st); + } +}; + +/// Used to get info about a given wire type based on the name +typedef vtr::flat_map t_wire_type_sizes; + /** * @brief check whether a switch block exists in a specified coordinate within the device grid * @@ -29,4 +54,8 @@ const t_chan_details& index_into_correct_chan(const t_physical_tile_loc& sb_loc, t_physical_tile_loc& chan_loc, e_rr_type& chan_type); -bool chan_coords_out_of_bounds(const t_physical_tile_loc& loc, e_rr_type chan_type); \ No newline at end of file +bool chan_coords_out_of_bounds(const t_physical_tile_loc& loc, e_rr_type chan_type); + +std::pair count_wire_type_sizes(const t_chan_details& chan_details_x, + const t_chan_details& chan_details_y, + const t_chan_width& nodes_per_chan); \ No newline at end of file From 1904fe8e1be4e667bb3e900f9c856a1c5db8f374 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Sun, 7 Sep 2025 16:19:22 -0400 Subject: [PATCH 10/58] move some common functions used by both switch-box and scatter-gather code to utils --- .../build_switchblocks.cpp | 175 ++---------------- ...witchblock_scatter_gather_common_utils.cpp | 129 +++++++++++++ .../switchblock_scatter_gather_common_utils.h | 16 +- 3 files changed, 160 insertions(+), 160 deletions(-) diff --git a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp index 75ddf19bc35..bfde68bd29e 100644 --- a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp +++ b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp @@ -136,6 +136,8 @@ #include "vpr_types.h" #include "build_switchblocks.h" + +#include "globals.h" #include "physical_types.h" #include "parse_switchblocks.h" #include "vtr_expr_eval.h" @@ -145,11 +147,6 @@ using vtr::FormulaParser; using vtr::t_formula_data; -struct t_wire_switchpoint { - int wire; ///< Wire index within the channel - int switchpoint; ///< Switchpoint of the wire -}; - struct t_wireconn_scratchpad { FormulaParser formula_parser; t_formula_data formula_data; @@ -178,8 +175,7 @@ static void compute_wire_connections(const t_physical_tile_loc& sb_loc, 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, +static void compute_wireconn_connections(e_directionality directionality, const t_chan_details& from_chan_details, const t_chan_details& to_chan_details, SwitchblockLookupKey sb_conn, @@ -204,8 +200,6 @@ static int evaluate_num_conns_formula(t_wireconn_scratchpad* scratchpad, const s /** * * @brief calculates the wire indices belonging to the types in types in 'wire_type_sizes' and switchpoints in 'points' at the given channel segment - * - * @param grid device grid * @param chan_details channel segment details (length, start and end points, ...) * @param chan_type channel type (CHANX/CHANY) * @param x the wire x-coordinate @@ -218,8 +212,7 @@ static int evaluate_num_conns_formula(t_wireconn_scratchpad* scratchpad, const s * @param rng 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, +static void get_switchpoint_wires(const t_chan_seg_details* chan_details, e_rr_type chan_type, int x, int y, @@ -271,19 +264,6 @@ static const t_chan_details& index_into_correct_chan(const t_physical_tile_loc& */ static bool coords_out_of_bounds(const DeviceGrid& grid, int x_coord, int y_coord, int layer_coord, e_rr_type chan_type); -/* returns the subsegment number of the specified wire at seg_coord*/ -static int get_wire_subsegment_num(const DeviceGrid& grid, e_rr_type chan_type, const t_chan_seg_details& wire_details, int seg_coord); - -int get_wire_segment_length(const DeviceGrid& grid, e_rr_type chan_type, const t_chan_seg_details& wire_details); - -/* 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); - /* adjusts a negative destination wire index calculated from a permutation formula */ static int adjust_formula_result(int dest_wire, int src_W, int dest_W, int connection_ind); @@ -348,8 +328,7 @@ void free_switchblock_permutations(t_sb_connection_map* sb_conns) { vtr::malloc_trim(0); } -static void get_switchpoint_wires(const DeviceGrid& grid, - const t_chan_seg_details* chan_details, +static void get_switchpoint_wires(const t_chan_seg_details* chan_details, e_rr_type chan_type, int x, int y, @@ -372,7 +351,6 @@ static void get_switchpoint_wires(const DeviceGrid& grid, collected_wire_switchpoints.clear(); 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()) { // wire_type_sizes may not contain wire_type if its seg freq is 0 @@ -385,14 +363,12 @@ static void get_switchpoint_wires(const DeviceGrid& grid, 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 - * of the specified switchpoints. - * - * 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 architect. - */ - for (int valid_switchpoint : points) { + // Walk through each wire segment of specified type and check whether it matches one + // of the specified switchpoints. + // 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 architect. + for (int valid_switchpoint : wire_switchpoints.switchpoints) { for (int iwire = first_type_wire; iwire <= last_type_wire; iwire++) { Direction seg_direction = chan_details[iwire].direction(); @@ -416,7 +392,7 @@ static void get_switchpoint_wires(const DeviceGrid& grid, } } - int wire_switchpoint = get_switchpoint_of_wire(grid, chan_type, chan_details[iwire], seg_coord, side); + int wire_switchpoint = get_switchpoint_of_wire(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 if (wire_switchpoint != valid_switchpoint) continue; @@ -498,7 +474,7 @@ static void compute_wire_connections(const t_physical_tile_loc& sb_loc, 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_wireconn_connections(grid, directionality, from_chan_details, to_chan_details, + compute_wireconn_connections(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, sb_conns, rng, scratchpad); } @@ -508,8 +484,7 @@ static void compute_wire_connections(const t_physical_tile_loc& sb_loc, * 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, +static void compute_wireconn_connections(e_directionality directionality, const t_chan_details& from_chan_details, const t_chan_details& to_chan_details, SwitchblockLookupKey sb_conn, @@ -536,12 +511,12 @@ static void compute_wireconn_connections(const DeviceGrid& grid, 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, + get_switchpoint_wires(from_chan_details[from_x][from_y].data(), from_chan_type, from_x, from_y, from_side, 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, + get_switchpoint_wires(to_chan_details[to_x][to_y].data(), to_chan_type, to_x, to_y, to_side, wireconn.to_switchpoint_set, wire_type_sizes_to, /*is_dest=*/true, wireconn.to_switchpoint_order, rng, &scratchpad->potential_dest_wires, &scratchpad->scratch_wires); @@ -798,124 +773,6 @@ static bool coords_out_of_bounds(const DeviceGrid& grid, int x_coord, int y_coor return result; } -static int get_wire_subsegment_num(const DeviceGrid& grid, e_rr_type chan_type, const t_chan_seg_details& wire_details, int seg_coord) { - /* We get wire subsegment number by comparing the wire's seg_coord to the seg_start of the wire. - * The offset between seg_start (or seg_end) and seg_coord is the subsegment number - * - * Cases: - * seg starts at bottom but does not extend all the way to the top -- look at seg_end - * seg starts > bottom and does not extend all the way to top -- look at seg_start - * seg starts > bottom but terminates all the way at the top -- look at seg_start - * seg starts at bottom and extends all the way to the top -- look at seg end - */ - - int subsegment_num; - int seg_start = wire_details.seg_start(); - int seg_end = wire_details.seg_end(); - Direction direction = wire_details.direction(); - int wire_length = get_wire_segment_length(grid, chan_type, wire_details); - int min_seg; - - /* determine the minimum and maximum values that the 'seg' coordinate - * of a wire can take */ - min_seg = 1; - - if (seg_start != min_seg) { - subsegment_num = seg_coord - seg_start; - } else { - subsegment_num = (wire_length - 1) - (seg_end - seg_coord); - } - - /* if this wire is going in the decreasing direction, reverse the subsegment num */ - VTR_ASSERT(seg_end >= seg_start); - if (direction == Direction::DEC) { - subsegment_num = wire_length - 1 - subsegment_num; - } - - return subsegment_num; -} - -/* returns wire segment length based on either: - * 1) the wire length specified in the segment details variable for this wire (if this wire segment doesn't span entire FPGA) - * 2) the seg_start and seg_end coordinates in the segment details for this wire (if this wire segment spans entire FPGA, as might happen for very long wires) - * - * Computing the wire segment length in this way help to classify short vs long wire segments according to switchpoint. */ -int get_wire_segment_length(const DeviceGrid& grid, e_rr_type chan_type, const t_chan_seg_details& wire_details) { - int wire_length; - - int min_seg = 1; - int max_seg = grid.width() - 2; //-2 for no perim channels - if (chan_type == e_rr_type::CHANY) { - max_seg = grid.height() - 2; //-2 for no perim channels - } - - int seg_start = wire_details.seg_start(); - int seg_end = wire_details.seg_end(); - - if (seg_start == min_seg && seg_end == max_seg) { - wire_length = seg_end - seg_start + 1; - } else { - wire_length = wire_details.length(); - } - - 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) { - /* this function calculates the switchpoint of a given wire by first calculating - * 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 - * - * So knowing the wire's subsegment_num and which switchblock side it connects to is - * enough to calculate the 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 - if (chan_type == e_rr_type::CHANY) { - max_seg = grid.height() - 2; //-2 for no perim channels - } - - /* check whether the current seg_coord/sb_side coordinate specifies a perimeter switch block side at which all wire segments terminate/start. - * in this case only segments with switchpoints = 0 can exist */ - bool perimeter_connection = false; - if ((seg_coord == min_seg && (sb_side == RIGHT || sb_side == TOP)) || (seg_coord == max_seg && (sb_side == LEFT || sb_side == BOTTOM))) { - perimeter_connection = true; - } - - int switchpoint; - if (perimeter_connection) { - switchpoint = 0; - } else { - int wire_length = get_wire_segment_length(grid, chan_type, wire_details); - int subsegment_num = get_wire_subsegment_num(grid, chan_type, wire_details, seg_coord); - - Direction direction = wire_details.direction(); - if (LEFT == sb_side || BOTTOM == sb_side) { - switchpoint = (subsegment_num + 1) % wire_length; - if (direction == Direction::DEC) { - switchpoint = subsegment_num; - } - } else { - VTR_ASSERT(RIGHT == sb_side || TOP == sb_side); - switchpoint = subsegment_num; - if (direction == Direction::DEC) { - switchpoint = (subsegment_num + 1) % wire_length; - } - } - } - - return switchpoint; -} - /* adjusts the destination wire calculated from a permutation formula to account for negative indices, * source wire set offset, and modulo by destination wire set size * */ diff --git a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp index fa907aef337..ef389349cc2 100644 --- a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp +++ b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp @@ -6,6 +6,23 @@ #include "rr_node_types.h" #include "rr_types.h" +/** + * Returns wire segment length based on either: + * 1) the wire length specified in the segment details variable for this wire (if this wire segment doesn't span entire FPGA) + * 2) the seg_start and seg_end coordinates in the segment details for this wire (if this wire segment spans entire FPGA, as might happen for very long wires) + * + * Computing the wire segment length in this way help to classify short vs long wire segments according to switchpoint. + */ +static int get_wire_segment_length(e_rr_type chan_type, + const t_chan_seg_details& wire_details); + +/** + * @brief Returns the subsegment number of the specified wire at seg_coord + */ +static int get_wire_subsegment_num(e_rr_type chan_type, + const t_chan_seg_details& wire_details, + int seg_coord); + /** * @brief Counts and summarizes wire types in a routing channel. * @@ -167,6 +184,64 @@ static t_wire_type_sizes count_chan_wire_type_sizes(const t_chan_seg_details* ch return wire_type_sizes; } +static int get_wire_subsegment_num(e_rr_type chan_type, + const t_chan_seg_details& wire_details, + int seg_coord) { + // We get wire subsegment number by comparing the wire's seg_coord to the seg_start of the wire. + // The offset between seg_start (or seg_end) and seg_coord is the subsegment number + // Cases: + // seg starts at bottom but does not extend all the way to the top -- look at seg_end + // seg starts > bottom and does not extend all the way to top -- look at seg_start + // seg starts > bottom but terminates all the way at the top -- look at seg_start + // seg starts at bottom and extends all the way to the top -- look at seg end + + int seg_start = wire_details.seg_start(); + int seg_end = wire_details.seg_end(); + Direction direction = wire_details.direction(); + int wire_length = get_wire_segment_length(chan_type, wire_details); + + // Determine the minimum and maximum values that the 'seg' coordinate of a wire can take + int min_seg = 1; + + int subsegment_num; + if (seg_start != min_seg) { + subsegment_num = seg_coord - seg_start; + } else { + subsegment_num = (wire_length - 1) - (seg_end - seg_coord); + } + + // If this wire is going in the decreasing direction, reverse the subsegment num. + VTR_ASSERT(seg_end >= seg_start); + if (direction == Direction::DEC) { + subsegment_num = wire_length - 1 - subsegment_num; + } + + return subsegment_num; +} + +static int get_wire_segment_length(e_rr_type chan_type, + const t_chan_seg_details& wire_details) { + const DeviceGrid& grid = g_vpr_ctx.device().grid; + + int min_seg = 1; + int max_seg = grid.width() - 2; //-2 for no perim channels + if (chan_type == e_rr_type::CHANY) { + max_seg = grid.height() - 2; //-2 for no perim channels + } + + int seg_start = wire_details.seg_start(); + int seg_end = wire_details.seg_end(); + + int wire_length; + if (seg_start == min_seg && seg_end == max_seg) { + wire_length = seg_end - seg_start + 1; + } else { + wire_length = wire_details.length(); + } + + return wire_length; +} + bool sb_not_here(const DeviceGrid& grid, const std::vector& inter_cluster_rr, const t_physical_tile_loc& loc, @@ -315,4 +390,58 @@ std::pair count_wire_type_sizes(const t_ch t_wire_type_sizes wire_type_sizes_y = count_chan_wire_type_sizes(chan_details_y[0][0].data(), nodes_per_chan.y_max); return {wire_type_sizes_x, wire_type_sizes_y}; +} + +int get_switchpoint_of_wire(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 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 + // + // So knowing the wire's subsegment_num and which switchblock side it connects to is + // enough to calculate the switchpoint + + const DeviceGrid& grid = g_vpr_ctx.device().grid; + + // 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 + if (chan_type == e_rr_type::CHANY) { + max_seg = grid.height() - 2; // -2 for no perim channels + } + + // Check whether the current seg_coord/sb_side coordinate specifies a perimeter switch block side at which all wire segments terminate/start. + // in this case only segments with switchpoints = 0 can exist + bool perimeter_connection = false; + if ((seg_coord == min_seg && (sb_side == RIGHT || sb_side == TOP)) || (seg_coord == max_seg && (sb_side == LEFT || sb_side == BOTTOM))) { + perimeter_connection = true; + } + + int switchpoint; + if (perimeter_connection) { + switchpoint = 0; + } else { + int wire_length = get_wire_segment_length(chan_type, wire_details); + int subsegment_num = get_wire_subsegment_num(chan_type, wire_details, seg_coord); + + Direction direction = wire_details.direction(); + if (LEFT == sb_side || BOTTOM == sb_side) { + switchpoint = (subsegment_num + 1) % wire_length; + if (direction == Direction::DEC) { + switchpoint = subsegment_num; + } + } else { + VTR_ASSERT(RIGHT == sb_side || TOP == sb_side); + switchpoint = subsegment_num; + if (direction == Direction::DEC) { + switchpoint = (subsegment_num + 1) % wire_length; + } + } + } + + return switchpoint; } \ No newline at end of file diff --git a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h index 87dcc3a199f..ae4c1f3a4d2 100644 --- a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h +++ b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h @@ -28,6 +28,11 @@ struct t_wire_info { } }; +struct t_wire_switchpoint { + int wire; ///< Wire index within the channel + int switchpoint; ///< Switchpoint of the wire +}; + /// Used to get info about a given wire type based on the name typedef vtr::flat_map t_wire_type_sizes; @@ -58,4 +63,13 @@ bool chan_coords_out_of_bounds(const t_physical_tile_loc& loc, e_rr_type chan_ty std::pair count_wire_type_sizes(const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, - const t_chan_width& nodes_per_chan); \ No newline at end of file + const t_chan_width& nodes_per_chan); + +/** + * 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 + */ +int get_switchpoint_of_wire(e_rr_type chan_type, + const t_chan_seg_details& wire_details, + int seg_coord, + e_side sb_side); \ No newline at end of file From c1f277108ea302f2d79b8596d4f8d94f1dd2e53d Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Sun, 7 Sep 2025 16:45:09 -0400 Subject: [PATCH 11/58] collect candidate wires for scatter-gather at each location --- .../build_scatter_gathers.cpp | 98 ++++++++++++++++++- .../build_scatter_gathers.h | 4 +- .../build_switchblocks.cpp | 2 +- 3 files changed, 97 insertions(+), 7 deletions(-) diff --git a/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp b/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp index 82a8413a756..415215183c7 100644 --- a/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp +++ b/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp @@ -3,6 +3,7 @@ #include "switchblock_scatter_gather_common_utils.h" #include "scatter_gather_types.h" +#include "rr_types.h" #include "globals.h" #include "vtr_assert.h" @@ -12,7 +13,7 @@ static void index_to_correct_channels(const t_wireconn_inf& pattern, const t_physical_tile_loc& loc, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, - std::vector>& correct_channels) { + std::vector>& correct_channels) { correct_channels.clear(); for (e_side side : pattern.sides) { @@ -22,19 +23,95 @@ static void index_to_correct_channels(const t_wireconn_inf& pattern, index_into_correct_chan(loc, side, chan_details_x, chan_details_y,chan_loc, chan_type); if (!chan_coords_out_of_bounds(chan_loc, chan_type)) { - correct_channels.push_back({chan_loc, chan_type}); + correct_channels.push_back({chan_loc, chan_type, side}); } } } +static +std::vector> + find_candidate_wires(const std::vector>& channels, + const std::vector& wire_switchpoints_vec, + const t_chan_details& chan_details_x, + const t_chan_details& chan_details_y, + const t_wire_type_sizes& wire_type_sizes_x, + const t_wire_type_sizes& wire_type_sizes_y, + bool is_dest) { + + // TODO: reuse + std::vector> collected_wire_switchpoints; + + for (const auto [chan_loc, chan_type, chan_side] : channels) { + int seg_coord = (chan_type == e_rr_type::CHANY) ? chan_loc.y : chan_loc.x; + + const t_wire_type_sizes& wire_type_sizes = (chan_type == e_rr_type::CHANX) ? wire_type_sizes_x : wire_type_sizes_y; + const t_chan_seg_details* chan_details = (chan_type == e_rr_type::CHANX) ? chan_details_x[chan_loc.x][chan_loc.y].data() : chan_details_y[chan_loc.x][chan_loc.y].data(); + + for (const t_wire_switchpoints& wire_switchpoints : wire_switchpoints_vec) { + collected_wire_switchpoints.clear(); + auto wire_type = vtr::string_view(wire_switchpoints.segment_name); + + 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; + int last_type_wire = first_type_wire + num_type_wires - 1; + + for (int valid_switchpoint : wire_switchpoints.switchpoints) { + for (int iwire = first_type_wire; iwire <= last_type_wire; iwire++) { + Direction seg_direction = chan_details[iwire].direction(); + + /* unidirectional wires going in the decreasing direction can have an outgoing edge + * only from the top or right switch block sides, and an incoming edge only if they are + * at the left or bottom sides (analogous for wires going in INC direction) */ + if (chan_side == TOP || chan_side == RIGHT) { + if (seg_direction == Direction::DEC && is_dest) { + continue; + } + if (seg_direction == Direction::INC && !is_dest) { + continue; + } + } else { + VTR_ASSERT(chan_side == LEFT || chan_side == BOTTOM); + if (seg_direction == Direction::DEC && !is_dest) { + continue; + } + if (seg_direction == Direction::INC && is_dest) { + continue; + } + } + + int wire_switchpoint = get_switchpoint_of_wire(chan_type, chan_details[iwire], seg_coord, chan_side); + + // 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({chan_loc, chan_type, chan_side, {iwire, wire_switchpoint}}); + } + } + + } + } + + return collected_wire_switchpoints; +} + void alloc_and_load_scatter_gather_connections(const std::vector& scatter_gather_patterns, const std::vector& inter_cluster_rr, const t_chan_details& chan_details_x, - const t_chan_details& chan_details_y) { + const t_chan_details& chan_details_y, + const t_chan_width& nodes_per_chan) { const DeviceGrid& grid = g_vpr_ctx.device().grid; - std::vector> gather_channels; - std::vector> scatter_channels; + std::vector> gather_channels; + std::vector> scatter_channels; + + const auto [wire_type_sizes_x, wire_type_sizes_y] = count_wire_type_sizes(chan_details_x, chan_details_y, nodes_per_chan); for (const t_scatter_gather_pattern& sg_pattern : scatter_gather_patterns) { VTR_ASSERT(sg_pattern.type == e_scatter_gather_type::UNIDIR); @@ -67,6 +144,17 @@ void alloc_and_load_scatter_gather_connections(const std::vector void alloc_and_load_scatter_gather_connections(const std::vector& scatter_gather_patterns, const std::vector& inter_cluster_rr, const t_chan_details& chan_details_x, - const t_chan_details& chan_details_y); \ No newline at end of file + const t_chan_details& chan_details_y, + const t_chan_width& nodes_per_chan); \ No newline at end of file diff --git a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp index bfde68bd29e..767c4ea0325 100644 --- a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp +++ b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp @@ -406,7 +406,7 @@ static void get_switchpoint_wires(const t_chan_seg_details* chan_details, } if (switchpoint_order == e_switch_point_order::SHUFFLED) { - // We new re-order the switchpoints to try to make adjacent switchpoints have different values + // We now 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 == e_switch_point_order::FIXED); From 8359c63287670ed96cefc62f1475bafc43f2ebb6 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Mon, 8 Sep 2025 16:46:40 -0400 Subject: [PATCH 12/58] move evaluate_num_conns_formula() to common utils --- .../build_switchblocks.cpp | 27 ++++++------------- ...witchblock_scatter_gather_common_utils.cpp | 14 ++++++++++ .../switchblock_scatter_gather_common_utils.h | 10 ++++++- 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp index 767c4ea0325..23139a7a3f5 100644 --- a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp +++ b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp @@ -144,12 +144,9 @@ #include "rr_types.h" #include "switchblock_scatter_gather_common_utils.h" -using vtr::FormulaParser; -using vtr::t_formula_data; - struct t_wireconn_scratchpad { - FormulaParser formula_parser; - t_formula_data formula_data; + vtr::FormulaParser formula_parser; + vtr::t_formula_data formula_data; std::vector potential_src_wires; std::vector potential_dest_wires; std::vector scratch_wires; @@ -195,8 +192,6 @@ static void compute_wireconn_connections(e_directionality directionality, 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); - /** * * @brief calculates the wire indices belonging to the types in types in 'wire_type_sizes' and switchpoints in 'points' at the given channel segment @@ -575,7 +570,11 @@ static void compute_wireconn_connections(e_directionality directionality, // * interleave (to ensure good diversity) // 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()); + int num_conns = evaluate_num_conns_formula(scratchpad->formula_parser, + scratchpad->formula_data, + 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); @@ -613,7 +612,7 @@ static void compute_wireconn_connections(e_directionality directionality, const std::vector& permutations_ref = iter->second; for (const std::string& perm : permutations_ref) { /* Convert the symbolic permutation formula to a number */ - t_formula_data& formula_data = scratchpad->formula_data; + vtr::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); @@ -665,16 +664,6 @@ static void compute_wireconn_connections(e_directionality directionality, } } -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(); - - vars.set_var_value("from", from_wire_count); - vars.set_var_value("to", to_wire_count); - - return scratchpad->formula_parser.parse_formula(num_conns_formula, vars); -} - static const t_chan_details& index_into_correct_chan(const t_physical_tile_loc& sb_loc, e_side src_side, e_side dest_side, diff --git a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp index ef389349cc2..40f362cfa11 100644 --- a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp +++ b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp @@ -5,6 +5,7 @@ #include "vpr_error.h" #include "rr_node_types.h" #include "rr_types.h" +#include "vtr_expr_eval.h" /** * Returns wire segment length based on either: @@ -444,4 +445,17 @@ int get_switchpoint_of_wire(e_rr_type chan_type, } return switchpoint; +} + +int evaluate_num_conns_formula(vtr::FormulaParser& formula_parser, + vtr::t_formula_data& formula_data, + const std::string& num_conns_formula, + int from_wire_count, + int to_wire_count) { + formula_data.clear(); + + formula_data.set_var_value("from", from_wire_count); + formula_data.set_var_value("to", to_wire_count); + + return formula_parser.parse_formula(num_conns_formula, formula_data); } \ No newline at end of file diff --git a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h index ae4c1f3a4d2..8d01fc28c12 100644 --- a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h +++ b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h @@ -4,9 +4,11 @@ #include "device_grid.h" #include "rr_types.h" #include "rr_graph_type.h" +#include "vtr_expr_eval.h" #include + /** Contains info about a wire segment type */ struct t_wire_info { int length; ///< the length of this type of wire segment in tiles @@ -72,4 +74,10 @@ std::pair count_wire_type_sizes(const t_ch int get_switchpoint_of_wire(e_rr_type chan_type, const t_chan_seg_details& wire_details, int seg_coord, - e_side sb_side); \ No newline at end of file + e_side sb_side); + +int evaluate_num_conns_formula(vtr::FormulaParser& formula_parser, + vtr::t_formula_data& formula_data, + const std::string& num_conns_formula, + int from_wire_count, + int to_wire_count); \ No newline at end of file From a575d958a75ce6e7cee8baf8c7eaae8b9d32a89a Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Mon, 8 Sep 2025 16:55:34 -0400 Subject: [PATCH 13/58] replace tuples with structs --- .../build_scatter_gathers.cpp | 59 ++++++++++++++----- 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp b/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp index 415215183c7..2fa77698819 100644 --- a/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp +++ b/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp @@ -9,11 +9,27 @@ #include +struct t_chan_loc { + t_physical_tile_loc location; + e_rr_type chan_type; + e_side side; +}; + +struct t_sg_candidate { + t_chan_loc chan_loc; + t_wire_switchpoint wire_switchpoint; +}; + +struct t_bottleneck_link { + std::vector gather_fanin_connections; + std::vector scatter_fanout_connections; +}; + static void index_to_correct_channels(const t_wireconn_inf& pattern, const t_physical_tile_loc& loc, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, - std::vector>& correct_channels) { + std::vector& correct_channels) { correct_channels.clear(); for (e_side side : pattern.sides) { @@ -29,8 +45,8 @@ static void index_to_correct_channels(const t_wireconn_inf& pattern, } static -std::vector> - find_candidate_wires(const std::vector>& channels, +std::vector + find_candidate_wires(const std::vector& channels, const std::vector& wire_switchpoints_vec, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, @@ -39,7 +55,7 @@ std::vector> collected_wire_switchpoints; + std::vector candidates; for (const auto [chan_loc, chan_type, chan_side] : channels) { int seg_coord = (chan_type == e_rr_type::CHANY) ? chan_loc.y : chan_loc.x; @@ -48,7 +64,6 @@ std::vector& scatter_gather_patterns, @@ -108,8 +123,11 @@ void alloc_and_load_scatter_gather_connections(const std::vector> gather_channels; - std::vector> scatter_channels; + std::vector gather_channels; + std::vector scatter_channels; + + vtr::FormulaParser formula_parser; + vtr::t_formula_data formula_data; const auto [wire_type_sizes_x, wire_type_sizes_y] = count_wire_type_sizes(chan_details_x, chan_details_y, nodes_per_chan); @@ -123,10 +141,10 @@ void alloc_and_load_scatter_gather_connections(const std::vector Date: Tue, 9 Sep 2025 12:13:40 -0400 Subject: [PATCH 14/58] call alloc_and_load_scatter_gather_connections --- .../build_scatter_gathers.cpp | 62 ++++++++++++------- .../build_scatter_gathers.h | 27 ++++++-- .../route/rr_graph_generation/rr_graph.cpp | 11 ++++ ...witchblock_scatter_gather_common_utils.cpp | 4 +- .../switchblock_scatter_gather_common_utils.h | 4 +- .../3d_SB_inter_die_stratixiv_arch.timing.xml | 8 +-- 6 files changed, 79 insertions(+), 37 deletions(-) diff --git a/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp b/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp index 2fa77698819..acfadeb8329 100644 --- a/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp +++ b/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp @@ -9,22 +9,6 @@ #include -struct t_chan_loc { - t_physical_tile_loc location; - e_rr_type chan_type; - e_side side; -}; - -struct t_sg_candidate { - t_chan_loc chan_loc; - t_wire_switchpoint wire_switchpoint; -}; - -struct t_bottleneck_link { - std::vector gather_fanin_connections; - std::vector scatter_fanout_connections; -}; - static void index_to_correct_channels(const t_wireconn_inf& pattern, const t_physical_tile_loc& loc, const t_chan_details& chan_details_x, @@ -116,11 +100,11 @@ std::vector return candidates; } -void alloc_and_load_scatter_gather_connections(const std::vector& scatter_gather_patterns, - const std::vector& inter_cluster_rr, - const t_chan_details& chan_details_x, - const t_chan_details& chan_details_y, - const t_chan_width& nodes_per_chan) { +std::vector alloc_and_load_scatter_gather_connections(const std::vector& scatter_gather_patterns, + const std::vector& inter_cluster_rr, + const t_chan_details& chan_details_x, + const t_chan_details& chan_details_y, + const t_chan_width& nodes_per_chan) { const DeviceGrid& grid = g_vpr_ctx.device().grid; std::vector gather_channels; @@ -129,6 +113,8 @@ void alloc_and_load_scatter_gather_connections(const std::vector bottleneck_links; + const auto [wire_type_sizes_x, wire_type_sizes_y] = count_wire_type_sizes(chan_details_x, chan_details_y, nodes_per_chan); for (const t_scatter_gather_pattern& sg_pattern : scatter_gather_patterns) { @@ -142,7 +128,7 @@ void alloc_and_load_scatter_gather_connections(const std::vector gather_wire_candidates.size()) { + bottleneck_fanin = gather_wire_candidates.size(); + } + if (bottleneck_fanout > scatter_wire_candidates.size()) { + bottleneck_fanout = scatter_wire_candidates.size(); + } + + + for (int i_bottleneck = 0, i_s = 0, i_g = 0; i_bottleneck < sg_loc_info.num; i_bottleneck++) { + + t_bottleneck_link bottleneck_link; + bottleneck_link.gather_fanin_connections.reserve(bottleneck_fanin); + bottleneck_link.scatter_fanout_connections.reserve(bottleneck_fanout); + for (int i = 0; i < bottleneck_fanin; i++) { + bottleneck_link.gather_fanin_connections.push_back(gather_wire_candidates[i_g]); + i_g = (i_g + 1) % bottleneck_fanin; + } + + for (int i = 0; i < bottleneck_fanout; i++) { + bottleneck_link.scatter_fanout_connections.push_back(scatter_wire_candidates[i_s]); + i_s = (i_s + 1) % bottleneck_fanout; + } + + bottleneck_links.push_back(std::move(bottleneck_link)); + } + + } + } } + + return bottleneck_links; } diff --git a/vpr/src/route/rr_graph_generation/build_scatter_gathers.h b/vpr/src/route/rr_graph_generation/build_scatter_gathers.h index 5d7a6089a0a..a8df647652a 100644 --- a/vpr/src/route/rr_graph_generation/build_scatter_gathers.h +++ b/vpr/src/route/rr_graph_generation/build_scatter_gathers.h @@ -3,11 +3,28 @@ #include "scatter_gather_types.h" #include "rr_types.h" #include "rr_graph_type.h" +#include "switchblock_scatter_gather_common_utils.h" #include -void alloc_and_load_scatter_gather_connections(const std::vector& scatter_gather_patterns, - const std::vector& inter_cluster_rr, - const t_chan_details& chan_details_x, - const t_chan_details& chan_details_y, - const t_chan_width& nodes_per_chan); \ No newline at end of file +struct t_chan_loc { + t_physical_tile_loc location; + e_rr_type chan_type; + e_side side; +}; + +struct t_sg_candidate { + t_chan_loc chan_loc; + t_wire_switchpoint wire_switchpoint; +}; + +struct t_bottleneck_link { + std::vector gather_fanin_connections; + std::vector scatter_fanout_connections; +}; + +std::vector alloc_and_load_scatter_gather_connections(const std::vector& scatter_gather_patterns, + const std::vector& inter_cluster_rr, + const t_chan_details& chan_details_x, + const t_chan_details& chan_details_y, + const t_chan_width& nodes_per_chan); \ No newline at end of file diff --git a/vpr/src/route/rr_graph_generation/rr_graph.cpp b/vpr/src/route/rr_graph_generation/rr_graph.cpp index 4d5b701aba4..e02d63362eb 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph.cpp +++ b/vpr/src/route/rr_graph_generation/rr_graph.cpp @@ -4,6 +4,7 @@ #include #include #include "alloc_and_load_rr_indexed_data.h" +#include "build_scatter_gathers.h" #include "get_parallel_segs.h" #include "physical_types.h" #include "physical_types_util.h" @@ -607,6 +608,7 @@ static void build_rr_graph(e_graph_type graph_type, const e_base_cost_type base_cost_type, const e_clock_modeling clock_modeling, const std::vector& directs, + const std::vector& scatter_gather_patterns, int* wire_to_rr_ipin_switch, bool is_flat, int* Warnings, @@ -711,6 +713,7 @@ void create_rr_graph(e_graph_type graph_type, router_opts.base_cost_type, router_opts.clock_modeling, directs, + device_ctx.arch->scatter_gather_patterns, &det_routing_arch.wire_to_rr_ipin_switch, is_flat, Warnings, @@ -950,6 +953,7 @@ static void build_rr_graph(e_graph_type graph_type, const e_base_cost_type base_cost_type, const e_clock_modeling clock_modeling, const std::vector& directs, + const std::vector& scatter_gather_patterns, int* wire_to_rr_ipin_switch, bool is_flat, int* Warnings, @@ -1191,6 +1195,13 @@ static void build_rr_graph(e_graph_type graph_type, grid, inter_cluster_prog_rr, switchblocks, nodes_per_chan, directionality, switchpoint_rng); + + alloc_and_load_scatter_gather_connections(scatter_gather_patterns, + inter_cluster_prog_rr, + chan_details_x, chan_details_y, + nodes_per_chan); + + } else { if (directionality == BI_DIRECTIONAL) { switch_block_conn = alloc_and_load_switch_block_conn(&nodes_per_chan, sb_type, Fs); diff --git a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp index 40f362cfa11..9c758f4065e 100644 --- a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp +++ b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp @@ -450,8 +450,8 @@ int get_switchpoint_of_wire(e_rr_type chan_type, int evaluate_num_conns_formula(vtr::FormulaParser& formula_parser, vtr::t_formula_data& formula_data, const std::string& num_conns_formula, - int from_wire_count, - int to_wire_count) { + size_t from_wire_count, + size_t to_wire_count) { formula_data.clear(); formula_data.set_var_value("from", from_wire_count); diff --git a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h index 8d01fc28c12..b8c526e8c06 100644 --- a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h +++ b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h @@ -79,5 +79,5 @@ int get_switchpoint_of_wire(e_rr_type chan_type, int evaluate_num_conns_formula(vtr::FormulaParser& formula_parser, vtr::t_formula_data& formula_data, const std::string& num_conns_formula, - int from_wire_count, - int to_wire_count); \ No newline at end of file + size_t from_wire_count, + size_t to_wire_count); \ No newline at end of file diff --git a/vtr_flow/arch/multi_die/stratixiv_3d/3d_SB_inter_die_stratixiv_arch.timing.xml b/vtr_flow/arch/multi_die/stratixiv_3d/3d_SB_inter_die_stratixiv_arch.timing.xml index 4a7bdb4f2e2..8f8691b7cf5 100644 --- a/vtr_flow/arch/multi_die/stratixiv_3d/3d_SB_inter_die_stratixiv_arch.timing.xml +++ b/vtr_flow/arch/multi_die/stratixiv_3d/3d_SB_inter_die_stratixiv_arch.timing.xml @@ -48374,19 +48374,19 @@ - + - + - + - + From 333aa5785c9104ceeb4542e9a5304b34e1a9a5bf Mon Sep 17 00:00:00 2001 From: Amir Poolad Date: Tue, 9 Sep 2025 12:06:22 -0400 Subject: [PATCH 15/58] Fix bug where sg_link offsets would be uninitialized --- .../libarchfpga/src/read_xml_arch_file_sg.cpp | 31 ++++--------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/libs/libarchfpga/src/read_xml_arch_file_sg.cpp b/libs/libarchfpga/src/read_xml_arch_file_sg.cpp index c432aeb665e..502a399cc49 100644 --- a/libs/libarchfpga/src/read_xml_arch_file_sg.cpp +++ b/libs/libarchfpga/src/read_xml_arch_file_sg.cpp @@ -4,6 +4,7 @@ #include "pugixml_util.hpp" #include "arch_error.h" #include "switchblock_types.h" +#include "vtr_util.h" /** * @brief Parses all tags under a tag. @@ -26,32 +27,12 @@ static std::vector parse_sg_link_tags(pugi::xml_node sg_link_list_tag sg_link.seg_type = pugiutil::get_attribute(node, "seg_type", loc_data).as_string(); // Since the offset attributes are optional and might not exist, the as_int method will return a value of zero if the attribute is empty - int x_offset = pugiutil::get_attribute(node, "x_offset", loc_data, pugiutil::OPTIONAL).as_int(0); - int y_offset = pugiutil::get_attribute(node, "y_offset", loc_data, pugiutil::OPTIONAL).as_int(0); - int z_offset = pugiutil::get_attribute(node, "z_offset", loc_data, pugiutil::OPTIONAL).as_int(0); + sg_link.x_offset = pugiutil::get_attribute(node, "x_offset", loc_data, pugiutil::OPTIONAL).as_int(0); + sg_link.y_offset = pugiutil::get_attribute(node, "y_offset", loc_data, pugiutil::OPTIONAL).as_int(0); + sg_link.z_offset = pugiutil::get_attribute(node, "z_offset", loc_data, pugiutil::OPTIONAL).as_int(0); - if (x_offset == 0 && y_offset == 0 && z_offset == 0) { - archfpga_throw(loc_data.filename_c_str(), loc_data.line(node), "All offset fields in the are zero or missing."); - } - - // We expect exactly one non-zero offset so the gather and scatter points are joined by a node that can be represented by a straight wire. - if (x_offset != 0) { - sg_link.x_offset = x_offset; - if (y_offset != 0 || z_offset != 0) { - archfpga_throw(loc_data.filename_c_str(), loc_data.line(node), "More than one of the offset fields in the are non-zero."); - } - } - if (y_offset != 0) { - sg_link.y_offset = y_offset; - if (x_offset != 0 || z_offset != 0) { - archfpga_throw(loc_data.filename_c_str(), loc_data.line(node), "More than one of the offset fields in the are non-zero."); - } - } - if (z_offset != 0) { - sg_link.z_offset = z_offset; - if (y_offset != 0 || x_offset != 0) { - archfpga_throw(loc_data.filename_c_str(), loc_data.line(node), "More than one of the offset fields in the are non-zero."); - } + if (vtr::exactly_k_conditions(1, sg_link.x_offset != 0, sg_link.y_offset != 0, sg_link.z_offset != 0)) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(node), "One and only one of the offset fields in the should be non-zero."); } sg_link_list.push_back(sg_link); From 7abe75ed8af138944f2fc6698d1243de49ea709a Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Tue, 9 Sep 2025 14:22:18 -0400 Subject: [PATCH 16/58] fix the condition for checking that only one offset is set --- libs/libarchfpga/src/read_xml_arch_file_sg.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/libarchfpga/src/read_xml_arch_file_sg.cpp b/libs/libarchfpga/src/read_xml_arch_file_sg.cpp index 502a399cc49..11f9e1976fb 100644 --- a/libs/libarchfpga/src/read_xml_arch_file_sg.cpp +++ b/libs/libarchfpga/src/read_xml_arch_file_sg.cpp @@ -31,7 +31,7 @@ static std::vector parse_sg_link_tags(pugi::xml_node sg_link_list_tag sg_link.y_offset = pugiutil::get_attribute(node, "y_offset", loc_data, pugiutil::OPTIONAL).as_int(0); sg_link.z_offset = pugiutil::get_attribute(node, "z_offset", loc_data, pugiutil::OPTIONAL).as_int(0); - if (vtr::exactly_k_conditions(1, sg_link.x_offset != 0, sg_link.y_offset != 0, sg_link.z_offset != 0)) { + if (!vtr::exactly_k_conditions(1, sg_link.x_offset != 0, sg_link.y_offset != 0, sg_link.z_offset != 0)) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(node), "One and only one of the offset fields in the should be non-zero."); } From a5e7fd7366ca9a91e3543c03054a45b1de75a325 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Tue, 9 Sep 2025 14:22:57 -0400 Subject: [PATCH 17/58] pass t_physical_loc instead of x/y/layer --- .../build_switchblocks.cpp | 197 +++--------------- .../switchblock_scatter_gather_common_utils.h | 20 ++ 2 files changed, 44 insertions(+), 173 deletions(-) diff --git a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp index 23139a7a3f5..6496944451c 100644 --- a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp +++ b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp @@ -163,7 +163,6 @@ static void compute_wire_connections(const t_physical_tile_loc& sb_loc, 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, @@ -176,12 +175,8 @@ static void compute_wireconn_connections(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, + const t_physical_tile_loc& from_loc, + const t_physical_tile_loc& to_loc, e_rr_type from_chan_type, e_rr_type to_chan_type, const t_wire_type_sizes& wire_type_sizes_from, @@ -220,45 +215,6 @@ static void get_switchpoint_wires(const t_chan_seg_details* chan_details, 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 - * specified tile coordinates (x,y,layer) and the switch block side. - * - * @param sb_loc Coordinates of the switch-box - * @param src_side switch block source 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 - * @param chan_y y-coordinate of the channel - * @param chan_layer layer_coordinate of the channel - * @param chan_type chan type that the function index into - * - * @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(const t_physical_tile_loc& sb_loc, - e_side src_side, - 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 - * - * @param grid device grid - * @param x_coord x-coordinate of the location - * @param y_coord y-coordinate of the location - * @param layer_coord layer-coordinate of the location - * @param chan_type track channel type (CHANX or CHANY), required since device perimeter does not have certain channels - * - * @return true if the track location is outside the device grid, false otherwise. - */ -static bool coords_out_of_bounds(const DeviceGrid& grid, int x_coord, int y_coord, int layer_coord, e_rr_type chan_type); - /* adjusts a negative destination wire index calculated from a permutation formula */ static int adjust_formula_result(int dest_wire, int src_W, int dest_W, int connection_ind); @@ -299,7 +255,7 @@ t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_detail 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 compute_wire_connections(sb_loc, from_side, to_side, - chan_details_x, chan_details_y, sb, grid, + chan_details_x, chan_details_y, sb, wire_type_sizes_x, wire_type_sizes_y, directionality, sb_conns, rng, &scratchpad); } @@ -415,17 +371,15 @@ static void compute_wire_connections(const t_physical_tile_loc& sb_loc, 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) { - 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; + t_physical_tile_loc from_loc, to_loc; + // For indexing into this switchblock's permutation funcs SBSideConnection side_conn(from_side, to_side); @@ -447,16 +401,15 @@ static void compute_wire_connections(const t_physical_tile_loc& sb_loc, * destination channels. also return the channel type (ie chanx/chany/both) into which we are * indexing */ // Details for source channel - const t_chan_details& from_chan_details = index_into_correct_chan(sb_loc, from_side, to_side, chan_details_x, chan_details_y, - from_x, from_y, from_layer, from_chan_type); + const t_chan_details& from_chan_details = index_into_correct_chan(sb_loc, from_side, chan_details_x, chan_details_y, + from_loc, from_chan_type); // Details for destination channel - const t_chan_details& to_chan_details = index_into_correct_chan(sb_loc, to_side, from_side, chan_details_x, chan_details_y, - to_x, to_y, to_layer, to_chan_type); + const t_chan_details& to_chan_details = index_into_correct_chan(sb_loc, to_side, chan_details_x, chan_details_y, + to_loc, 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_loc and to_loc aren't out of bounds + if (chan_coords_out_of_bounds(to_loc, to_chan_type) || chan_coords_out_of_bounds(from_loc, from_chan_type)) { return; } @@ -470,7 +423,7 @@ static void compute_wire_connections(const t_physical_tile_loc& sb_loc, // compute the destination wire segments to which the source wire segment should connect based on the current wireconn compute_wireconn_connections(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, + sb_conn, from_loc, to_loc, from_chan_type, to_chan_type, wire_type_sizes_from, wire_type_sizes_to, sb, wireconn, sb_conns, rng, scratchpad); } } @@ -483,12 +436,8 @@ static void compute_wireconn_connections(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, + const t_physical_tile_loc& from_loc, + const t_physical_tile_loc& to_loc, e_rr_type from_chan_type, e_rr_type to_chan_type, const t_wire_type_sizes& wire_type_sizes_from, @@ -506,12 +455,12 @@ static void compute_wireconn_connections(e_directionality directionality, 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(from_chan_details[from_x][from_y].data(), from_chan_type, from_x, from_y, from_side, + get_switchpoint_wires(from_chan_details[from_loc.x][from_loc.y].data(), from_chan_type, from_loc.x, from_loc.y, from_side, 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(to_chan_details[to_x][to_y].data(), to_chan_type, to_x, to_y, to_side, + get_switchpoint_wires(to_chan_details[to_loc.x][to_loc.y].data(), to_chan_type, to_loc.x, to_loc.y, to_side, wireconn.to_switchpoint_set, wire_type_sizes_to, /*is_dest=*/true, wireconn.to_switchpoint_order, rng, &scratchpad->potential_dest_wires, &scratchpad->scratch_wires); @@ -585,7 +534,7 @@ static void compute_wireconn_connections(e_directionality directionality, 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 - Direction from_wire_direction = from_chan_details[from_x][from_y][from_wire].direction(); + Direction from_wire_direction = from_chan_details[from_loc.x][from_loc.y][from_wire].direction(); if (from_wire_direction == Direction::INC) { /* if this is a unidirectional wire headed in the increasing direction (relative to coordinate system) * then switch block source side should be BOTTOM or LEFT */ @@ -630,19 +579,19 @@ static void compute_wireconn_connections(e_directionality directionality, t_switchblock_edge sb_edge; sb_edge.from_wire = from_wire; sb_edge.to_wire = to_wire; - sb_edge.from_wire_layer = from_layer; - sb_edge.to_wire_layer = to_layer; + sb_edge.from_wire_layer = from_loc.layer_num; + sb_edge.to_wire_layer = to_loc.layer_num; // if the switch override has been set, use that, Otherwise use default 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(); + } else if (from_loc.layer_num == to_loc.layer_num) { + sb_edge.switch_ind = to_chan_details[to_loc.x][to_loc.y][to_wire].arch_wire_switch(); sb_edge.switch_ind_between_layers = -1; //the connection does not cross any layers } else { - VTR_ASSERT(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 = to_chan_details[to_x][to_y][to_wire].arch_inter_die_switch(); + VTR_ASSERT(from_loc.layer_num != to_loc.layer_num); + sb_edge.switch_ind = to_chan_details[to_loc.x][to_loc.y][to_wire].arch_wire_switch(); + sb_edge.switch_ind_between_layers = to_chan_details[to_loc.x][to_loc.y][to_wire].arch_inter_die_switch(); } VTR_LOGV(verbose, " make_conn: %d -> %d switch=%d\n", sb_edge.from_wire, sb_edge.to_wire, sb_edge.switch_ind); @@ -664,104 +613,6 @@ static void compute_wireconn_connections(e_directionality directionality, } } -static const t_chan_details& index_into_correct_chan(const t_physical_tile_loc& sb_loc, - e_side src_side, - 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 */ - switch (src_side) { - case TOP: - /* this is y-channel belonging to tile above in the same layer */ - chan_x = sb_loc.x; - chan_y = sb_loc.y + 1; - chan_layer = sb_loc.layer_num; - chan_type = e_rr_type::CHANY; - return chan_details_y; - break; - case RIGHT: - /* this is x-channel belonging to tile to the right in the same layer */ - chan_x = sb_loc.x + 1; - chan_y = sb_loc.y; - chan_layer = sb_loc.layer_num; - chan_type = e_rr_type::CHANX; - return chan_details_x; - break; - case BOTTOM: - /* this is y-channel on the right of the tile in the same layer */ - chan_x = sb_loc.x; - chan_y = sb_loc.y; - chan_type = e_rr_type::CHANY; - chan_layer = sb_loc.layer_num; - return chan_details_y; - break; - case LEFT: - /* this is x-channel on top of the tile in the same layer*/ - chan_x = sb_loc.x; - chan_y = sb_loc.y; - chan_type = e_rr_type::CHANX; - chan_layer = sb_loc.layer_num; - return chan_details_x; - break; - case ABOVE: - /* this is x-channel and y-channel on the same tile location in layer above the current layer */ - chan_x = sb_loc.x; - chan_y = sb_loc.y; - chan_layer = sb_loc.layer_num + 1; - chan_type = (dest_side == RIGHT || dest_side == LEFT) ? e_rr_type::CHANX : e_rr_type::CHANY; - return (dest_side == RIGHT || dest_side == LEFT) ? chan_details_x : chan_details_y; - break; - case UNDER: - /* this is x-channel and y-channel on the same tile location in layer under the current layer */ - chan_x = sb_loc.x; - chan_y = sb_loc.y; - chan_layer = sb_loc.layer_num - 1; - chan_type = (dest_side == RIGHT || dest_side == LEFT) ? e_rr_type::CHANX : e_rr_type::CHANY; - return (dest_side == RIGHT || dest_side == LEFT) ? chan_details_x : chan_details_y; - break; - default: - VPR_FATAL_ERROR(VPR_ERROR_ARCH, "index_into_correct_chan: unknown side specified: %d\n", src_side); - break; - } - VTR_ASSERT(false); - return chan_details_x; //Unreachable -} - -static bool coords_out_of_bounds(const DeviceGrid& grid, int x_coord, int y_coord, int layer_coord, e_rr_type chan_type) { - bool result = true; - - /* the layer that channel is located at must be legal regardless of chan_type*/ - if (layer_coord < 0 || layer_coord > (int)grid.get_num_layers()) { - return result; - } - - if (e_rr_type::CHANX == chan_type) { - /* there is no x-channel at x=0 */ - if (x_coord <= 0 || x_coord >= int(grid.width()) - 1 || y_coord < 0 || y_coord >= int(grid.height()) - 1) { - result = true; - } else { - result = false; - } - } else if (e_rr_type::CHANY == chan_type) { - /* there is no y-channel at y=0 */ - if (x_coord < 0 || x_coord >= int(grid.width()) - 1 || y_coord <= 0 || y_coord >= int(grid.height()) - 1) { - result = true; - } else { - result = false; - } - - } else { - VPR_FATAL_ERROR(VPR_ERROR_ARCH, "coords_out_of_bounds(): illegal channel type %d\n", chan_type); - } - return result; -} - /* adjusts the destination wire calculated from a permutation formula to account for negative indices, * source wire set offset, and modulo by destination wire set size * */ diff --git a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h index b8c526e8c06..e8c9e654724 100644 --- a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h +++ b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h @@ -54,6 +54,19 @@ bool sb_not_here(const DeviceGrid& grid, e_sb_location sb_location, const t_specified_loc& specified_loc = t_specified_loc()); +/** + * @brief finds the correct channel (x or y), and the coordinates to index into it based on the + * specified tile coordinates (x,y,layer) and the switch block side. + * + * @param sb_loc Coordinates of the switch blocks + * @param src_side The side of switch block where the routing channels segment is located at. + * @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_loc Coordinate of the indexed routing channel segment. To be filled by this function. + * @param chan_type The type of the indexed routing channel segment. To be filled by this function. + * + * @return returns the type of channel that we are indexing into (ie, CHANX or CHANY) and channel coordinates and type + */ const t_chan_details& index_into_correct_chan(const t_physical_tile_loc& sb_loc, e_side src_side, const t_chan_details& chan_details_x, @@ -61,6 +74,13 @@ const t_chan_details& index_into_correct_chan(const t_physical_tile_loc& sb_loc, t_physical_tile_loc& chan_loc, e_rr_type& chan_type); +/** + * @brief Check whether a specific switch block location is valid within the device grid + * @param loc Coordinates of the location to be evaluated. + * @param chan_type Routing channel type (CHANX or CHANY), required since device perimeter does not have certain channels + * + * @return True if the given location is outside the device grid, false otherwise. + */ bool chan_coords_out_of_bounds(const t_physical_tile_loc& loc, e_rr_type chan_type); std::pair count_wire_type_sizes(const t_chan_details& chan_details_x, From 44666fe138cba2d1eae09d42e444179bdfd825c9 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Wed, 10 Sep 2025 16:52:20 -0400 Subject: [PATCH 18/58] update alloc_and_load_inter_die_rr_node_indices() to accept t_bottleneck_link --- .../build_scatter_gathers.cpp | 13 +- .../build_scatter_gathers.h | 2 + .../route/rr_graph_generation/rr_graph.cpp | 24 ++-- .../route/rr_graph_generation/rr_graph2.cpp | 118 +----------------- vpr/src/route/rr_graph_generation/rr_graph2.h | 16 +-- .../rr_graph_generation/rr_node_indices.cpp | 43 ++++--- .../rr_graph_generation/rr_node_indices.h | 7 +- ...witchblock_scatter_gather_common_utils.cpp | 2 +- .../3d_SB_inter_die_stratixiv_arch.timing.xml | 48 ------- 9 files changed, 48 insertions(+), 225 deletions(-) diff --git a/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp b/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp index acfadeb8329..4e5325625ae 100644 --- a/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp +++ b/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp @@ -140,7 +140,6 @@ std::vector alloc_and_load_scatter_gather_connections(const s scatter_loc.y = gather_loc.y + sg_link.y_offset; scatter_loc.layer_num = gather_loc.layer_num + sg_link.z_offset; - index_to_correct_channels(sg_pattern.gather_pattern, gather_loc, chan_details_x, chan_details_y, gather_channels); index_to_correct_channels(sg_pattern.scatter_pattern, scatter_loc, chan_details_x, chan_details_y, scatter_channels); @@ -172,18 +171,18 @@ std::vector alloc_and_load_scatter_gather_connections(const s gather_wire_candidates.size(), scatter_wire_candidates.size()); + bottleneck_fanin = std::min(bottleneck_fanin, gather_wire_candidates.size()); + bottleneck_fanout = std::min(bottleneck_fanout, scatter_wire_candidates.size()); - if (bottleneck_fanin > gather_wire_candidates.size()) { - bottleneck_fanin = gather_wire_candidates.size(); - } - if (bottleneck_fanout > scatter_wire_candidates.size()) { - bottleneck_fanout = scatter_wire_candidates.size(); + if (bottleneck_fanin == 0 || bottleneck_fanout == 0) { + continue; } - for (int i_bottleneck = 0, i_s = 0, i_g = 0; i_bottleneck < sg_loc_info.num; i_bottleneck++) { t_bottleneck_link bottleneck_link; + bottleneck_link.gather_loc = gather_loc; + bottleneck_link.scatter_loc = scatter_loc; bottleneck_link.gather_fanin_connections.reserve(bottleneck_fanin); bottleneck_link.scatter_fanout_connections.reserve(bottleneck_fanout); diff --git a/vpr/src/route/rr_graph_generation/build_scatter_gathers.h b/vpr/src/route/rr_graph_generation/build_scatter_gathers.h index a8df647652a..3de644be45f 100644 --- a/vpr/src/route/rr_graph_generation/build_scatter_gathers.h +++ b/vpr/src/route/rr_graph_generation/build_scatter_gathers.h @@ -19,6 +19,8 @@ struct t_sg_candidate { }; struct t_bottleneck_link { + t_physical_tile_loc gather_loc; + t_physical_tile_loc scatter_loc; std::vector gather_fanin_connections; std::vector scatter_fanout_connections; }; diff --git a/vpr/src/route/rr_graph_generation/rr_graph.cpp b/vpr/src/route/rr_graph_generation/rr_graph.cpp index e02d63362eb..c116c9b0599 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph.cpp +++ b/vpr/src/route/rr_graph_generation/rr_graph.cpp @@ -1195,13 +1195,6 @@ static void build_rr_graph(e_graph_type graph_type, grid, inter_cluster_prog_rr, switchblocks, nodes_per_chan, directionality, switchpoint_rng); - - alloc_and_load_scatter_gather_connections(scatter_gather_patterns, - inter_cluster_prog_rr, - chan_details_x, chan_details_y, - nodes_per_chan); - - } else { if (directionality == BI_DIRECTIONAL) { switch_block_conn = alloc_and_load_switch_block_conn(&nodes_per_chan, sb_type, Fs); @@ -1227,17 +1220,18 @@ 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. - if (grid.get_num_layers() > 1 && sb_type == CUSTOM) { - // 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); + const std::vector bottleneck_links = alloc_and_load_scatter_gather_connections(scatter_gather_patterns, + inter_cluster_prog_rr, + chan_details_x, chan_details_y, + nodes_per_chan); + + // Check whether RR graph need to allocate new nodes for 3D connections. + // To avoid wasting memory, the data structures are only allocated if we have more than one die in device grid. + if (grid.get_num_layers() > 1) { // Allocate new nodes in each switchblocks - alloc_and_load_inter_die_rr_node_indices(device_ctx.rr_graph_builder, grid, extra_nodes_per_switchblock, &num_rr_nodes); + alloc_and_load_inter_die_rr_node_indices(device_ctx.rr_graph_builder, bottleneck_links, &num_rr_nodes); device_ctx.rr_graph_builder.resize_nodes(num_rr_nodes); } diff --git a/vpr/src/route/rr_graph_generation/rr_graph2.cpp b/vpr/src/route/rr_graph_generation/rr_graph2.cpp index bcc4dd1e5a0..2b87643acdb 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph2.cpp +++ b/vpr/src/route/rr_graph_generation/rr_graph2.cpp @@ -132,42 +132,6 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, t_rr_edge_info_set& rr_edges_to_create, t_rr_edge_info_set& des_3d_rr_edges_to_create); -/** - * @brief checks if a specific switch block edge is crossing any layer to create 3D custom switch blocks - * - * @param src_side switch block edge source side - * @param dest_side switch block edge destination side - * - * @return true if the connection going to another layer, false otherwise. - */ -static bool is_sb_conn_layer_crossing(e_side src_side, e_side dest_side); - -/** - * @brief finds corresponding RR nodes for a 3D SB edge and fill 3D custom switch block information (offset to correct extra CHANX nodes, source tracks, ..) - * - * @param rr_graph_builder RRGraphBuilder data structure which allows data modification on a routing resource graph - * @param x x-coordinate of both src and dest wires - * @param y y-coordinate of both src and dest wires - * @param from_wire from wire index within channel width - * @param from_wire_layer from wire layer-coordinate - * @param from_wire_type from wire type (CHANX/CHANY) - * @param to_wire to wire index within channel width - * @param to_wire_layer to wire layer-coordinate - * @param to_wire_type to wire type (CHANX/CHANY) - * @param curr_switchblocks_offset number of extra nodes that has already been added to the current switch block - * - * @ returns whether both source track RR node and destination RR node exist - */ -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 int vpr_to_phy_track(const int itrack, const int chan_num, const int seg_num, @@ -1036,84 +1000,6 @@ void dump_track_to_pin_map(t_track_to_pin_lookup& track_to_pin_map, } } -static bool is_sb_conn_layer_crossing(e_side src_side, e_side dest_side) { - if (src_side < NUM_2D_SIDES && dest_side < NUM_2D_SIDES) { - return false; - } - - if (src_side == dest_side) { - return false; - } - - 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) { - 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); - - if (from_inode && to_inode) { - return true; - } - - return false; -} - -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) { - 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 (int layer = 0; layer < (int)grid_ctx.get_num_layers(); layer++) { - - int num_of_3d_conn = 0; - 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; - } - - 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++; - } - } - } - } - } - extra_nodes_per_switchblocks[x][y] += ((num_of_3d_conn + custom_3d_sb_fanin_fanout - 1) / custom_3d_sb_fanin_fanout); - } - } - } - return extra_nodes_per_switchblocks; -} - int get_track_to_pins(RRGraphBuilder& rr_graph_builder, int layer, int seg, @@ -1124,11 +1010,11 @@ int get_track_to_pins(RRGraphBuilder& rr_graph_builder, t_rr_edge_info_set& rr_edges_to_create, const t_track_to_pin_lookup& track_to_pin_lookup, const t_chan_seg_details* seg_details, - enum e_rr_type chan_type, + e_rr_type chan_type, int chan_length, int wire_to_ipin_switch, int wire_to_pin_between_dice_switch, - enum e_directionality directionality) { + e_directionality directionality) { /* * Adds the fan-out edges from wire segment at (chan, seg, track) to adjacent * blocks along the wire's length diff --git a/vpr/src/route/rr_graph_generation/rr_graph2.h b/vpr/src/route/rr_graph_generation/rr_graph2.h index 87c3024f352..644f0ef202e 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph2.h +++ b/vpr/src/route/rr_graph_generation/rr_graph2.h @@ -11,18 +11,6 @@ /******************* 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. - * - * @param sb_conn_map switch block permutation map - * @param rr_graph_builder RRGraphBuilder data structure which allows data modification on a routing resource graph - * - * @return number of die-crossing connection for each unique (x, y) location within the grid ([0..grid.width-1][0..grid.height-1]) - */ -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); - std::vector alloc_and_load_seg_details(int* max_chan_width, const int max_len, const std::vector& segment_inf, @@ -113,11 +101,11 @@ int get_track_to_pins(RRGraphBuilder& rr_graph_builder, t_rr_edge_info_set& rr_edges_to_create, const t_track_to_pin_lookup& track_to_pin_lookup, const t_chan_seg_details* seg_details, - enum e_rr_type chan_type, + e_rr_type chan_type, int chan_length, int wire_to_ipin_switch, int wire_to_pin_between_dice_switch, - enum e_directionality directionality); + e_directionality directionality); int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, const int layer, 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 5820d237ebc..15969382df8 100644 --- a/vpr/src/route/rr_graph_generation/rr_node_indices.cpp +++ b/vpr/src/route/rr_graph_generation/rr_node_indices.cpp @@ -1,6 +1,7 @@ #include "rr_node_indices.h" +#include "build_scatter_gathers.h" #include "describe_rr_node.h" #include "globals.h" #include "physical_types.h" @@ -323,8 +324,7 @@ void alloc_and_load_rr_node_indices(RRGraphBuilder& rr_graph_builder, } void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, - const DeviceGrid& grid, - const vtr::NdMatrix& extra_nodes_per_switchblock, + const std::vector& bottleneck_links, int* index) { // In case of multi-die FPGAs, we add extra nodes of type CHANZ to // support inter-die communication coming from switch blocks (connection between two tracks in different layers) @@ -333,32 +333,35 @@ void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, // 2) xhigh == xlow, yhigh == ylow // 3) ptc = [0:number_of_connection-1] // 4) direction = NONE - const auto& device_ctx = g_vpr_ctx.device(); + const DeviceContext& device_ctx = g_vpr_ctx.device(); + const DeviceGrid& grid = device_ctx.grid; - for (size_t layer = 0; layer < grid.get_num_layers(); layer++) { - // Skip the current die if architecture file specifies that it doesn't have global resource routing - if (!device_ctx.inter_cluster_prog_routing_resources.at(layer)) { - continue; + vtr::NdMatrix chanz_nodes_per_loc{{grid.width(), grid.height()}, 0}; + + for (const t_bottleneck_link& bottleneck_link : bottleneck_links) { + const t_physical_tile_loc& src_loc = bottleneck_link.gather_loc; + const t_physical_tile_loc& dst_loc = bottleneck_link.scatter_loc; + + if (src_loc.x == dst_loc.x && src_loc.y == dst_loc.y) { + VTR_ASSERT_SAFE(src_loc.layer_num != dst_loc.layer_num); + chanz_nodes_per_loc[src_loc.x][src_loc.y]++; } + } - for (size_t y = 0; y < grid.height() - 1; ++y) { - for (size_t x = 1; x < grid.width() - 1; ++x) { - // how many track-to-track connection go from current layer to other layers - int conn_count = extra_nodes_per_switchblock[x][y]; + for (size_t x = 0; x < grid.width(); x++) { + for (size_t y = 0; y < grid.height(); y++) { + const int num_chanz_nodes = chanz_nodes_per_loc[x][y]; - // skip if no connection is required - if (conn_count == 0) { - continue; - } + // reserve extra nodes for inter-die track-to-track connection + for (size_t layer = 0; layer < grid.get_num_layers(); layer++) { + rr_graph_builder.node_lookup().reserve_nodes(layer, x, y, e_rr_type::CHANZ, num_chanz_nodes); - // reserve extra nodes for inter-die track-to-track connection - rr_graph_builder.node_lookup().reserve_nodes(layer, x, y, e_rr_type::CHANZ, conn_count); - for (int rr_node_offset = 0; rr_node_offset < conn_count; rr_node_offset++) { - RRNodeId inode = rr_graph_builder.node_lookup().find_node(layer, x, y, e_rr_type::CHANZ, rr_node_offset); + for (int track_num = 0; track_num < num_chanz_nodes; track_num++) { + RRNodeId inode = rr_graph_builder.node_lookup().find_node(layer, x, y, e_rr_type::CHANZ, track_num); if (!inode) { inode = RRNodeId(*index); ++(*index); - rr_graph_builder.node_lookup().add_node(inode, layer, x, y, e_rr_type::CHANZ, rr_node_offset); + rr_graph_builder.node_lookup().add_node(inode, layer, x, y, e_rr_type::CHANZ, track_num); } } } diff --git a/vpr/src/route/rr_graph_generation/rr_node_indices.h b/vpr/src/route/rr_graph_generation/rr_node_indices.h index 91ddab2fcc9..afcd20c78ae 100644 --- a/vpr/src/route/rr_graph_generation/rr_node_indices.h +++ b/vpr/src/route/rr_graph_generation/rr_node_indices.h @@ -8,6 +8,8 @@ #include "rr_graph_utils.h" #include "clustered_netlist_fwd.h" +struct t_bottleneck_link; + /** * @brief Allocates and populates data structures for efficient rr_node index lookups. * @@ -32,15 +34,12 @@ void alloc_and_load_rr_node_indices(RRGraphBuilder& rr_graph_builder, * @brief Allocates extra nodes within the RR graph to support 3D custom switch blocks for multi-die FPGAs * * @param rr_graph_builder RRGraphBuilder data structure which allows data modification on a routing resource graph - * @param nodes_per_chan number of tracks per channel (x, y) - * @param grid The device grid representing the physical layout of tiles in the FPGA fabric. * @param extra_nodes_per_switchblock keeps how many extra length-0 CHANX node is required for each unique (x,y) location within the grid. * Number of these extra nodes are exactly the same for all layers. Hence, we only keep it for one layer. ([0..grid.width-1][0..grid.height-1) * @param index Pointer to the global RR node index counter; incremented as new RR nodes are assigned. */ void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, - const DeviceGrid& grid, - const vtr::NdMatrix& extra_nodes_per_switchblock, + const std::vector& bottleneck_links, int* index); /** diff --git a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp index 9c758f4065e..6f43a2392e4 100644 --- a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp +++ b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp @@ -353,7 +353,7 @@ bool chan_coords_out_of_bounds(const t_physical_tile_loc& loc, e_rr_type chan_ty const int grid_layers = grid.get_num_layers(); // the layer that channel is located at must be legal regardless of chan_type - if (loc.layer_num < 0 || loc.layer_num > grid_layers) { + if (loc.layer_num < 0 || loc.layer_num >= grid_layers) { return true; } diff --git a/vtr_flow/arch/multi_die/stratixiv_3d/3d_SB_inter_die_stratixiv_arch.timing.xml b/vtr_flow/arch/multi_die/stratixiv_3d/3d_SB_inter_die_stratixiv_arch.timing.xml index 8f8691b7cf5..7a11f92487e 100644 --- a/vtr_flow/arch/multi_die/stratixiv_3d/3d_SB_inter_die_stratixiv_arch.timing.xml +++ b/vtr_flow/arch/multi_die/stratixiv_3d/3d_SB_inter_die_stratixiv_arch.timing.xml @@ -48253,54 +48253,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 9ea5a4defb9960f26b4cae201aabbb243d6dedaf Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Wed, 10 Sep 2025 18:07:14 -0400 Subject: [PATCH 19/58] store 3d t_bottleneck_link per x/y location --- .../build_scatter_gathers.cpp | 22 ++++++++++++++-- .../build_scatter_gathers.h | 3 ++- .../route/rr_graph_generation/rr_graph.cpp | 12 ++++----- .../rr_graph_generation/rr_node_indices.cpp | 25 ++++++------------- .../rr_graph_generation/rr_node_indices.h | 2 +- 5 files changed, 37 insertions(+), 27 deletions(-) diff --git a/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp b/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp index 4e5325625ae..53fc343131b 100644 --- a/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp +++ b/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp @@ -104,7 +104,8 @@ std::vector alloc_and_load_scatter_gather_connections(const s const std::vector& inter_cluster_rr, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, - const t_chan_width& nodes_per_chan) { + const t_chan_width& nodes_per_chan, + vtr::NdMatrix, 2>& interdie_3d_links) { const DeviceGrid& grid = g_vpr_ctx.device().grid; std::vector gather_channels; @@ -115,6 +116,11 @@ std::vector alloc_and_load_scatter_gather_connections(const s std::vector bottleneck_links; + interdie_3d_links.clear(); + if (grid.get_num_layers() > 1) { + interdie_3d_links.resize({grid.width(), grid.height()}); + } + const auto [wire_type_sizes_x, wire_type_sizes_y] = count_wire_type_sizes(chan_details_x, chan_details_y, nodes_per_chan); for (const t_scatter_gather_pattern& sg_pattern : scatter_gather_patterns) { @@ -178,6 +184,13 @@ std::vector alloc_and_load_scatter_gather_connections(const s continue; } + const bool is_3d_link = (gather_loc.layer_num != scatter_loc.layer_num); + if (is_3d_link) { + interdie_3d_links[gather_loc.x][gather_loc.y].reserve(interdie_3d_links[gather_loc.x][gather_loc.y].size() + sg_loc_info.num); + } else { + bottleneck_links.reserve(bottleneck_links.size() + sg_loc_info.num); + } + for (int i_bottleneck = 0, i_s = 0, i_g = 0; i_bottleneck < sg_loc_info.num; i_bottleneck++) { t_bottleneck_link bottleneck_link; @@ -196,7 +209,12 @@ std::vector alloc_and_load_scatter_gather_connections(const s i_s = (i_s + 1) % bottleneck_fanout; } - bottleneck_links.push_back(std::move(bottleneck_link)); + if (is_3d_link) { + interdie_3d_links[gather_loc.x][gather_loc.y].push_back(std::move(bottleneck_link)); + } else { + bottleneck_links.push_back(std::move(bottleneck_link)); + } + } } diff --git a/vpr/src/route/rr_graph_generation/build_scatter_gathers.h b/vpr/src/route/rr_graph_generation/build_scatter_gathers.h index 3de644be45f..6e0a28e6356 100644 --- a/vpr/src/route/rr_graph_generation/build_scatter_gathers.h +++ b/vpr/src/route/rr_graph_generation/build_scatter_gathers.h @@ -29,4 +29,5 @@ std::vector alloc_and_load_scatter_gather_connections(const s const std::vector& inter_cluster_rr, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, - const t_chan_width& nodes_per_chan); \ No newline at end of file + const t_chan_width& nodes_per_chan, + vtr::NdMatrix, 2>& interdie_3d_links); \ No newline at end of file diff --git a/vpr/src/route/rr_graph_generation/rr_graph.cpp b/vpr/src/route/rr_graph_generation/rr_graph.cpp index c116c9b0599..6daea0e15ec 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph.cpp +++ b/vpr/src/route/rr_graph_generation/rr_graph.cpp @@ -1222,16 +1222,18 @@ static void build_rr_graph(e_graph_type graph_type, } // END SB LOOKUP + vtr::NdMatrix, 2> interdie_3d_links; const std::vector bottleneck_links = alloc_and_load_scatter_gather_connections(scatter_gather_patterns, inter_cluster_prog_rr, chan_details_x, chan_details_y, - nodes_per_chan); + nodes_per_chan, + interdie_3d_links); // Check whether RR graph need to allocate new nodes for 3D connections. // To avoid wasting memory, the data structures are only allocated if we have more than one die in device grid. if (grid.get_num_layers() > 1) { // Allocate new nodes in each switchblocks - alloc_and_load_inter_die_rr_node_indices(device_ctx.rr_graph_builder, bottleneck_links, &num_rr_nodes); + alloc_and_load_inter_die_rr_node_indices(device_ctx.rr_graph_builder, interdie_3d_links, &num_rr_nodes); device_ctx.rr_graph_builder.resize_nodes(num_rr_nodes); } @@ -2090,12 +2092,10 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder continue; } - // In multi-die FPGAs with track-to-track connections between layers, we need to load newly added length-0 CHANX nodes + // In multi-die FPGAs with track-to-track connections between layers, we need to load CHANZ 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()); + if (grid.get_num_layers() > 1) { build_inter_die_custom_sb_rr_chan(rr_graph_builder, layer, i, j, CHANX_COST_INDEX_START, chan_width, chan_details_x); } 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 15969382df8..6410574f4e3 100644 --- a/vpr/src/route/rr_graph_generation/rr_node_indices.cpp +++ b/vpr/src/route/rr_graph_generation/rr_node_indices.cpp @@ -324,7 +324,7 @@ void alloc_and_load_rr_node_indices(RRGraphBuilder& rr_graph_builder, } void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, - const std::vector& bottleneck_links, + const vtr::NdMatrix, 2>& interdie_3d_links, int* index) { // In case of multi-die FPGAs, we add extra nodes of type CHANZ to // support inter-die communication coming from switch blocks (connection between two tracks in different layers) @@ -332,36 +332,27 @@ void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, // 1) type = CHANZ // 2) xhigh == xlow, yhigh == ylow // 3) ptc = [0:number_of_connection-1] - // 4) direction = NONE const DeviceContext& device_ctx = g_vpr_ctx.device(); const DeviceGrid& grid = device_ctx.grid; - vtr::NdMatrix chanz_nodes_per_loc{{grid.width(), grid.height()}, 0}; - - for (const t_bottleneck_link& bottleneck_link : bottleneck_links) { - const t_physical_tile_loc& src_loc = bottleneck_link.gather_loc; - const t_physical_tile_loc& dst_loc = bottleneck_link.scatter_loc; - - if (src_loc.x == dst_loc.x && src_loc.y == dst_loc.y) { - VTR_ASSERT_SAFE(src_loc.layer_num != dst_loc.layer_num); - chanz_nodes_per_loc[src_loc.x][src_loc.y]++; - } - } - for (size_t x = 0; x < grid.width(); x++) { for (size_t y = 0; y < grid.height(); y++) { - const int num_chanz_nodes = chanz_nodes_per_loc[x][y]; + const int num_chanz_nodes = interdie_3d_links[x][y].size(); // reserve extra nodes for inter-die track-to-track connection for (size_t layer = 0; layer < grid.get_num_layers(); layer++) { rr_graph_builder.node_lookup().reserve_nodes(layer, x, y, e_rr_type::CHANZ, num_chanz_nodes); + } - for (int track_num = 0; track_num < num_chanz_nodes; track_num++) { + for (int track_num = 0; track_num < num_chanz_nodes; track_num++) { + for (size_t layer = 0; layer < grid.get_num_layers(); layer++) { RRNodeId inode = rr_graph_builder.node_lookup().find_node(layer, x, y, e_rr_type::CHANZ, track_num); if (!inode) { inode = RRNodeId(*index); - ++(*index); rr_graph_builder.node_lookup().add_node(inode, layer, x, y, e_rr_type::CHANZ, track_num); + if (layer == 0) { + ++(*index); + } } } } diff --git a/vpr/src/route/rr_graph_generation/rr_node_indices.h b/vpr/src/route/rr_graph_generation/rr_node_indices.h index afcd20c78ae..051eac0b395 100644 --- a/vpr/src/route/rr_graph_generation/rr_node_indices.h +++ b/vpr/src/route/rr_graph_generation/rr_node_indices.h @@ -39,7 +39,7 @@ void alloc_and_load_rr_node_indices(RRGraphBuilder& rr_graph_builder, * @param index Pointer to the global RR node index counter; incremented as new RR nodes are assigned. */ void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, - const std::vector& bottleneck_links, + const vtr::NdMatrix, 2>& interdie_3d_links, int* index); /** From 0932ddb1a59a095ff06a1068c5dada1bdcdefba2 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Wed, 10 Sep 2025 18:28:03 -0400 Subject: [PATCH 20/58] add chanz nodes based on interdie 3d links (SG) --- .../route/rr_graph_generation/rr_graph.cpp | 42 +++++++++++++------ 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/vpr/src/route/rr_graph_generation/rr_graph.cpp b/vpr/src/route/rr_graph_generation/rr_graph.cpp index 6daea0e15ec..4e9e4f50ff6 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph.cpp +++ b/vpr/src/route/rr_graph_generation/rr_graph.cpp @@ -193,6 +193,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder const t_track_to_pin_lookup& track_to_pin_lookup_x, const t_track_to_pin_lookup& track_to_pin_lookup_y, const t_pin_to_track_lookup& opin_to_track_map, + const vtr::NdMatrix, 2>& interdie_3d_links, const vtr::NdMatrix, 3>& switch_block_conn, t_sb_connection_map* sb_conn_map, const DeviceGrid& grid, @@ -489,9 +490,9 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, * @param chan_details_x channel-x details (length, start and end points, ...) */ static void build_inter_die_custom_sb_rr_chan(RRGraphBuilder& rr_graph_builder, - const int layer, const int x_coord, const int y_coord, + const std::vector& interdie_3d_links, const int const_index_offset, const t_chan_width& nodes_per_chan, const t_chan_details& chan_details_x); @@ -1323,6 +1324,7 @@ static void build_rr_graph(e_graph_type graph_type, chan_details_x, chan_details_y, track_to_pin_lookup_x, track_to_pin_lookup_y, opin_to_track_map, + interdie_3d_links, switch_block_conn, sb_conn_map, grid, Fs, unidir_sb_pattern, Fc_out, Fc_xofs, Fc_yofs, nodes_per_chan, @@ -1953,6 +1955,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder const t_track_to_pin_lookup& track_to_pin_lookup_x, const t_track_to_pin_lookup& track_to_pin_lookup_y, const t_pin_to_track_lookup& opin_to_track_map, + const vtr::NdMatrix, 2>& interdie_3d_links, const vtr::NdMatrix, 3>& switch_block_conn, t_sb_connection_map* sb_conn_map, const DeviceGrid& grid, @@ -2085,6 +2088,15 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder for (size_t i = 0; i < grid.width() - 1; ++i) { for (size_t j = 0; j < grid.height() - 1; ++j) { + + // In multi-die FPGAs with track-to-track connections between layers, we need to load CHANZ 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) { + build_inter_die_custom_sb_rr_chan(rr_graph_builder, i, j, interdie_3d_links[i][j], + CHANX_COST_INDEX_START, chan_width, chan_details_x); + } + for (int layer = 0; layer < (int)grid.get_num_layers(); ++layer) { 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 @@ -2092,14 +2104,6 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder continue; } - // In multi-die FPGAs with track-to-track connections between layers, we need to load CHANZ 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) { - build_inter_die_custom_sb_rr_chan(rr_graph_builder, layer, i, j, CHANX_COST_INDEX_START, chan_width, - chan_details_x); - } - if (i > 0) { int tracks_per_chan = ((is_global_graph) ? 1 : chan_width.x_list[j]); build_rr_chan(rr_graph_builder, layer, i, j, e_rr_type::CHANX, track_to_pin_lookup_x, sb_conn_map, @@ -3117,14 +3121,15 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, } static void build_inter_die_custom_sb_rr_chan(RRGraphBuilder& rr_graph_builder, - const int layer, const int x_coord, const int y_coord, + const std::vector& interdie_3d_links, const int const_index_offset, const t_chan_width& nodes_per_chan, const t_chan_details& chan_details_x) { auto& mutable_device_ctx = g_vpr_ctx.mutable_device(); const t_chan_seg_details* seg_details = chan_details_x[x_coord][y_coord].data(); + const size_t num_layers = g_vpr_ctx.device().grid.get_num_layers(); // 3D connections within the switch blocks use some CHANZ nodes to allow a single 3D connection to be driven // by multiple tracks in the source layer, and drives multiple tracks in the destination layer. @@ -3142,14 +3147,19 @@ static void build_inter_die_custom_sb_rr_chan(RRGraphBuilder& rr_graph_builder, // Go through allocated nodes until no nodes are found within the RRGraph builder for (int track_num = 0; /*no condition*/; track_num++) { // Try to find a node with the current track_num - RRNodeId node = rr_graph_builder.node_lookup().find_node(layer, x_coord, y_coord, e_rr_type::CHANZ, track_num); + + RRNodeId node = rr_graph_builder.node_lookup().find_node(0, x_coord, y_coord, e_rr_type::CHANZ, track_num); + for (size_t layer = 1; layer < num_layers; layer++) { + VTR_ASSERT(node == rr_graph_builder.node_lookup().find_node(layer, x_coord, y_coord, e_rr_type::CHANZ, track_num)); + } // If the track can't be found, it means we have already processed all tracks if (!node.is_valid()) { + VTR_ASSERT(interdie_3d_links.size() == (size_t)track_num); break; } - rr_graph_builder.set_node_layer(node, layer); + rr_graph_builder.set_node_layer(node, 0); rr_graph_builder.set_node_coordinates(node, x_coord, y_coord, x_coord, y_coord); // TODO: the index doesn't make any sense. We need to an RRIndexedDataId for CHANZ nodes rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(const_index_offset + seg_details[start_track - 1].index())); @@ -3160,7 +3170,13 @@ static void build_inter_die_custom_sb_rr_chan(RRGraphBuilder& rr_graph_builder, rr_graph_builder.set_node_type(node, e_rr_type::CHANZ); rr_graph_builder.set_node_track_num(node, track_num); - rr_graph_builder.set_node_direction(node, Direction::NONE); + if (interdie_3d_links[track_num].scatter_loc.layer_num > interdie_3d_links[track_num].gather_loc.layer_num) { + rr_graph_builder.set_node_direction(node, Direction::INC); + } else { + VTR_ASSERT_SAFE(interdie_3d_links[track_num].scatter_loc.layer_num < interdie_3d_links[track_num].gather_loc.layer_num); + rr_graph_builder.set_node_direction(node, Direction::DEC); + } + } } From 0253916802d2ca0fa37af9f3335f02b082a96fc9 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Wed, 10 Sep 2025 19:10:05 -0400 Subject: [PATCH 21/58] remove custom 3d switch block stuff from rr graph --- vpr/src/base/read_options.cpp | 6 - vpr/src/base/read_options.h | 1 - vpr/src/base/setup_vpr.cpp | 1 - vpr/src/base/vpr_types.h | 2 - .../route/rr_graph_generation/rr_graph.cpp | 138 +++++++++--------- .../route/rr_graph_generation/rr_graph2.cpp | 118 ++------------- vpr/src/route/rr_graph_generation/rr_graph2.h | 6 +- 7 files changed, 83 insertions(+), 189 deletions(-) diff --git a/vpr/src/base/read_options.cpp b/vpr/src/base/read_options.cpp index 4164705f481..1c23689388b 100644 --- a/vpr/src/base/read_options.cpp +++ b/vpr/src/base/read_options.cpp @@ -2795,12 +2795,6 @@ argparse::ArgumentParser create_arg_parser(const std::string& prog_name, t_optio .help("Controls the verbosity of routing's output. Higher values produce more output (useful for debugging routing problems)") .default_value("1") .show_in(argparse::ShowIn::HELP_ONLY); - route_grp.add_argument(args.custom_3d_sb_fanin_fanout, "--custom_3d_sb_fanin_fanout") - .help( - "Specifies the number of tracks that can drive a 3D switch block connection" - "and the number of tracks that can be driven by a 3D switch block connection") - .default_value("1") - .show_in(argparse::ShowIn::HELP_ONLY); auto& route_timing_grp = parser.add_argument_group("timing-driven routing options"); diff --git a/vpr/src/base/read_options.h b/vpr/src/base/read_options.h index 4bd8485dc3f..b396716b094 100644 --- a/vpr/src/base/read_options.h +++ b/vpr/src/base/read_options.h @@ -232,7 +232,6 @@ struct t_options { argparse::ArgValue flat_routing; argparse::ArgValue router_opt_choke_points; argparse::ArgValue route_verbosity; - argparse::ArgValue custom_3d_sb_fanin_fanout; /* Timing-driven router options only */ argparse::ArgValue astar_fac; diff --git a/vpr/src/base/setup_vpr.cpp b/vpr/src/base/setup_vpr.cpp index c63222ff4bc..d855483d5e0 100644 --- a/vpr/src/base/setup_vpr.cpp +++ b/vpr/src/base/setup_vpr.cpp @@ -533,7 +533,6 @@ static void setup_router_opts(const t_options& Options, t_router_opts* RouterOpt RouterOpts->generate_rr_node_overuse_report = Options.generate_rr_node_overuse_report; RouterOpts->flat_routing = Options.flat_routing; RouterOpts->has_choke_point = Options.router_opt_choke_points; - RouterOpts->custom_3d_sb_fanin_fanout = Options.custom_3d_sb_fanin_fanout; RouterOpts->with_timing_analysis = Options.timing_analysis; RouterOpts->verify_route_file_switch_id = Options.verify_route_file_switch_id; diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index 6d012dbe782..85d85906eb2 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -1361,8 +1361,6 @@ struct t_router_opts { bool flat_routing; bool has_choke_point; - int custom_3d_sb_fanin_fanout = 1; - bool with_timing_analysis; /// Whether to verify the switch IDs in the route file with the RR Graph. diff --git a/vpr/src/route/rr_graph_generation/rr_graph.cpp b/vpr/src/route/rr_graph_generation/rr_graph.cpp index 4e9e4f50ff6..e85a1194672 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph.cpp +++ b/vpr/src/route/rr_graph_generation/rr_graph.cpp @@ -205,14 +205,13 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder const t_chan_width& chan_width, const int wire_to_ipin_switch, const int wire_to_pin_between_dice_switch, - const int custom_3d_sb_fanin_fanout, const int delayless_switch, - const enum e_directionality directionality, + const e_directionality directionality, bool* Fc_clipped, const std::vector& directs, const std::vector& clb_to_clb_directs, bool is_global_graph, - const enum e_clock_modeling clock_modeling, + const e_clock_modeling clock_modeling, bool is_flat, const int route_verbosity); @@ -462,7 +461,6 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, const t_track_to_pin_lookup& track_to_pin_lookup, t_sb_connection_map* sb_conn_map, const vtr::NdMatrix, 3>& switch_block_conn, - vtr::NdMatrix& num_of_3d_conns_custom_SB, const int cost_index_offset, const t_chan_width& nodes_per_chan, const DeviceGrid& grid, @@ -472,12 +470,9 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, t_rr_edge_info_set& rr_edges_to_create, - t_rr_edge_info_set& des_3d_rr_edges_to_create, const int wire_to_ipin_switch, const int wire_to_pin_between_dice_switch, - const int custom_3d_sb_fanin_fanout, - const int delayless_switch, - const enum e_directionality directionality); + const e_directionality directionality); /** * @brief builds the extra length-0 CHANX nodes to handle 3D custom switchblocks edges in the RR graph. @@ -489,13 +484,13 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, * @param nodes_per_chan number of tracks per channel (x, y) * @param chan_details_x channel-x details (length, start and end points, ...) */ -static void build_inter_die_custom_sb_rr_chan(RRGraphBuilder& rr_graph_builder, - const int x_coord, - const int y_coord, - const std::vector& interdie_3d_links, - const int const_index_offset, - const t_chan_width& nodes_per_chan, - const t_chan_details& chan_details_x); +static void build_inter_die_3d_rr_chan(RRGraphBuilder& rr_graph_builder, + const int x_coord, + const int y_coord, + const std::vector& interdie_3d_links, + const int const_index_offset, + const t_chan_width& nodes_per_chan, + const t_chan_details& chan_details_x); void uniquify_edges(t_rr_edge_info_set& rr_edges_to_create); @@ -602,7 +597,6 @@ static void build_rr_graph(e_graph_type graph_type, const int global_route_switch, const int wire_to_arch_ipin_switch, const int wire_to_pin_between_dice_switch, - const int custom_3d_sb_fanin_fanout, const int delayless_switch, const float R_minW_nmos, const float R_minW_pmos, @@ -707,7 +701,6 @@ void create_rr_graph(e_graph_type graph_type, det_routing_arch.global_route_switch, det_routing_arch.wire_to_arch_ipin_switch, det_routing_arch.wire_to_arch_ipin_switch_between_dice, - router_opts.custom_3d_sb_fanin_fanout, det_routing_arch.delayless_switch, det_routing_arch.R_minW_nmos, det_routing_arch.R_minW_pmos, @@ -947,7 +940,6 @@ static void build_rr_graph(e_graph_type graph_type, const int global_route_switch, const int wire_to_arch_ipin_switch, const int wire_to_pin_between_dice_switch, - const int custom_3d_sb_fanin_fanout, const int delayless_switch, const float R_minW_nmos, const float R_minW_pmos, @@ -1330,7 +1322,6 @@ static void build_rr_graph(e_graph_type graph_type, nodes_per_chan, wire_to_arch_ipin_switch, wire_to_pin_between_dice_switch, - custom_3d_sb_fanin_fanout, delayless_switch, directionality, &Fc_clipped, @@ -1967,14 +1958,13 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder const t_chan_width& chan_width, const int wire_to_ipin_switch, const int wire_to_pin_between_dice_switch, - const int custom_3d_sb_fanin_fanout, const int delayless_switch, - const enum e_directionality directionality, + const e_directionality directionality, bool* Fc_clipped, const std::vector& directs, const std::vector& clb_to_clb_directs, bool is_global_graph, - const enum e_clock_modeling clock_modeling, + const e_clock_modeling clock_modeling, bool /*is_flat*/, const int route_verbosity) { // We take special care when creating RR graph edges (there are typically many more @@ -2078,13 +2068,7 @@ 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 - vtr::NdMatrix num_of_3d_conns_custom_SB; - if (grid.get_num_layers() > 1 && sb_conn_map != nullptr) { - num_of_3d_conns_custom_SB.resize({grid.width(), grid.height()}, 0); - } - - t_rr_edge_info_set des_3d_rr_edges_to_create; + t_rr_edge_info_set interdie_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) { @@ -2093,8 +2077,8 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder // 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) { - build_inter_die_custom_sb_rr_chan(rr_graph_builder, i, j, interdie_3d_links[i][j], - CHANX_COST_INDEX_START, chan_width, chan_details_x); + build_inter_die_3d_rr_chan(rr_graph_builder, i, j, interdie_3d_links[i][j], + CHANX_COST_INDEX_START, chan_width, chan_details_x); } for (int layer = 0; layer < (int)grid.get_num_layers(); ++layer) { @@ -2108,14 +2092,12 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder int tracks_per_chan = ((is_global_graph) ? 1 : chan_width.x_list[j]); build_rr_chan(rr_graph_builder, layer, i, j, e_rr_type::CHANX, track_to_pin_lookup_x, sb_conn_map, switch_block_conn, - num_of_3d_conns_custom_SB, CHANX_COST_INDEX_START, + CHANX_COST_INDEX_START, chan_width, grid, tracks_per_chan, sblock_pattern, Fs / 3, chan_details_x, chan_details_y, - rr_edges_to_create, des_3d_rr_edges_to_create, + rr_edges_to_create, wire_to_ipin_switch, wire_to_pin_between_dice_switch, - custom_3d_sb_fanin_fanout, - delayless_switch, directionality); //Create the actual CHAN->CHAN edges @@ -2129,14 +2111,12 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder int tracks_per_chan = ((is_global_graph) ? 1 : chan_width.y_list[i]); build_rr_chan(rr_graph_builder, layer, i, j, e_rr_type::CHANY, track_to_pin_lookup_y, sb_conn_map, switch_block_conn, - num_of_3d_conns_custom_SB, CHANX_COST_INDEX_START + num_seg_types_x, + CHANX_COST_INDEX_START + num_seg_types_x, chan_width, grid, tracks_per_chan, sblock_pattern, Fs / 3, chan_details_x, chan_details_y, - rr_edges_to_create, des_3d_rr_edges_to_create, + rr_edges_to_create, wire_to_ipin_switch, wire_to_pin_between_dice_switch, - custom_3d_sb_fanin_fanout, - delayless_switch, directionality); //Create the actual CHAN->CHAN edges @@ -2147,15 +2127,18 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder rr_edges_to_create.clear(); } } + + if (grid.get_num_layers() > 1) { + uniquify_edges(interdie_3d_rr_edges_to_create); + alloc_and_load_edges(rr_graph_builder, interdie_3d_rr_edges_to_create); + num_edges += interdie_3d_rr_edges_to_create.size(); + interdie_3d_rr_edges_to_create.clear(); + } + } } - if (grid.get_num_layers() > 1 && sb_conn_map != nullptr) { - uniquify_edges(des_3d_rr_edges_to_create); - alloc_and_load_edges(rr_graph_builder, des_3d_rr_edges_to_create); - num_edges += des_3d_rr_edges_to_create.size(); - des_3d_rr_edges_to_create.clear(); - } + VTR_LOGV(route_verbosity > 1, "CHAN->CHAN type edge count:%d\n", num_edges); @@ -2939,7 +2922,6 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, const t_track_to_pin_lookup& track_to_pin_lookup, t_sb_connection_map* sb_conn_map, const vtr::NdMatrix, 3>& switch_block_conn, - vtr::NdMatrix& num_of_3d_conns_custom_SB, const int cost_index_offset, const t_chan_width& nodes_per_chan, const DeviceGrid& grid, @@ -2949,12 +2931,9 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, t_rr_edge_info_set& rr_edges_to_create, - t_rr_edge_info_set& des_3d_rr_edges_to_create, const int wire_to_ipin_switch, const int wire_to_pin_between_dice_switch, - const int custom_3d_sb_fanin_fanout, - const int delayless_switch, - const enum e_directionality directionality) { + const e_directionality directionality) { // this function builds both x and y-directed channel segments, so set up our coordinates based on channel type const auto& device_ctx = g_vpr_ctx.device(); @@ -3033,9 +3012,9 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, if (to_seg_details->length() > 0) { get_track_to_tracks(rr_graph_builder, layer, chan_coord, start, track, chan_type, chan_coord, opposite_chan_type, seg_dimension, max_opposite_chan_width, grid, - Fs_per_side, sblock_pattern, num_of_3d_conns_custom_SB, node, rr_edges_to_create, - des_3d_rr_edges_to_create, from_seg_details, to_seg_details, opposite_chan_details, - directionality, custom_3d_sb_fanin_fanout, delayless_switch, + Fs_per_side, sblock_pattern, node, rr_edges_to_create, + from_seg_details, to_seg_details, opposite_chan_details, + directionality, switch_block_conn, sb_conn_map); } } @@ -3054,9 +3033,9 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, if (to_seg_details->length() > 0) { get_track_to_tracks(rr_graph_builder, layer, chan_coord, start, track, chan_type, chan_coord + 1, opposite_chan_type, seg_dimension, max_opposite_chan_width, grid, - Fs_per_side, sblock_pattern, num_of_3d_conns_custom_SB, node, rr_edges_to_create, - des_3d_rr_edges_to_create, from_seg_details, to_seg_details, opposite_chan_details, - directionality, custom_3d_sb_fanin_fanout, delayless_switch, switch_block_conn, sb_conn_map); + Fs_per_side, sblock_pattern, node, rr_edges_to_create, + from_seg_details, to_seg_details, opposite_chan_details, + directionality, switch_block_conn, sb_conn_map); } } @@ -3085,9 +3064,9 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, if (to_seg_details->length() > 0) { get_track_to_tracks(rr_graph_builder, layer, chan_coord, start, track, chan_type, target_seg, chan_type, seg_dimension, max_chan_width, grid, - Fs_per_side, sblock_pattern, num_of_3d_conns_custom_SB, node, rr_edges_to_create, - des_3d_rr_edges_to_create, from_seg_details, to_seg_details, from_chan_details, - directionality, custom_3d_sb_fanin_fanout, delayless_switch, + Fs_per_side, sblock_pattern, node, rr_edges_to_create, + from_seg_details, to_seg_details, from_chan_details, + directionality, switch_block_conn, sb_conn_map); } } @@ -3120,13 +3099,40 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, } } -static void build_inter_die_custom_sb_rr_chan(RRGraphBuilder& rr_graph_builder, - const int x_coord, - const int y_coord, - const std::vector& interdie_3d_links, - const int const_index_offset, - const t_chan_width& nodes_per_chan, - const t_chan_details& chan_details_x) { +static void add_interdie_3d_edges(RRGraphBuilder& rr_graph_builder, + int x_coord, + int y_coord, + const std::vector& interdie_3d_links, + t_rr_edge_info_set& interdie_3d_rr_edges_to_create) { + + const RRSpatialLookup& node_lookup = rr_graph_builder.node_lookup(); + const int num_tracks = interdie_3d_links.size(); + + for (int track = 0; track < num_tracks; track++) { + const t_bottleneck_link& link = interdie_3d_links[track]; + VTR_ASSERT_SAFE(x_coord == link.gather_loc.x && y_coord == link.gather_loc.y); + VTR_ASSERT_SAFE(x_coord == link.scatter_loc.x && y_coord == link.scatter_loc.y); + + RRNodeId chanz_node = node_lookup.find_node(0, x_coord, y_coord, e_rr_type::CHANZ, track); + + for (const t_sg_candidate& gather_wire : link.gather_fanin_connections) { + const t_physical_tile_loc& chan_loc = gather_wire.chan_loc.location; + e_rr_type chan_type = gather_wire.chan_loc.chan_type; + + RRNodeId gather_node = node_lookup.find_node(chan_loc.layer_num, chan_loc.x, chan_loc.y, chan_type, gather_wire.wire_switchpoint.wire); + + + } + } +} + +static void build_inter_die_3d_rr_chan(RRGraphBuilder& rr_graph_builder, + const int x_coord, + const int y_coord, + const std::vector& interdie_3d_links, + const int const_index_offset, + const t_chan_width& nodes_per_chan, + const t_chan_details& chan_details_x) { auto& mutable_device_ctx = g_vpr_ctx.mutable_device(); const t_chan_seg_details* seg_details = chan_details_x[x_coord][y_coord].data(); const size_t num_layers = g_vpr_ctx.device().grid.get_num_layers(); diff --git a/vpr/src/route/rr_graph_generation/rr_graph2.cpp b/vpr/src/route/rr_graph_generation/rr_graph2.cpp index 2b87643acdb..d7950573892 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph2.cpp +++ b/vpr/src/route/rr_graph_generation/rr_graph2.cpp @@ -88,15 +88,11 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, const int to_y, const e_rr_type to_chan_type, const int switch_override, - const int custom_3d_sb_fanin_fanout, - const int delayless_switch, 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); -/* +/** * @brief Figures out the edges that should connect the given wire segment to the given channel segment, adds these edges to 'rr_edge_to_create' * * @param rr_graph_builder RRGraphBuilder data structure which allows data modification on a routing resource graph @@ -124,13 +120,9 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, const e_side from_side, const e_side to_side, const int swtich_override, - const int custom_3d_sb_fanin_fanout, - const int delayless_switch, 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, - t_rr_edge_info_set& des_3d_rr_edges_to_create); + t_rr_edge_info_set& rr_edges_to_create); static int vpr_to_phy_track(const int itrack, const int chan_num, @@ -1115,22 +1107,18 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, const DeviceGrid& grid, const int Fs_per_side, t_sblock_pattern& sblock_pattern, - vtr::NdMatrix& num_of_3d_conns_custom_SB, RRNodeId from_rr_node, t_rr_edge_info_set& rr_edges_to_create, - t_rr_edge_info_set& des_3d_rr_edges_to_create, const t_chan_seg_details* from_seg_details, const t_chan_seg_details* to_seg_details, const t_chan_details& to_chan_details, - const enum e_directionality directionality, - const int custom_3d_sb_fanin_fanout, - const int delayless_switch, + const e_directionality directionality, const vtr::NdMatrix, 3>& switch_block_conn, 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 to_side; + e_side to_side; /* check whether a custom switch block will be used */ bool custom_switch_block = false; @@ -1255,8 +1243,8 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, if (Direction::DEC == from_seg_details[from_track].direction() || BI_DIRECTIONAL == directionality) { num_conn += get_track_to_chan_seg(rr_graph_builder, layer, 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); + switch_override, + *sb_conn_map, from_rr_node, rr_edges_to_create); } } else { if (BI_DIRECTIONAL == directionality) { @@ -1293,8 +1281,8 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, if (Direction::INC == from_seg_details[from_track].direction() || BI_DIRECTIONAL == directionality) { num_conn += get_track_to_chan_seg(rr_graph_builder, layer, 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); + switch_override, + *sb_conn_map, from_rr_node, rr_edges_to_create); } } else { if (BI_DIRECTIONAL == directionality) { @@ -1405,12 +1393,8 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, const int to_y, const e_rr_type to_chan_type, const int switch_override, - const int custom_3d_sb_fanin_fanout, - const int delayless_switch, 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) { const auto& device_ctx = g_vpr_ctx.device(); @@ -1429,8 +1413,6 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, 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); @@ -1453,57 +1435,7 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, ++edge_count; } } 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 >= (int)device_ctx.grid.get_num_layers()) - || (to_layer < 0 || to_layer >= (int)device_ctx.grid.get_num_layers())) { - continue; - } - - if (tile_x != to_x || tile_y != to_y) { - continue; - } - - // In order to connect two tracks in different layers, we need to follow these three steps: - // 1) connect "from_tracks" to CHANZ node in the same switch block - // 2) connect CHANZ node located in from_layer to another CHANZ node located in to_layer - // 3) connect CHANZ node located in to_layer to "to_track" - // +-------------+ +-------------+ +--------------+ +--------------+ - // | from_wire | -----> | CHANZ node | ------> | CHANZ node | ------> | to_wire | - // | (src_layer) | | (src_layer) | | (dest_layer) | | (dest_layer) | - // +-------------+ +-------------+ +--------------+ +--------------+ - - const int chanz_track_num = num_of_3d_conns_custom_SB[tile_x][tile_y] / custom_3d_sb_fanin_fanout; - RRNodeId src_chanz_node = rr_graph_builder.node_lookup().find_node(layer, tile_x, tile_y, e_rr_type::CHANZ, chanz_track_num); - RRNodeId sink_chanz_node = rr_graph_builder.node_lookup().find_node(to_layer, tile_x, tile_y, e_rr_type::CHANZ, chanz_track_num); - RRNodeId sink_track_node = rr_graph_builder.node_lookup().find_node(to_layer, to_x, to_y, to_chan_type, to_wire); - - if (!src_chanz_node || !sink_chanz_node || !sink_track_node) { - continue; - } - - // 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 - rr_edges_to_create.emplace_back(from_rr_node, src_chanz_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, but redundant edges will be removed before updating the RR graph - des_3d_rr_edges_to_create.emplace_back(sink_chanz_node, sink_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 - if (num_of_3d_conns_custom_SB[tile_x][tile_y] % custom_3d_sb_fanin_fanout == 0) { - rr_edges_to_create.emplace_back(src_chanz_node, sink_chanz_node, delayless_switch, false); - ++edge_count; - } - - num_of_3d_conns_custom_SB[tile_x][tile_y]++; + VTR_ASSERT(false); } } } @@ -1518,13 +1450,9 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, const e_side from_side, const e_side to_side, const int switch_override, - const int custom_3d_sb_fanin_fanout, - const int delayless_switch, 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, - t_rr_edge_info_set& des_3d_rr_edges_to_create) { + t_rr_edge_info_set& rr_edges_to_create) { int edge_count = 0; int to_x, to_y; int tile_x, tile_y; @@ -1557,36 +1485,10 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, to_y, to_chan_type, switch_override, - custom_3d_sb_fanin_fanout, - delayless_switch, sb_conn_map, - num_of_3d_conns_custom_SB, rr_edges_to_create, - des_3d_rr_edges_to_create, edge_count); - // 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, - tile_y, - layer, - from_side, - from_wire, - from_rr_node, - to_another_die_side, - to_x, - to_y, - to_chan_type, - switch_override, - custom_3d_sb_fanin_fanout, - delayless_switch, - sb_conn_map, - num_of_3d_conns_custom_SB, - rr_edges_to_create, - des_3d_rr_edges_to_create, - edge_count); - } return edge_count; } diff --git a/vpr/src/route/rr_graph_generation/rr_graph2.h b/vpr/src/route/rr_graph_generation/rr_graph2.h index 644f0ef202e..98a64003b7d 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph2.h +++ b/vpr/src/route/rr_graph_generation/rr_graph2.h @@ -120,16 +120,12 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, const DeviceGrid& grid, const int Fs_per_side, t_sblock_pattern& sblock_pattern, - vtr::NdMatrix& num_of_3d_conns_custom_SB, RRNodeId from_rr_node, t_rr_edge_info_set& rr_edges_to_create, - t_rr_edge_info_set& des_3d_rr_edges_to_create, const t_chan_seg_details* from_seg_details, const t_chan_seg_details* to_seg_details, const t_chan_details& to_chan_details, - const enum e_directionality directionality, - const int custom_3d_sb_fanin_fanout, - const int delayless_switch, + const e_directionality directionality, const vtr::NdMatrix, 3>& switch_block_conn, const t_sb_connection_map* sb_conn_map); From f6d18810311ee8370c5142c388976d83ae1d71a3 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Wed, 10 Sep 2025 19:24:00 -0400 Subject: [PATCH 22/58] add inter-die 3d edges --- vpr/src/route/rr_graph_generation/rr_graph.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/vpr/src/route/rr_graph_generation/rr_graph.cpp b/vpr/src/route/rr_graph_generation/rr_graph.cpp index e85a1194672..48760736f92 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph.cpp +++ b/vpr/src/route/rr_graph_generation/rr_graph.cpp @@ -3102,6 +3102,8 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, static void add_interdie_3d_edges(RRGraphBuilder& rr_graph_builder, int x_coord, int y_coord, + const t_chan_details& chan_details_x, + const t_chan_details& chan_details_y, const std::vector& interdie_3d_links, t_rr_edge_info_set& interdie_3d_rr_edges_to_create) { @@ -3118,10 +3120,19 @@ static void add_interdie_3d_edges(RRGraphBuilder& rr_graph_builder, for (const t_sg_candidate& gather_wire : link.gather_fanin_connections) { const t_physical_tile_loc& chan_loc = gather_wire.chan_loc.location; e_rr_type chan_type = gather_wire.chan_loc.chan_type; - RRNodeId gather_node = node_lookup.find_node(chan_loc.layer_num, chan_loc.x, chan_loc.y, chan_type, gather_wire.wire_switchpoint.wire); + interdie_3d_rr_edges_to_create.emplace_back(gather_node, chanz_node, 1, false); + } + + for (const t_sg_candidate& scatter_wire : link.scatter_fanout_connections) { + const t_physical_tile_loc& chan_loc = scatter_wire.chan_loc.location; + e_rr_type chan_type = scatter_wire.chan_loc.chan_type; + const t_chan_details& chan_details = (chan_type == e_rr_type::CHANX) ? chan_details_x : chan_details_y; + RRNodeId scatter_node = node_lookup.find_node(chan_loc.layer_num, chan_loc.x, chan_loc.y, chan_type, scatter_wire.wire_switchpoint.wire); + int switch_index = chan_details[chan_loc.x][chan_loc.y][scatter_wire.wire_switchpoint.wire].arch_wire_switch(); + interdie_3d_rr_edges_to_create.emplace_back(chanz_node, scatter_node, switch_index, false); } } } From 53dd48659c7fbdd39a62ac6bfe050f0fb3f033f1 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Thu, 11 Sep 2025 11:56:36 -0400 Subject: [PATCH 23/58] add arch_wire_switch --- libs/libarchfpga/src/physical_types.h | 9 +++-- .../build_scatter_gathers.cpp | 34 +++++++++++++++---- .../build_scatter_gathers.h | 2 ++ .../route/rr_graph_generation/rr_graph.cpp | 14 +++++++- .../route/rr_graph_generation/rr_graph2.cpp | 2 +- vpr/src/route/rr_graph_generation/rr_graph2.h | 2 +- 6 files changed, 48 insertions(+), 15 deletions(-) diff --git a/libs/libarchfpga/src/physical_types.h b/libs/libarchfpga/src/physical_types.h index 3418e7ba342..faf0e8bac1c 100644 --- a/libs/libarchfpga/src/physical_types.h +++ b/libs/libarchfpga/src/physical_types.h @@ -32,7 +32,6 @@ #include #include #include -#include #include #include @@ -1746,14 +1745,14 @@ struct t_segment_inf { * 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; + short arch_wire_switch_dec = ARCH_FPGA_UNDEFINED_VAL; /** * @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; + short arch_opin_switch_dec = ARCH_FPGA_UNDEFINED_VAL; /** * @brief Index of the switch type that connects output pins (OPINs) to this @@ -1761,7 +1760,7 @@ struct t_segment_inf { * the switches from the architecture file, not the expanded list of switches * that is built at the end of build_rr_graph. */ - short arch_inter_die_switch = -1; + short arch_inter_die_switch = ARCH_FPGA_UNDEFINED_VAL; /** * @brief The fraction of logic blocks along its length to which this segment can connect. @@ -1783,7 +1782,7 @@ struct t_segment_inf { /// The capacitance of a routing track, per unit logic block length. float Cmetal; - enum e_directionality directionality; + e_directionality directionality; /** * @brief Defines what axis the segment is parallel to. See e_parallel_axis diff --git a/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp b/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp index 53fc343131b..85e6b037291 100644 --- a/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp +++ b/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp @@ -102,6 +102,7 @@ std::vector std::vector alloc_and_load_scatter_gather_connections(const std::vector& scatter_gather_patterns, const std::vector& inter_cluster_rr, + const std::vector& segment_inf, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, const t_chan_width& nodes_per_chan, @@ -133,13 +134,22 @@ std::vector alloc_and_load_scatter_gather_connections(const s continue; } - auto it = std::ranges::find_if(sg_pattern.sg_links, - [&](const t_sg_link& link) noexcept { - return link.name == sg_loc_info.sg_link_name; - }); + auto sg_link_it = std::ranges::find_if(sg_pattern.sg_links, + [&](const t_sg_link& link) noexcept { + return link.name == sg_loc_info.sg_link_name; + }); - VTR_ASSERT_SAFE(it != sg_pattern.sg_links.end()); - const t_sg_link& sg_link = *it; + VTR_ASSERT(sg_link_it != sg_pattern.sg_links.end()); + const t_sg_link& sg_link = *sg_link_it; + + + auto seg_it = std::ranges::find_if(segment_inf, + [&](const t_segment_inf& seg) noexcept { + return seg.name == sg_link.seg_type; + }); + + VTR_ASSERT(seg_it != segment_inf.end()); + const t_segment_inf& wire_segment = *seg_it; t_physical_tile_loc scatter_loc; scatter_loc.x = gather_loc.x + sg_link.x_offset; @@ -184,7 +194,7 @@ std::vector alloc_and_load_scatter_gather_connections(const s continue; } - const bool is_3d_link = (gather_loc.layer_num != scatter_loc.layer_num); + const bool is_3d_link = (sg_link.z_offset != 0); if (is_3d_link) { interdie_3d_links[gather_loc.x][gather_loc.y].reserve(interdie_3d_links[gather_loc.x][gather_loc.y].size() + sg_loc_info.num); } else { @@ -210,8 +220,18 @@ std::vector alloc_and_load_scatter_gather_connections(const s } if (is_3d_link) { + if (sg_link.z_offset < 0 && wire_segment.arch_wire_switch_dec != ARCH_FPGA_UNDEFINED_VAL) { + bottleneck_link.arch_wire_switch = wire_segment.arch_wire_switch_dec; + } else { + bottleneck_link.arch_wire_switch = wire_segment.arch_wire_switch; + } interdie_3d_links[gather_loc.x][gather_loc.y].push_back(std::move(bottleneck_link)); } else { + if ((sg_link.x_offset < 0 || sg_link.y_offset < 0) && wire_segment.arch_wire_switch_dec != ARCH_FPGA_UNDEFINED_VAL) { + bottleneck_link.arch_wire_switch = wire_segment.arch_wire_switch_dec; + } else { + bottleneck_link.arch_wire_switch = wire_segment.arch_wire_switch; + } bottleneck_links.push_back(std::move(bottleneck_link)); } diff --git a/vpr/src/route/rr_graph_generation/build_scatter_gathers.h b/vpr/src/route/rr_graph_generation/build_scatter_gathers.h index 6e0a28e6356..33f3faa3482 100644 --- a/vpr/src/route/rr_graph_generation/build_scatter_gathers.h +++ b/vpr/src/route/rr_graph_generation/build_scatter_gathers.h @@ -21,12 +21,14 @@ struct t_sg_candidate { struct t_bottleneck_link { t_physical_tile_loc gather_loc; t_physical_tile_loc scatter_loc; + int arch_wire_switch; std::vector gather_fanin_connections; std::vector scatter_fanout_connections; }; std::vector alloc_and_load_scatter_gather_connections(const std::vector& scatter_gather_patterns, const std::vector& inter_cluster_rr, + const std::vector& segment_inf, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, const t_chan_width& nodes_per_chan, diff --git a/vpr/src/route/rr_graph_generation/rr_graph.cpp b/vpr/src/route/rr_graph_generation/rr_graph.cpp index 48760736f92..ba7a4ad4ace 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph.cpp +++ b/vpr/src/route/rr_graph_generation/rr_graph.cpp @@ -492,6 +492,14 @@ static void build_inter_die_3d_rr_chan(RRGraphBuilder& rr_graph_builder, const t_chan_width& nodes_per_chan, const t_chan_details& chan_details_x); +static void add_interdie_3d_edges(RRGraphBuilder& rr_graph_builder, + int x_coord, + int y_coord, + const t_chan_details& chan_details_x, + const t_chan_details& chan_details_y, + const std::vector& interdie_3d_links, + t_rr_edge_info_set& interdie_3d_rr_edges_to_create); + void uniquify_edges(t_rr_edge_info_set& rr_edges_to_create); void alloc_and_load_edges(RRGraphBuilder& rr_graph_builder, @@ -1218,6 +1226,7 @@ static void build_rr_graph(e_graph_type graph_type, vtr::NdMatrix, 2> interdie_3d_links; const std::vector bottleneck_links = alloc_and_load_scatter_gather_connections(scatter_gather_patterns, inter_cluster_prog_rr, + segment_inf, chan_details_x, chan_details_y, nodes_per_chan, interdie_3d_links); @@ -2129,6 +2138,9 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder } if (grid.get_num_layers() > 1) { + add_interdie_3d_edges(rr_graph_builder, i, j, + chan_details_x, chan_details_y, + interdie_3d_links[i][j], interdie_3d_rr_edges_to_create); uniquify_edges(interdie_3d_rr_edges_to_create); alloc_and_load_edges(rr_graph_builder, interdie_3d_rr_edges_to_create); num_edges += interdie_3d_rr_edges_to_create.size(); @@ -3122,7 +3134,7 @@ static void add_interdie_3d_edges(RRGraphBuilder& rr_graph_builder, e_rr_type chan_type = gather_wire.chan_loc.chan_type; RRNodeId gather_node = node_lookup.find_node(chan_loc.layer_num, chan_loc.x, chan_loc.y, chan_type, gather_wire.wire_switchpoint.wire); - interdie_3d_rr_edges_to_create.emplace_back(gather_node, chanz_node, 1, false); + interdie_3d_rr_edges_to_create.emplace_back(gather_node, chanz_node, link.arch_wire_switch, false); } for (const t_sg_candidate& scatter_wire : link.scatter_fanout_connections) { diff --git a/vpr/src/route/rr_graph_generation/rr_graph2.cpp b/vpr/src/route/rr_graph_generation/rr_graph2.cpp index d7950573892..544ca0df1d4 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph2.cpp +++ b/vpr/src/route/rr_graph_generation/rr_graph2.cpp @@ -243,7 +243,7 @@ std::vector alloc_and_load_seg_details(int* max_chan_width, const int max_len, const std::vector& segment_inf, const bool use_full_seg_groups, - const enum e_directionality directionality) { + const e_directionality directionality) { /* Allocates and loads the seg_details data structure. Max_len gives the * * maximum length of a segment (dimension of array). The code below tries * * to: * diff --git a/vpr/src/route/rr_graph_generation/rr_graph2.h b/vpr/src/route/rr_graph_generation/rr_graph2.h index 98a64003b7d..45bebc65f4d 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph2.h +++ b/vpr/src/route/rr_graph_generation/rr_graph2.h @@ -15,7 +15,7 @@ std::vector alloc_and_load_seg_details(int* max_chan_width, const int max_len, const std::vector& segment_inf, const bool use_full_seg_groups, - const enum e_directionality directionality); + const e_directionality directionality); void alloc_and_load_chan_details(const DeviceGrid& grid, const t_chan_width& nodes_per_chan, From 8a882c1ffe28497adbf3bd7c0673512819d0d1f3 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Thu, 11 Sep 2025 14:47:43 -0400 Subject: [PATCH 24/58] fix the bug in index assignment to chanz nodes --- vpr/src/route/rr_graph_generation/rr_node_indices.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) 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 6410574f4e3..2cefaa1a423 100644 --- a/vpr/src/route/rr_graph_generation/rr_node_indices.cpp +++ b/vpr/src/route/rr_graph_generation/rr_node_indices.cpp @@ -345,16 +345,19 @@ void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, } for (int track_num = 0; track_num < num_chanz_nodes; track_num++) { + bool incremnet_index = false; for (size_t layer = 0; layer < grid.get_num_layers(); layer++) { RRNodeId inode = rr_graph_builder.node_lookup().find_node(layer, x, y, e_rr_type::CHANZ, track_num); if (!inode) { inode = RRNodeId(*index); rr_graph_builder.node_lookup().add_node(inode, layer, x, y, e_rr_type::CHANZ, track_num); - if (layer == 0) { - ++(*index); - } + incremnet_index = true; } } + + if (incremnet_index) { + ++(*index); + } } } } From a3a9aeca49044cf328aecac56b6cdb9666716955 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Thu, 11 Sep 2025 16:30:45 -0400 Subject: [PATCH 25/58] rename add_interdie_3d_edges() to add_inter_die_3d_edges() --- .../route/rr_graph_generation/rr_graph.cpp | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/vpr/src/route/rr_graph_generation/rr_graph.cpp b/vpr/src/route/rr_graph_generation/rr_graph.cpp index ba7a4ad4ace..e0aea9da2b2 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph.cpp +++ b/vpr/src/route/rr_graph_generation/rr_graph.cpp @@ -492,13 +492,13 @@ static void build_inter_die_3d_rr_chan(RRGraphBuilder& rr_graph_builder, const t_chan_width& nodes_per_chan, const t_chan_details& chan_details_x); -static void add_interdie_3d_edges(RRGraphBuilder& rr_graph_builder, - int x_coord, - int y_coord, - const t_chan_details& chan_details_x, - const t_chan_details& chan_details_y, - const std::vector& interdie_3d_links, - t_rr_edge_info_set& interdie_3d_rr_edges_to_create); +static void add_inter_die_3d_edges(RRGraphBuilder& rr_graph_builder, + int x_coord, + int y_coord, + const t_chan_details& chan_details_x, + const t_chan_details& chan_details_y, + const std::vector& interdie_3d_links, + t_rr_edge_info_set& interdie_3d_rr_edges_to_create); void uniquify_edges(t_rr_edge_info_set& rr_edges_to_create); @@ -2109,7 +2109,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder wire_to_pin_between_dice_switch, directionality); - //Create the actual CHAN->CHAN edges + // Create the actual CHAN->CHAN 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(); @@ -2138,9 +2138,9 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder } if (grid.get_num_layers() > 1) { - add_interdie_3d_edges(rr_graph_builder, i, j, - chan_details_x, chan_details_y, - interdie_3d_links[i][j], interdie_3d_rr_edges_to_create); + add_inter_die_3d_edges(rr_graph_builder, i, j, + chan_details_x, chan_details_y, + interdie_3d_links[i][j], interdie_3d_rr_edges_to_create); uniquify_edges(interdie_3d_rr_edges_to_create); alloc_and_load_edges(rr_graph_builder, interdie_3d_rr_edges_to_create); num_edges += interdie_3d_rr_edges_to_create.size(); @@ -3111,13 +3111,13 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, } } -static void add_interdie_3d_edges(RRGraphBuilder& rr_graph_builder, - int x_coord, - int y_coord, - const t_chan_details& chan_details_x, - const t_chan_details& chan_details_y, - const std::vector& interdie_3d_links, - t_rr_edge_info_set& interdie_3d_rr_edges_to_create) { +static void add_inter_die_3d_edges(RRGraphBuilder& rr_graph_builder, + int x_coord, + int y_coord, + const t_chan_details& chan_details_x, + const t_chan_details& chan_details_y, + const std::vector& interdie_3d_links, + t_rr_edge_info_set& interdie_3d_rr_edges_to_create) { const RRSpatialLookup& node_lookup = rr_graph_builder.node_lookup(); const int num_tracks = interdie_3d_links.size(); From 2dd17315b821f404cb4af75699bc578618a16653 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Thu, 11 Sep 2025 16:34:24 -0400 Subject: [PATCH 26/58] some minor clean ups --- libs/librrgraph/src/base/check_rr_graph.cpp | 2 +- libs/librrgraph/src/base/rr_graph_storage.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/librrgraph/src/base/check_rr_graph.cpp b/libs/librrgraph/src/base/check_rr_graph.cpp index 8643ea6f55d..d4357a63fe3 100644 --- a/libs/librrgraph/src/base/check_rr_graph.cpp +++ b/libs/librrgraph/src/base/check_rr_graph.cpp @@ -441,7 +441,7 @@ void check_rr_node(const RRGraphView& rr_graph, break; case e_rr_type::CHANZ: - if (xhigh != xlow || yhigh != ylow || xhigh > grid_width - 1 || ylow < 1 || yhigh > grid_height - 1) { + if (xhigh != xlow || yhigh != ylow || xhigh > grid_width - 1 || yhigh > grid_height - 1) { VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Error in check_rr_node: CHANZ out of range for endpoints (%d,%d) and (%d,%d)\n", xlow, ylow, xhigh, yhigh); } diff --git a/libs/librrgraph/src/base/rr_graph_storage.h b/libs/librrgraph/src/base/rr_graph_storage.h index 0bf58ff4539..6c03ec5c0ff 100644 --- a/libs/librrgraph/src/base/rr_graph_storage.h +++ b/libs/librrgraph/src/base/rr_graph_storage.h @@ -242,7 +242,7 @@ class t_rr_graph_storage { } /** @brief Find the layer number that RRNodeId is located at. - * it is zero if the FPGA only has one die. + * It is zero if the FPGA only has one die. * The layer number start from the base die (base die: 0, the die above it: 1, etc.) */ short node_layer(RRNodeId id) const{ @@ -903,7 +903,7 @@ class t_rr_graph_storage { * Layer number that each RR node is located at * Layer number refers to the die that the node belongs to. The layer number of base die is zero and die above it one, etc. * This data is also considered as a hot data since it is used in inner loop of router, but since it didn't fit nicely into t_rr_node_data due to alignment issues, we had to store it - *in a separate vector. + * in a separate vector. */ vtr::vector node_layer_; From 0f5ae7a859257009ba89bfc76c57555583bffd19 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Fri, 12 Sep 2025 15:38:05 -0400 Subject: [PATCH 27/58] add layer_low/high to RR graph API to support CHANZ nodes that span multiple layers --- libs/librrgraph/src/base/check_rr_graph.cpp | 25 +++--- libs/librrgraph/src/base/check_rr_graph.h | 2 +- libs/librrgraph/src/base/rr_graph_builder.cpp | 50 ++++++----- libs/librrgraph/src/base/rr_graph_builder.h | 9 +- libs/librrgraph/src/base/rr_graph_storage.cpp | 13 ++- libs/librrgraph/src/base/rr_graph_storage.h | 60 +++++++++---- libs/librrgraph/src/base/rr_graph_utils.cpp | 31 ++++--- libs/librrgraph/src/base/rr_graph_view.h | 27 ++++-- libs/librrgraph/src/io/gen/rr_graph_uxsdcxx.h | 88 ++++++++++++++----- .../src/io/gen/rr_graph_uxsdcxx_capnp.h | 16 ++-- .../src/io/gen/rr_graph_uxsdcxx_interface.h | 15 ++-- libs/librrgraph/src/io/rr_graph.xsd | 3 +- .../src/io/rr_graph_uxsdcxx_serializer.h | 28 ++++-- .../librrgraph/src/utils/describe_rr_node.cpp | 2 +- .../gen/rr_graph_uxsdcxx.capnp | 24 ++--- vpr/src/analysis/timing_reports.cpp | 8 +- vpr/src/base/read_route.cpp | 19 ++-- vpr/src/base/stats.cpp | 12 +-- vpr/src/base/stats.h | 4 +- vpr/src/draw/draw_basic.cpp | 8 +- vpr/src/draw/draw_rr.cpp | 14 +-- vpr/src/draw/draw_rr_edges.cpp | 8 +- vpr/src/draw/search_bar.cpp | 2 +- .../pack/sync_netlists_to_routing_flat.cpp | 8 +- vpr/src/place/net_cost_handler.cpp | 28 ++---- vpr/src/route/DecompNetlistRouter.tpp | 4 +- vpr/src/route/check_route.cpp | 8 +- vpr/src/route/connection_router.tpp | 18 ++-- vpr/src/route/overuse_report.cpp | 25 +++--- vpr/src/route/parallel_connection_router.cpp | 2 +- vpr/src/route/route_common.cpp | 20 ++--- vpr/src/route/route_common.h | 4 +- vpr/src/route/route_utilization.cpp | 2 +- vpr/src/route/route_utils.cpp | 4 +- .../router_lookahead_compressed_map.cpp | 10 ++- .../router_lookahead_extended_map.cpp | 27 +++--- .../router_lookahead/router_lookahead_map.cpp | 21 ++--- .../router_lookahead_map_utils.cpp | 20 ++--- .../router_lookahead_simple.cpp | 5 +- .../clock_connection_builders.cpp | 3 +- .../clock_network_builders.cpp | 6 +- .../route/rr_graph_generation/rr_graph.cpp | 14 ++- .../rr_graph_generation/rr_node_indices.cpp | 2 +- .../tileable_rr_graph_node_builder.cpp | 18 ++-- vpr/src/route/serial_connection_router.cpp | 6 +- vpr/src/util/vpr_utils.cpp | 66 +++++++------- vpr/src/util/vpr_utils.h | 3 +- 47 files changed, 465 insertions(+), 327 deletions(-) diff --git a/libs/librrgraph/src/base/check_rr_graph.cpp b/libs/librrgraph/src/base/check_rr_graph.cpp index d4357a63fe3..e219e56b036 100644 --- a/libs/librrgraph/src/base/check_rr_graph.cpp +++ b/libs/librrgraph/src/base/check_rr_graph.cpp @@ -234,11 +234,11 @@ void check_rr_graph(const RRGraphView& rr_graph, size_t inode = (size_t)rr_node; e_rr_type rr_type = rr_graph.node_type(rr_node); int ptc_num = rr_graph.node_ptc_num(rr_node); - int layer_num = rr_graph.node_layer(rr_node); + int layer_low = rr_graph.node_layer_low(rr_node); int xlow = rr_graph.node_xlow(rr_node); int ylow = rr_graph.node_ylow(rr_node); - t_physical_tile_type_ptr type = grid.get_physical_type({xlow, ylow, layer_num}); + t_physical_tile_type_ptr type = grid.get_physical_type({xlow, ylow, layer_low}); if (rr_type == e_rr_type::IPIN || rr_type == e_rr_type::OPIN) { // #TODO: No edges are added for internal pins. However, they need to be checked somehow! @@ -278,7 +278,7 @@ void check_rr_graph(const RRGraphView& rr_graph, if (has_adjacent_channel(rr_graph, grid, node)) { auto block_type = grid.get_physical_type({rr_graph.node_xlow(rr_node), rr_graph.node_ylow(rr_node), - rr_graph.node_layer(rr_node)}); + rr_graph.node_layer_low(rr_node)}); std::string pin_name = block_type_pin_index_to_name(block_type, rr_graph.node_pin_num(rr_node), is_flat); /* Print error messages for all the sides that a node may appear */ for (const e_side& node_side : TOTAL_2D_SIDES) { @@ -315,10 +315,10 @@ static bool rr_node_is_global_clb_ipin(const RRGraphView& rr_graph, const Device /* Returns true if inode refers to a global CLB input pin node. */ t_physical_tile_type_ptr type = grid.get_physical_type({rr_graph.node_xlow(inode), rr_graph.node_ylow(inode), - rr_graph.node_layer(inode)}); + rr_graph.node_layer_low(inode)}); if (rr_graph.node_type(inode) != e_rr_type::IPIN) - return (false); + return false; int ipin = rr_graph.node_pin_num(inode); @@ -330,7 +330,7 @@ void check_rr_node(const RRGraphView& rr_graph, const DeviceGrid& grid, const VibDeviceGrid& vib_grid, const t_chan_width& chan_width, - const enum e_route_type route_type, + const e_route_type route_type, const int inode, bool is_flat) { //Make sure over-flow doesn't happen @@ -347,7 +347,8 @@ void check_rr_node(const RRGraphView& rr_graph, int xhigh = rr_graph.node_xhigh(rr_node); int ylow = rr_graph.node_ylow(rr_node); int yhigh = rr_graph.node_yhigh(rr_node); - int layer_num = rr_graph.node_layer(rr_node); + int layer_low = rr_graph.node_layer_low(rr_node); + int layer_high = rr_graph.node_layer_low(rr_node); int ptc_num = rr_graph.node_ptc_num(rr_node); int capacity = rr_graph.node_capacity(rr_node); RRIndexedDataId cost_index = rr_graph.node_cost_index(rr_node); @@ -362,9 +363,9 @@ void check_rr_node(const RRGraphView& rr_graph, "in check_rr_node: rr endpoints (%d,%d) and (%d,%d) are out of range.\n", xlow, ylow, xhigh, yhigh); } - if (layer_num < 0 || layer_num > grid_layers - 1) { + if (layer_low < 0 || layer_high > grid_layers - 1) { VPR_FATAL_ERROR(VPR_ERROR_ROUTE, - "in check_rr_node: rr endpoints layer_num (%d) is out of range.\n", layer_num); + "in check_rr_node: rr endpoints layer range (%d, %d) is out of range.\n", layer_low, layer_high); } if (ptc_num < 0) { @@ -378,7 +379,7 @@ void check_rr_node(const RRGraphView& rr_graph, } // Check that the segment is within the array and such. - t_physical_tile_type_ptr type = grid.get_physical_type({xlow, ylow, layer_num}); + t_physical_tile_type_ptr type = grid.get_physical_type({xlow, ylow, layer_low}); switch (rr_type) { case e_rr_type::SOURCE: @@ -398,7 +399,7 @@ void check_rr_node(const RRGraphView& rr_graph, "in check_rr_node: node %d (type %d) is at an illegal clb location (%d, %d).\n", inode, rr_type, xlow, ylow); } - vtr::Rect tile_bb = grid.get_tile_bb({xlow, ylow, layer_num}); + vtr::Rect tile_bb = grid.get_tile_bb({xlow, ylow, layer_low}); if (xlow < tile_bb.xmin() || ylow < tile_bb.ymin() || xhigh > tile_bb.xmax() || yhigh > tile_bb.ymax()) { VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "in check_rr_node: node %d (type %d) has endpoints (%d,%d) and (%d,%d), which is outside the bounds of the grid tile containing it.\n", inode, rr_type, xlow, ylow, xhigh, yhigh); @@ -464,7 +465,7 @@ void check_rr_node(const RRGraphView& rr_graph, int mux_max_ptc = -1; const VibInf* vib_type = nullptr; if (vib_grid.get_num_layers() > 0) { - vib_type = vib_grid.get_vib(layer_num, xlow, ylow); + vib_type = vib_grid.get_vib(layer_low, xlow, ylow); } if (vib_type) { mux_max_ptc = (int)vib_type->get_first_stages().size(); diff --git a/libs/librrgraph/src/base/check_rr_graph.h b/libs/librrgraph/src/base/check_rr_graph.h index e436e92f247..8fd6dffbda9 100644 --- a/libs/librrgraph/src/base/check_rr_graph.h +++ b/libs/librrgraph/src/base/check_rr_graph.h @@ -39,6 +39,6 @@ void check_rr_node(const RRGraphView& rr_graph, const DeviceGrid& grid, const VibDeviceGrid& vib_grid, const t_chan_width& chan_width, - const enum e_route_type route_type, + const e_route_type route_type, const int inode, bool is_flat); diff --git a/libs/librrgraph/src/base/rr_graph_builder.cpp b/libs/librrgraph/src/base/rr_graph_builder.cpp index b446108cc1d..1196d7fdc3a 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.cpp +++ b/libs/librrgraph/src/base/rr_graph_builder.cpp @@ -38,32 +38,32 @@ vtr::vector>& RRGraphBuilder::node_ptc_storage() { void RRGraphBuilder::add_node_to_all_locs(RRNodeId node) { e_rr_type node_type = node_storage_.node_type(node); short node_ptc_num = node_storage_.node_ptc_num(node); - short node_layer = node_storage_.node_layer(node); for (int ix = node_storage_.node_xlow(node); ix <= node_storage_.node_xhigh(node); ix++) { for (int iy = node_storage_.node_ylow(node); iy <= node_storage_.node_yhigh(node); iy++) { - - switch (node_type) { - case e_rr_type::SOURCE: - case e_rr_type::SINK: - case e_rr_type::CHANZ: - case e_rr_type::CHANY: - case e_rr_type::CHANX: - node_lookup_.add_node(node, node_layer, ix, iy, node_type, node_ptc_num, TOTAL_2D_SIDES[0]); - break; - - case e_rr_type::OPIN: - case e_rr_type::IPIN: - for (const e_side side : TOTAL_2D_SIDES) { - if (node_storage_.is_node_on_specific_side(node, side)) { - node_lookup_.add_node(node,node_layer, ix, iy, node_type, node_ptc_num, side); + for (int iz = node_storage_.node_layer_low(node); iz <= node_storage_.node_layer_high(node); iz++) { + switch (node_type) { + case e_rr_type::SOURCE: + case e_rr_type::SINK: + case e_rr_type::CHANZ: + case e_rr_type::CHANY: + case e_rr_type::CHANX: + node_lookup_.add_node(node, iz, ix, iy, node_type, node_ptc_num, TOTAL_2D_SIDES[0]); + break; + + case e_rr_type::OPIN: + case e_rr_type::IPIN: + for (const e_side side : TOTAL_2D_SIDES) { + if (node_storage_.is_node_on_specific_side(node, side)) { + node_lookup_.add_node(node,iz, ix, iy, node_type, node_ptc_num, side); + } } - } - break; + break; - default: - VTR_LOG_ERROR("Invalid node type for node '%lu' in the routing resource graph file", size_t(node)); - break; + default: + VTR_LOG_ERROR("Invalid node type for node '%lu' in the routing resource graph file", size_t(node)); + break; + } } } } @@ -78,7 +78,8 @@ RRNodeId RRGraphBuilder::create_node(int layer, int x, int y, e_rr_type type, in node_storage_.emplace_back(); node_tilable_track_nums_.emplace_back(); RRNodeId new_node = RRNodeId(node_storage_.size() - 1); - node_storage_.set_node_layer(new_node, layer); + node_storage_.set_node_layer_low(new_node, layer); + node_storage_.set_node_layer_high(new_node, layer); node_storage_.set_node_type(new_node, type); node_storage_.set_node_coordinates(new_node, x, y, x, y); node_storage_.set_node_ptc_num(new_node, ptc); @@ -287,7 +288,8 @@ void RRGraphBuilder::add_node_track_num(RRNodeId node, vtr::Point node_o } void RRGraphBuilder::add_track_node_to_lookup(RRNodeId node) { - VTR_ASSERT_MSG(node_storage_.node_type(node) == e_rr_type::CHANX || node_storage_.node_type(node) == e_rr_type::CHANY, "Update track node look-up is only valid to CHANX/CHANY nodes"); + VTR_ASSERT_MSG(node_storage_.node_type(node) == e_rr_type::CHANX || node_storage_.node_type(node) == e_rr_type::CHANY, + "Update track node look-up is only valid to CHANX/CHANY nodes"); // Compute the track id based on the (x, y) coordinate size_t x_start = std::min(node_storage_.node_xlow(node), node_storage_.node_xhigh(node)); @@ -310,7 +312,7 @@ void RRGraphBuilder::add_track_node_to_lookup(RRNodeId node) { if (e_rr_type::CHANX == node_type || e_rr_type::CHANY == node_type) { ptc = (node_type == e_rr_type::CHANX) ? node_tilable_track_nums_[node][x - node_storage_.node_xlow(node)] : node_tilable_track_nums_[node][y - node_storage_.node_ylow(node)]; - node_lookup_.add_node(node, node_storage_.node_layer(node), x, y, node_type, ptc); + node_lookup_.add_node(node, node_storage_.node_layer_low(node), x, y, node_type, ptc); } } } diff --git a/libs/librrgraph/src/base/rr_graph_builder.h b/libs/librrgraph/src/base/rr_graph_builder.h index 1b520274ea5..34417b03120 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.h +++ b/libs/librrgraph/src/base/rr_graph_builder.h @@ -154,7 +154,7 @@ class RRGraphBuilder { * - valid geometry information: xlow/ylow/xhigh/yhigh * - a valid node type * - a valid node ptc number - * - a valid side (applicable to OPIN and IPIN nodes only + * - a valid side (applicable to OPIN and IPIN nodes only) */ void add_node_to_all_locs(RRNodeId node); @@ -239,10 +239,13 @@ class RRGraphBuilder { } /** @brief set the layer number at which RRNodeId is located at */ - inline void set_node_layer(RRNodeId id, int layer){ - node_storage_.set_node_layer(id, layer); + inline void set_node_layer_low(RRNodeId id, int layer){ + node_storage_.set_node_layer_low(id, layer); } + inline void set_node_layer_high(RRNodeId id, int layer){ + node_storage_.set_node_layer_high(id, layer); + } /** @brief set_node_pin_num() is designed for logic blocks, which are IPIN and OPIN nodes */ inline void set_node_pin_num(RRNodeId id, int new_pin_num) { diff --git a/libs/librrgraph/src/base/rr_graph_storage.cpp b/libs/librrgraph/src/base/rr_graph_storage.cpp index c3ba21ccec0..d616c177154 100644 --- a/libs/librrgraph/src/base/rr_graph_storage.cpp +++ b/libs/librrgraph/src/base/rr_graph_storage.cpp @@ -637,12 +637,16 @@ const char* t_rr_graph_storage::node_side_string(RRNodeId id) const { return TOTAL_2D_SIDE_STRINGS[side]; } } - /* Not found, return an invalid string*/ + // Not found, return an invalid string return TOTAL_2D_SIDE_STRINGS[NUM_2D_SIDES]; } -void t_rr_graph_storage::set_node_layer(RRNodeId id, short layer) { - node_layer_[id] = layer; +void t_rr_graph_storage::set_node_layer_low(RRNodeId id, short layer) { + node_layer_low_[id] = layer; +} + +void t_rr_graph_storage::set_node_layer_high(RRNodeId id, short layer) { + node_layer_high_[id] = layer; } void t_rr_graph_storage::set_node_ptc_num(RRNodeId id, int new_ptc_num) { @@ -860,7 +864,8 @@ t_rr_graph_view t_rr_graph_storage::view() const { vtr::make_const_array_view_id(node_ptc_), vtr::make_const_array_view_id(node_first_edge_), vtr::make_const_array_view_id(node_fan_in_), - vtr::make_const_array_view_id(node_layer_), + vtr::make_const_array_view_id(node_layer_low_), + vtr::make_const_array_view_id(node_layer_high_), node_name_, vtr::make_const_array_view_id(edge_src_node_), vtr::make_const_array_view_id(edge_dest_node_), diff --git a/libs/librrgraph/src/base/rr_graph_storage.h b/libs/librrgraph/src/base/rr_graph_storage.h index 6c03ec5c0ff..08dd7f18608 100644 --- a/libs/librrgraph/src/base/rr_graph_storage.h +++ b/libs/librrgraph/src/base/rr_graph_storage.h @@ -245,8 +245,15 @@ class t_rr_graph_storage { * It is zero if the FPGA only has one die. * The layer number start from the base die (base die: 0, the die above it: 1, etc.) */ - short node_layer(RRNodeId id) const{ - return node_layer_[id]; + // short node_layer(RRNodeId id) const{ + // return node_layer_[id]; + // } + short node_layer_low(RRNodeId id) const { + return node_layer_low_[id]; + } + + short node_layer_high(RRNodeId id) const { + return node_layer_high_[id]; } /** @@ -537,8 +544,11 @@ class t_rr_graph_storage { node_ptc_.reserve(node_storage_.capacity()); node_ptc_.resize(node_storage_.size()); - node_layer_.reserve(node_storage_.capacity()); - node_layer_.resize(node_storage_.size()); + node_layer_low_.reserve(node_storage_.capacity()); + node_layer_low_.resize(node_storage_.size()); + + node_layer_high_.reserve(node_storage_.capacity()); + node_layer_high_.resize(node_storage_.size()); if (is_tileable_) { node_bend_start_.reserve(node_storage_.capacity()); @@ -555,7 +565,8 @@ class t_rr_graph_storage { VTR_ASSERT(!edges_read_); node_storage_.reserve(size); node_ptc_.reserve(size); - node_layer_.reserve(size); + node_layer_low_.reserve(size); + node_layer_high_.reserve(size); if (is_tileable_) { node_bend_start_.reserve(size); node_bend_end_.reserve(size); @@ -568,7 +579,8 @@ class t_rr_graph_storage { VTR_ASSERT(!edges_read_); node_storage_.resize(size); node_ptc_.resize(size); - node_layer_.resize(size); + node_layer_low_.resize(size); + node_layer_high_.resize(size); if (is_tileable_) { node_bend_start_.resize(size); node_bend_end_.resize(size); @@ -593,7 +605,8 @@ class t_rr_graph_storage { node_ptc_.clear(); node_first_edge_.clear(); node_fan_in_.clear(); - node_layer_.clear(); + node_layer_low_.clear(); + node_layer_high_.clear(); node_bend_start_.clear(); node_bend_end_.clear(); node_name_.clear(); @@ -631,7 +644,8 @@ class t_rr_graph_storage { node_ptc_.shrink_to_fit(); node_first_edge_.shrink_to_fit(); node_fan_in_.shrink_to_fit(); - node_layer_.shrink_to_fit(); + node_layer_low_.shrink_to_fit(); + node_layer_high_.shrink_to_fit(); node_bend_start_.shrink_to_fit(); node_bend_end_.shrink_to_fit(); @@ -647,7 +661,8 @@ class t_rr_graph_storage { VTR_ASSERT(!edges_read_); node_storage_.emplace_back(); node_ptc_.emplace_back(); - node_layer_.emplace_back(); + node_layer_low_.emplace_back(); + node_layer_high_.emplace_back(); if (is_tileable_) { node_bend_start_.emplace_back(); node_bend_end_.emplace_back(); @@ -673,7 +688,8 @@ class t_rr_graph_storage { void set_node_type(RRNodeId id, e_rr_type new_type); void set_node_name(RRNodeId id, const std::string& new_name); void set_node_coordinates(RRNodeId id, short x1, short y1, short x2, short y2); - void set_node_layer(RRNodeId id, short layer); + void set_node_layer_low(RRNodeId id, short layer); + void set_node_layer_high(RRNodeId id, short layer); void set_node_cost_index(RRNodeId, RRIndexedDataId new_cost_index); void set_node_bend_start(RRNodeId id, size_t bend_start); void set_node_bend_end(RRNodeId id, size_t bend_end); @@ -905,7 +921,8 @@ class t_rr_graph_storage { * This data is also considered as a hot data since it is used in inner loop of router, but since it didn't fit nicely into t_rr_node_data due to alignment issues, we had to store it * in a separate vector. */ - vtr::vector node_layer_; + vtr::vector node_layer_low_; + vtr::vector node_layer_high_; /** * @brief Stores the assigned names for the RRNode IDs. @@ -1009,7 +1026,8 @@ class t_rr_graph_view { const vtr::array_view_id node_ptc, const vtr::array_view_id node_first_edge, const vtr::array_view_id node_fan_in, - const vtr::array_view_id node_layer, + const vtr::array_view_id node_layer_low, + const vtr::array_view_id node_layer_high, const std::unordered_map& node_name, const vtr::array_view_id edge_src_node, const vtr::array_view_id edge_dest_node, @@ -1021,7 +1039,8 @@ class t_rr_graph_view { , node_ptc_(node_ptc) , node_first_edge_(node_first_edge) , node_fan_in_(node_fan_in) - , node_layer_(node_layer) + , node_layer_low_(node_layer_low) + , node_layer_high_(node_layer_high) , node_name_(node_name) , edge_src_node_(edge_src_node) , edge_dest_node_(edge_dest_node) @@ -1094,8 +1113,16 @@ class t_rr_graph_view { * @param id The RRNodeId for which to retrieve the layer number. * @return The layer number (die) where the RRNodeId is located. */ - short node_layer(RRNodeId id) const{ - return node_layer_[id]; + // short node_layer(RRNodeId id) const { + // return node_layer_[id]; + // } + + short node_layer_low(RRNodeId id) const { + return node_layer_low_[id]; + } + + short node_layer_high(RRNodeId id) const { + return node_layer_high_[id]; } /** @@ -1227,7 +1254,8 @@ class t_rr_graph_view { vtr::array_view_id node_ptc_; vtr::array_view_id node_first_edge_; vtr::array_view_id node_fan_in_; - vtr::array_view_id node_layer_; + vtr::array_view_id node_layer_low_; + vtr::array_view_id node_layer_high_; const std::unordered_map& node_name_; vtr::array_view_id edge_src_node_; vtr::array_view_id edge_dest_node_; diff --git a/libs/librrgraph/src/base/rr_graph_utils.cpp b/libs/librrgraph/src/base/rr_graph_utils.cpp index 614961c4c67..b721c34de35 100644 --- a/libs/librrgraph/src/base/rr_graph_utils.cpp +++ b/libs/librrgraph/src/base/rr_graph_utils.cpp @@ -6,7 +6,7 @@ #include "rr_graph_view.h" #include "librrgraph_types.h" -/* +/** * @brief Walk backwards from origin SINK, and insert all cluster-edge IPINs to which origin is connected to sink_ipins * * @param rr_graph @@ -154,8 +154,9 @@ void rr_set_sink_locs(const RRGraphView& rr_graph, RRGraphBuilder& rr_graph_buil for (size_t node = 0; node < rr_graph.num_nodes(); ++node) { auto node_id = RRNodeId(node); - if (rr_graph.node_type((RRNodeId)node_id) != e_rr_type::SINK) + if (rr_graph.node_type((RRNodeId)node_id) != e_rr_type::SINK) { continue; + } int node_xlow = rr_graph.node_xlow(node_id); int node_ylow = rr_graph.node_ylow(node_id); @@ -164,13 +165,19 @@ void rr_set_sink_locs(const RRGraphView& rr_graph, RRGraphBuilder& rr_graph_buil // Skip "0x0" nodes; either the tile is 1x1, or we have seen the node on a previous call of this function // and its new location has already been set - if ((node_xhigh - node_xlow) == 0 && (node_yhigh - node_ylow) == 0) + if ((node_xhigh - node_xlow) == 0 && (node_yhigh - node_ylow) == 0) { + continue; + } + + const int node_layer = rr_graph.node_layer_low(node_id); + // Only CHANZ nodes spand across multiple layers. We're processing SINK nodes + if (node_layer != rr_graph.node_layer_high(node_id)) { continue; + } - int node_layer = rr_graph.node_layer(node_id); int node_ptc = rr_graph.node_ptc_num(node_id); - t_physical_tile_loc tile_loc = {node_xlow, node_ylow, node_layer}; + t_physical_tile_loc tile_loc{node_xlow, node_ylow, node_layer}; t_physical_tile_type_ptr tile_type = grid.get_physical_type(tile_loc); vtr::Rect tile_bb = grid.get_tile_bb(tile_loc); @@ -240,8 +247,8 @@ bool inter_layer_connections_limited_to_opin(const RRGraphView& rr_graph) { for (const RRNodeId from_node : rr_graph.nodes()) { for (t_edge_size edge : rr_graph.edges(from_node)) { RRNodeId to_node = rr_graph.edge_sink_node(from_node, edge); - int from_layer = rr_graph.node_layer(from_node); - int to_layer = rr_graph.node_layer(to_node); + int from_layer = rr_graph.node_layer_low(from_node); + int to_layer = rr_graph.node_layer_low(to_node); if (from_layer != to_layer) { if (rr_graph.node_type(from_node) != e_rr_type::OPIN) { @@ -272,6 +279,11 @@ bool chanx_chany_nodes_are_adjacent(const RRGraphView& rr_graph, RRNodeId node1, RRNodeId chanx_node = node1; RRNodeId chany_node = node2; + // If CHANX and CHANY nodes are not in the same layer, they are not adjacent + if (rr_graph.node_layer_low(chanx_node) != rr_graph.node_layer_low(chany_node)) { + return false; + } + // Check vertical (Y) adjacency if (rr_graph.node_ylow(chany_node) > rr_graph.node_ylow(chanx_node) + 1 || rr_graph.node_yhigh(chany_node) < rr_graph.node_ylow(chanx_node)) { @@ -332,13 +344,11 @@ bool chan_same_type_are_adjacent(const RRGraphView& rr_graph, RRNodeId node1, RR int xhigh1 = rr_graph.node_xhigh(node1); int ylow1 = rr_graph.node_ylow(node1); int yhigh1 = rr_graph.node_yhigh(node1); - int layer1 = rr_graph.node_layer(node1); int xlow2 = rr_graph.node_xlow(node2); int xhigh2 = rr_graph.node_xhigh(node2); int ylow2 = rr_graph.node_ylow(node2); int yhigh2 = rr_graph.node_yhigh(node2); - int layer2 = rr_graph.node_layer(node2); if (type == e_rr_type::CHANX) { if (ylow1 != ylow2) { @@ -376,8 +386,7 @@ bool chan_same_type_are_adjacent(const RRGraphView& rr_graph, RRNodeId node1, RR } else if (type == e_rr_type::CHANZ) { // Same X/Y span, adjacent layer bool same_xy = (xlow1 == xlow2 && xhigh1 == xhigh2 && ylow1 == ylow2 && yhigh1 == yhigh2); - bool adjacent_layer = std::abs(layer1 - layer2) == 1; - return same_xy && adjacent_layer; + return same_xy; } else { VTR_ASSERT_MSG(false, "Unexpected RR node type in chan_same_type_are_adjacent().\n"); } diff --git a/libs/librrgraph/src/base/rr_graph_view.h b/libs/librrgraph/src/base/rr_graph_view.h index b465c528586..6c0c34524b5 100644 --- a/libs/librrgraph/src/base/rr_graph_view.h +++ b/libs/librrgraph/src/base/rr_graph_view.h @@ -227,9 +227,19 @@ class RRGraphView { /** @brief Return the layer num of a specified node. */ - inline short node_layer(RRNodeId node) const { - return node_storage_.node_layer(node); + // inline short node_layer(RRNodeId node) const { + // return node_storage_.node_layer(node); + // } + + inline short node_layer_high(RRNodeId node) const { + return node_storage_.node_layer_high(node); + } + + inline short node_layer_low(RRNodeId node) const { + return node_storage_.node_layer_low(node); } + + /** * @brief Return the bend start of a specified node. @@ -368,7 +378,6 @@ class RRGraphView { std::string coordinate_string = node_type_string(node); //write the component's type as a routing resource node coordinate_string += ":" + std::to_string(size_t(node)) + " "; //add the index of the routing resource node - int node_layer_num = node_layer(node); if (node_type(node) == e_rr_type::OPIN || node_type(node) == e_rr_type::IPIN) { coordinate_string += "side: ("; //add the side of the routing resource node for (const e_side& node_side : TOTAL_2D_SIDES) { @@ -382,12 +391,12 @@ class RRGraphView { // and the end to the lower coordinate start_x = " (" + std::to_string(node_xhigh(node)) + ","; //start and end coordinates are the same for OPINs and IPINs start_y = std::to_string(node_yhigh(node)) + ","; - start_layer_str = std::to_string(node_layer_num) + ")"; + start_layer_str = std::to_string(node_layer_low(node)) + ")"; } else if (node_type(node) == e_rr_type::SOURCE || node_type(node) == e_rr_type::SINK) { // For SOURCE and SINK the starting and ending coordinate are identical, so just use start start_x = " (" + std::to_string(node_xhigh(node)) + ","; start_y = std::to_string(node_yhigh(node)) + ","; - start_layer_str = std::to_string(node_layer_num) + ")"; + start_layer_str = std::to_string(node_layer_low(node)) + ")"; } else if (node_type(node) == e_rr_type::CHANX || node_type(node) == e_rr_type::CHANY || node_type(node) == e_rr_type::CHANZ) { //for channels, we would like to describe the component with segment specific information RRIndexedDataId cost_index = node_cost_index(node); int seg_index = rr_indexed_data_[cost_index].seg_index; @@ -401,19 +410,19 @@ class RRGraphView { start_x = " (" + std::to_string(node_xhigh(node)) + ","; //start coordinates have large value start_y = std::to_string(node_yhigh(node)) + ","; - start_layer_str = std::to_string(node_layer_num) + ")"; + start_layer_str = std::to_string(node_layer_high(node)) + ")"; end_x = " (" + std::to_string(node_xlow(node)) + ","; //end coordinates have smaller value end_y = std::to_string(node_ylow(node)) + ","; - end_layer_str = std::to_string(node_layer_num) + ")"; + end_layer_str = std::to_string(node_layer_low(node)) + ")"; } else { // signal travels in increasing direction, stays at same point, or can travel both directions start_x = " (" + std::to_string(node_xlow(node)) + ","; //start coordinates have smaller value start_y = std::to_string(node_ylow(node)) + ","; - start_layer_str = std::to_string(node_layer_num) + ")"; + start_layer_str = std::to_string(node_layer_high(node)) + ")"; end_x = " (" + std::to_string(node_xhigh(node)) + ","; //end coordinates have larger value end_y = std::to_string(node_yhigh(node)) + ","; - end_layer_str = std::to_string(node_layer_num) + ")"; //layer number + end_layer_str = std::to_string(node_layer_high(node)) + ")"; //layer number if (node_direction(node) == Direction::BIDIR) { arrow = " <->"; //indicate that signal can travel both direction } diff --git a/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx.h b/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx.h index e6d3e3ff467..0dd0969e66e 100644 --- a/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx.h +++ b/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx.h @@ -4,9 +4,9 @@ * https://github.com/duck2/uxsdcxx * Modify only if your build process doesn't involve regenerating this file. * - * Cmdline: uxsdcxx/uxsdcxx.py /home/soheil/vpr_repos/libs/librrgraph/src/io/rr_graph.xsd - * Input file: /home/soheil/vpr_repos/libs/librrgraph/src/io/rr_graph.xsd - * md5sum of input file: 5d51b89242fe6e463629ac43a72e4606 + * Cmdline: uxsdcxx/uxsdcxx.py /home/soheil/vtr/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd + * Input file: /home/soheil/vtr/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd + * md5sum of input file: 040903603053940a1b24392c38663b59 */ #include @@ -275,8 +275,8 @@ constexpr const char *atok_lookup_t_grid_loc[] = {"block_type_id", "height_offse enum class gtok_t_grid_locs {GRID_LOC}; constexpr const char *gtok_lookup_t_grid_locs[] = {"grid_loc"}; -enum class atok_t_node_loc {LAYER, PTC, SIDE, XHIGH, XLOW, YHIGH, YLOW}; -constexpr const char *atok_lookup_t_node_loc[] = {"layer", "ptc", "side", "xhigh", "xlow", "yhigh", "ylow"}; +enum class atok_t_node_loc {LAYER_HIGH, LAYER_LOW, PTC, SIDE, XHIGH, XLOW, YHIGH, YLOW}; +constexpr const char *atok_lookup_t_node_loc[] = {"layer_high", "layer_low", "ptc", "side", "xhigh", "xlow", "yhigh", "ylow"}; enum class atok_t_node_timing {C, R}; @@ -1156,14 +1156,6 @@ inline atok_t_node_loc lex_attr_t_node_loc(const char *in, const std::function.").c_str()); @@ -1790,6 +1813,24 @@ inline enum_pin_type lex_enum_pin_type(const char *in, bool throw_on_invalid, co inline enum_node_type lex_enum_node_type(const char *in, bool throw_on_invalid, const std::function * report_error){ unsigned int len = strlen(in); switch(len){ + case 3: + switch(in[0]){ + case onechar('M', 0, 8): + switch(in[1]){ + case onechar('U', 0, 8): + switch(in[2]){ + case onechar('X', 0, 8): + return enum_node_type::MUX; + break; + default: break; + } + break; + default: break; + } + break; + default: break; + } + break; case 4: switch(*((triehash_uu32*)&in[0])){ case onechar('I', 0, 32) | onechar('P', 8, 32) | onechar('I', 16, 32) | onechar('N', 24, 32): @@ -2464,14 +2505,17 @@ inline void load_grid_loc_required_attributes(const pugi::xml_node &root, int * } inline void load_node_loc_required_attributes(const pugi::xml_node &root, int * xhigh, int * xlow, int * yhigh, int * ylow, const std::function * report_error){ - std::bitset<7> astate = 0; + std::bitset<8> astate = 0; for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ atok_t_node_loc in = lex_attr_t_node_loc(attr.name(), report_error); if(astate[(int)in] == 0) astate[(int)in] = 1; else noreturn_report(report_error, ("Duplicate attribute " + std::string(attr.name()) + " in .").c_str()); switch(in){ - case atok_t_node_loc::LAYER: - /* Attribute layer set after element init */ + case atok_t_node_loc::LAYER_HIGH: + /* Attribute layer_high set after element init */ + break; + case atok_t_node_loc::LAYER_LOW: + /* Attribute layer_low set after element init */ break; case atok_t_node_loc::PTC: /* Attribute ptc set after element init */ @@ -2494,7 +2538,7 @@ inline void load_node_loc_required_attributes(const pugi::xml_node &root, int * default: break; /* Not possible. */ } } - std::bitset<7> test_astate = astate | std::bitset<7>(0b0000101); + std::bitset<8> test_astate = astate | std::bitset<8>(0b00001011); if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_node_loc, report_error); } @@ -3409,8 +3453,11 @@ inline void load_node_loc(const pugi::xml_node &root, T &out, Context &context, for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ atok_t_node_loc in = lex_attr_t_node_loc(attr.name(), report_error); switch(in){ - case atok_t_node_loc::LAYER: - out.set_node_loc_layer(load_int(attr.value(), report_error), context); + case atok_t_node_loc::LAYER_HIGH: + out.set_node_loc_layer_high(load_int(attr.value(), report_error), context); + break; + case atok_t_node_loc::LAYER_LOW: + out.set_node_loc_layer_low(load_int(attr.value(), report_error), context); break; case atok_t_node_loc::PTC: out.set_node_loc_ptc(attr.value(), context); @@ -4152,7 +4199,8 @@ inline void write_node(T &in, std::ostream &os, Context &context){ { auto child_context = in.get_node_loc(context); os << " @@ -230,6 +230,8 @@ inline enum_node_type conv_enum_node_type(ucap::NodeType e, const std::function< return enum_node_type::OPIN; case ucap::NodeType::IPIN: return enum_node_type::IPIN; + case ucap::NodeType::MUX: + return enum_node_type::MUX; default: (*report_error)("Unknown enum_node_type"); throw std::runtime_error("Unreachable!"); @@ -254,6 +256,8 @@ inline ucap::NodeType conv_to_enum_node_type(enum_node_type e) { return ucap::NodeType::OPIN; case enum_node_type::IPIN: return ucap::NodeType::IPIN; + case enum_node_type::MUX: + return ucap::NodeType::MUX; default: throw std::runtime_error("Unknown enum_node_type"); } @@ -765,7 +769,8 @@ inline void load_node_loc_capnp_type(const ucap::NodeLoc::Reader &root, T &out, (void)report_error; (void)stack; - out.set_node_loc_layer(root.getLayer(), context); + out.set_node_loc_layer_high(root.getLayerHigh(), context); + out.set_node_loc_layer_low(root.getLayerLow(), context); out.set_node_loc_ptc(root.getPtc().cStr(), context); out.set_node_loc_side(conv_enum_loc_side(root.getSide(), report_error), context); } @@ -1223,7 +1228,8 @@ inline void write_node_capnp_type(T &in, ucap::Node::Builder &root, Context &con { auto child_context = in.get_node_loc(context); auto node_loc = root.initLoc(); - node_loc.setLayer(in.get_node_loc_layer(child_context)); + node_loc.setLayerHigh(in.get_node_loc_layer_high(child_context)); + node_loc.setLayerLow(in.get_node_loc_layer_low(child_context)); node_loc.setPtc(in.get_node_loc_ptc(child_context)); if((bool)in.get_node_loc_side(child_context)) node_loc.setSide(conv_to_enum_loc_side(in.get_node_loc_side(child_context))); diff --git a/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx_interface.h b/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx_interface.h index 7050b45c9cd..bbaae2e5e5f 100644 --- a/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx_interface.h +++ b/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx_interface.h @@ -4,9 +4,9 @@ * https://github.com/duck2/uxsdcxx * Modify only if your build process doesn't involve regenerating this file. * - * Cmdline: uxsdcxx/uxsdcxx.py /home/soheil/vpr_repos/libs/librrgraph/src/io/rr_graph.xsd - * Input file: /home/soheil/vpr_repos/libs/librrgraph/src/io/rr_graph.xsd - * md5sum of input file: 5d51b89242fe6e463629ac43a72e4606 + * Cmdline: uxsdcxx/uxsdcxx.py /home/soheil/vtr/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd + * Input file: /home/soheil/vtr/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd + * md5sum of input file: 040903603053940a1b24392c38663b59 */ #include @@ -371,7 +371,8 @@ class RrGraphBase { /** Generated for complex type "node_loc": * - * + * + * * * * @@ -380,8 +381,10 @@ class RrGraphBase { * * */ - virtual inline int get_node_loc_layer(typename ContextTypes::NodeLocReadContext &ctx) = 0; - virtual inline void set_node_loc_layer(int layer, typename ContextTypes::NodeLocWriteContext &ctx) = 0; + virtual inline int get_node_loc_layer_high(typename ContextTypes::NodeLocReadContext &ctx) = 0; + virtual inline void set_node_loc_layer_high(int layer_high, typename ContextTypes::NodeLocWriteContext &ctx) = 0; + virtual inline int get_node_loc_layer_low(typename ContextTypes::NodeLocReadContext &ctx) = 0; + virtual inline void set_node_loc_layer_low(int layer_low, typename ContextTypes::NodeLocWriteContext &ctx) = 0; virtual inline const char * get_node_loc_ptc(typename ContextTypes::NodeLocReadContext &ctx) = 0; virtual inline void set_node_loc_ptc(const char * ptc, typename ContextTypes::NodeLocWriteContext &ctx) = 0; virtual inline enum_loc_side get_node_loc_side(typename ContextTypes::NodeLocReadContext &ctx) = 0; diff --git a/libs/librrgraph/src/io/rr_graph.xsd b/libs/librrgraph/src/io/rr_graph.xsd index bff9f16c3f4..0d513a34924 100644 --- a/libs/librrgraph/src/io/rr_graph.xsd +++ b/libs/librrgraph/src/io/rr_graph.xsd @@ -277,7 +277,8 @@ - + + diff --git a/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h b/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h index ea09e79a818..2813600bb50 100644 --- a/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h +++ b/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h @@ -699,7 +699,8 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { rr_graph_builder_->set_node_coordinates(node_id, xlow, ylow, xhigh, yhigh); // We set the layer num 0 - If it is specified in the XML, it will be overwritten - rr_graph_builder_->set_node_layer(node_id, 0); + rr_graph_builder_->set_node_layer_low(node_id, 0); + rr_graph_builder_->set_node_layer_high(node_id, 0); return inode; } @@ -717,8 +718,11 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { temp_string_ = rr_graph_builder_->node_ptc_nums_to_string(node.id()); return temp_string_.c_str(); } - inline int get_node_loc_layer(const t_rr_node& node) final { - return rr_graph_->node_layer(node.id()); + inline int get_node_loc_layer_low(const t_rr_node& node) final { + return rr_graph_->node_layer_low(node.id()); + } + inline int get_node_loc_layer_high(const t_rr_node& node) final { + return rr_graph_->node_layer_high(node.id()); } inline int get_node_loc_xhigh(const t_rr_node& node) final { return rr_graph_->node_xhigh(node.id()); @@ -733,13 +737,20 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { return rr_graph_->node_ylow(node.id()); } - inline void set_node_loc_layer(int layer_num, int& inode) final { + inline void set_node_loc_layer_low(int layer_num, int& inode) final { auto node = (*rr_nodes_)[inode]; RRNodeId node_id = node.id(); + VTR_ASSERT(layer_num >= 0); + rr_graph_builder_->set_node_layer_low(node_id, layer_num); + } + + inline void set_node_loc_layer_high(int layer_num, int& inode) final { + auto node = (*rr_nodes_)[inode]; + RRNodeId node_id = node.id(); VTR_ASSERT(layer_num >= 0); - rr_graph_builder_->set_node_layer(node_id, layer_num); + rr_graph_builder_->set_node_layer_high(node_id, layer_num); } inline void set_node_loc_side(uxsd::enum_loc_side side, int& inode) final { @@ -1171,15 +1182,14 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { * use the pair data structure to keep the maximum*/ if (rr_graph.node_type(node.id()) == e_rr_type::CHANX || rr_graph.node_type(node.id()) == e_rr_type::CHANY) { if(rr_graph.node_type(RRNodeId(sink_node)) == e_rr_type::IPIN){ - if (rr_graph.node_layer(RRNodeId(sink_node)) == rr_graph.node_layer(RRNodeId(source_node))) { + if (rr_graph.node_layer_low(RRNodeId(sink_node)) == rr_graph.node_layer_low(RRNodeId(source_node))) { count_for_wire_to_ipin_switches[switch_id]++; if (count_for_wire_to_ipin_switches[switch_id] > most_frequent_switch.second) { most_frequent_switch.first = switch_id; most_frequent_switch.second = count_for_wire_to_ipin_switches[switch_id]; } - } - else{ - VTR_ASSERT(rr_graph.node_layer(RRNodeId(sink_node)) != rr_graph.node_layer(RRNodeId(source_node))); + } else{ + VTR_ASSERT(rr_graph.node_layer_low(RRNodeId(sink_node)) != rr_graph.node_layer_low(RRNodeId(source_node))); count_for_wire_to_ipin_switches_between_dice[switch_id]++; if(count_for_wire_to_ipin_switches_between_dice[switch_id] > most_frequent_switch_between_dice.second){ most_frequent_switch_between_dice.first = switch_id; diff --git a/libs/librrgraph/src/utils/describe_rr_node.cpp b/libs/librrgraph/src/utils/describe_rr_node.cpp index 16daa5c0718..2b439195296 100644 --- a/libs/librrgraph/src/utils/describe_rr_node.cpp +++ b/libs/librrgraph/src/utils/describe_rr_node.cpp @@ -30,7 +30,7 @@ std::string describe_rr_node(const RRGraphView& rr_graph, } else if (node_type == e_rr_type::IPIN || node_type == e_rr_type::OPIN) { t_physical_tile_type_ptr type = grid.get_physical_type({rr_graph.node_xlow(inode), rr_graph.node_ylow(inode), - rr_graph.node_layer(inode)}); + rr_graph.node_layer_low(inode)}); std::string pin_name = block_type_pin_index_to_name(type, rr_graph.node_pin_num(inode), is_flat); diff --git a/libs/libvtrcapnproto/gen/rr_graph_uxsdcxx.capnp b/libs/libvtrcapnproto/gen/rr_graph_uxsdcxx.capnp index 5df8cb2c04f..d43f8738382 100644 --- a/libs/libvtrcapnproto/gen/rr_graph_uxsdcxx.capnp +++ b/libs/libvtrcapnproto/gen/rr_graph_uxsdcxx.capnp @@ -2,11 +2,11 @@ # https://github.com/duck2/uxsdcxx # Modify only if your build process doesn't involve regenerating this file. # -# Cmdline: uxsdcxx/uxsdcap.py /home/soheil/vpr_repos/libs/librrgraph/src/io/rr_graph.xsd -# Input file: /home/soheil/vpr_repos/libs/librrgraph/src/io/rr_graph.xsd -# md5sum of input file: 5d51b89242fe6e463629ac43a72e4606 +# Cmdline: uxsdcxx/uxsdcap.py /home/soheil/vtr/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd +# Input file: /home/soheil/vtr/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd +# md5sum of input file: 040903603053940a1b24392c38663b59 -@0x8fe58c48975cfaf0; +@0xe7650575a8718aa2; using Cxx = import "/capnp/c++.capnp"; $Cxx.namespace("ucap"); @@ -41,6 +41,7 @@ enum NodeType { sink @5; opin @6; ipin @7; + mux @8; } enum NodeDirection { @@ -177,13 +178,14 @@ struct GridLocs { } struct NodeLoc { - layer @0 :Int32 = 0; - ptc @1 :Text; - side @2 :LocSide; - xhigh @3 :Int32; - xlow @4 :Int32; - yhigh @5 :Int32; - ylow @6 :Int32; + layerHigh @0 :Int32 = 0; + layerLow @1 :Int32 = 0; + ptc @2 :Text; + side @3 :LocSide; + xhigh @4 :Int32; + xlow @5 :Int32; + yhigh @6 :Int32; + ylow @7 :Int32; } struct NodeTiming { diff --git a/vpr/src/analysis/timing_reports.cpp b/vpr/src/analysis/timing_reports.cpp index 0c7a408ab4a..f30e22a5d09 100644 --- a/vpr/src/analysis/timing_reports.cpp +++ b/vpr/src/analysis/timing_reports.cpp @@ -38,8 +38,8 @@ static t_bb get_net_bounding_box(const AtomNetId atom_net_id) { bb.xmax = rr_graph.node_xhigh(route_tree_root); bb.ymin = rr_graph.node_ylow(route_tree_root); bb.ymax = rr_graph.node_yhigh(route_tree_root); - bb.layer_min = rr_graph.node_layer(route_tree_root); - bb.layer_max = rr_graph.node_layer(route_tree_root); + bb.layer_min = rr_graph.node_layer_low(route_tree_root); + bb.layer_max = rr_graph.node_layer_high(route_tree_root); // Iterate over all nodes in the route tree and update the bounding box for (auto& rt_node : route_tree.all_nodes()) { @@ -51,8 +51,8 @@ static t_bb get_net_bounding_box(const AtomNetId atom_net_id) { bb.ymin = std::min(static_cast(rr_graph.node_ylow(inode)), bb.ymin); bb.ymax = std::max(static_cast(rr_graph.node_yhigh(inode)), bb.ymax); - bb.layer_min = std::min(static_cast(rr_graph.node_layer(inode)), bb.layer_min); - bb.layer_max = std::max(static_cast(rr_graph.node_layer(inode)), bb.layer_max); + bb.layer_min = std::min(static_cast(rr_graph.node_layer_low(inode)), bb.layer_min); + bb.layer_max = std::max(static_cast(rr_graph.node_layer_high(inode)), bb.layer_max); } return bb; }; diff --git a/vpr/src/base/read_route.cpp b/vpr/src/base/read_route.cpp index 188b9697f5e..59cfac94bf8 100644 --- a/vpr/src/base/read_route.cpp +++ b/vpr/src/base/read_route.cpp @@ -692,17 +692,14 @@ void print_route(const Netlist<>& net_list, e_rr_type rr_type = rr_graph.node_type(inode); int ilow = rr_graph.node_xlow(inode); int jlow = rr_graph.node_ylow(inode); - int layer_num = rr_graph.node_layer(inode); + int layer_low = rr_graph.node_layer_low(inode); - fprintf(fp, "Node:\t%zu\t%6s (%d,%d,%d) ", size_t(inode), - rr_graph.node_type_string(inode), ilow, jlow, layer_num); + fprintf(fp, "Node:\t%zu\t%6s (%d,%d,%d) ", size_t(inode), rr_graph.node_type_string(inode), ilow, jlow, layer_low); - if (ilow != rr_graph.node_xhigh(inode) - || jlow != rr_graph.node_yhigh(inode)) - fprintf(fp, "to (%d,%d,%d) ", rr_graph.node_xhigh(inode), - rr_graph.node_yhigh(inode), layer_num); + if (ilow != rr_graph.node_xhigh(inode) || jlow != rr_graph.node_yhigh(inode) || layer_low != rr_graph.node_layer_high(inode)) + fprintf(fp, "to (%d,%d,%d) ", rr_graph.node_xhigh(inode), rr_graph.node_yhigh(inode), rr_graph.node_layer_high(inode)); - t_physical_tile_type_ptr physical_tile = device_ctx.grid.get_physical_type({ilow, jlow, layer_num}); + t_physical_tile_type_ptr physical_tile = device_ctx.grid.get_physical_type({ilow, jlow, layer_low}); switch (rr_type) { case e_rr_type::IPIN: @@ -745,13 +742,13 @@ void print_route(const Netlist<>& net_list, if (!physical_tile->is_io() && (rr_type == e_rr_type::IPIN || rr_type == e_rr_type::OPIN)) { int pin_num = rr_graph.node_pin_num(inode); - int xoffset = device_ctx.grid.get_width_offset({ilow, jlow, layer_num}); - int yoffset = device_ctx.grid.get_height_offset({ilow, jlow, layer_num}); + int xoffset = device_ctx.grid.get_width_offset({ilow, jlow, layer_low}); + int yoffset = device_ctx.grid.get_height_offset({ilow, jlow, layer_low}); auto [sub_tile, sub_tile_rel_cap] = get_sub_tile_from_pin_physical_num(physical_tile, pin_num); int sub_tile_offset = sub_tile->capacity.low + sub_tile_rel_cap; ClusterBlockId iblock = grid_blocks.block_at_location({ilow - xoffset, jlow - yoffset, - sub_tile_offset, layer_num}); + sub_tile_offset, layer_low}); VTR_ASSERT(iblock); const t_pb_graph_pin* pb_pin; if (is_pin_on_tile(physical_tile, pin_num)) { diff --git a/vpr/src/base/stats.cpp b/vpr/src/base/stats.cpp index 033fed6f2c3..b8e139079a2 100644 --- a/vpr/src/base/stats.cpp +++ b/vpr/src/base/stats.cpp @@ -63,12 +63,12 @@ static void get_channel_occupancy_stats(const Netlist<>& net_list, bool /***/); void routing_stats(const Netlist<>& net_list, bool full_stats, - enum e_route_type route_type, + e_route_type route_type, std::vector& segment_inf, float R_minW_nmos, float R_minW_pmos, float grid_logic_tile_area, - enum e_directionality directionality, + e_directionality directionality, int wire_to_ipin_switch, bool is_flat) { auto& device_ctx = g_vpr_ctx.device(); @@ -130,12 +130,12 @@ std::pair, vtr::NdMatrix> calculate_channel_width( const auto& device_ctx = g_vpr_ctx.device(); const auto& rr_graph = device_ctx.rr_graph; - auto chanx_width = vtr::NdMatrix({{(size_t)device_ctx.grid.get_num_layers(), + auto chanx_width = vtr::NdMatrix({{device_ctx.grid.get_num_layers(), device_ctx.grid.width(), device_ctx.grid.height()}}, 0); - auto chany_width = vtr::NdMatrix({{(size_t)device_ctx.grid.get_num_layers(), + auto chany_width = vtr::NdMatrix({{device_ctx.grid.get_num_layers(), device_ctx.grid.width(), device_ctx.grid.height()}}, 0); @@ -145,13 +145,13 @@ std::pair, vtr::NdMatrix> calculate_channel_width( if (rr_type == e_rr_type::CHANX) { int y = rr_graph.node_ylow(node_id); - int layer = rr_graph.node_layer(node_id); + int layer = rr_graph.node_layer_low(node_id); for (int x = rr_graph.node_xlow(node_id); x <= rr_graph.node_xhigh(node_id); x++) { chanx_width[layer][x][y] += rr_graph.node_capacity(node_id); } } else if (rr_type == e_rr_type::CHANY) { int x = rr_graph.node_xlow(node_id); - int layer = rr_graph.node_layer(node_id); + int layer = rr_graph.node_layer_low(node_id); for (int y = rr_graph.node_ylow(node_id); y <= rr_graph.node_yhigh(node_id); y++) { chany_width[layer][x][y] += rr_graph.node_capacity(node_id); } diff --git a/vpr/src/base/stats.h b/vpr/src/base/stats.h index 08b9e4d1d13..e986827fd4d 100644 --- a/vpr/src/base/stats.h +++ b/vpr/src/base/stats.h @@ -14,12 +14,12 @@ class DeviceGrid; */ void routing_stats(const Netlist<>& net_list, bool full_stats, - enum e_route_type route_type, + e_route_type route_type, std::vector& segment_inf, float R_minW_nmos, float R_minW_pmos, float grid_logic_tile_area, - enum e_directionality directionality, + e_directionality directionality, int wire_to_ipin_switch, bool is_flat); diff --git a/vpr/src/draw/draw_basic.cpp b/vpr/src/draw/draw_basic.cpp index 90452e6f1c2..5bca8a47843 100644 --- a/vpr/src/draw/draw_basic.cpp +++ b/vpr/src/draw/draw_basic.cpp @@ -272,7 +272,7 @@ void draw_congestion(ezgl::renderer* g) { //Record min/max congestion float min_congestion_ratio = 1.; float max_congestion_ratio = min_congestion_ratio; - auto congested_rr_nodes = collect_congested_rr_nodes(); + std::vector congested_rr_nodes = collect_congested_rr_nodes(); for (RRNodeId inode : congested_rr_nodes) { short occ = route_ctx.rr_node_route_inf[inode].occ(); short capacity = rr_graph.node_capacity(inode); @@ -333,7 +333,7 @@ void draw_congestion(ezgl::renderer* g) { //Draw each congested node for (RRNodeId inode : congested_rr_nodes) { - int layer_num = rr_graph.node_layer(inode); + int layer_num = rr_graph.node_layer_low(inode); int transparency_factor = get_rr_node_transparency(inode); if (!draw_state->draw_layer_display[layer_num].visible) continue; @@ -663,8 +663,8 @@ bool is_edge_valid_to_draw(RRNodeId current_node, RRNodeId prev_node) { t_draw_state* draw_state = get_draw_state_vars(); const RRGraphView& rr_graph = g_vpr_ctx.device().rr_graph; - int current_node_layer = rr_graph.node_layer(current_node); - int prev_node_layer = rr_graph.node_layer(prev_node); + int current_node_layer = rr_graph.node_layer_low(current_node); + int prev_node_layer = rr_graph.node_layer_low(prev_node); if (!(is_inter_cluster_node(rr_graph, current_node)) || !(is_inter_cluster_node(rr_graph, prev_node))) { return false; diff --git a/vpr/src/draw/draw_rr.cpp b/vpr/src/draw/draw_rr.cpp index 2bc7f81b168..a955543a340 100644 --- a/vpr/src/draw/draw_rr.cpp +++ b/vpr/src/draw/draw_rr.cpp @@ -358,7 +358,7 @@ void draw_rr_node(RRNodeId inode, const ezgl::color color, ezgl::renderer* g) { const RRGraphView& rr_graph = device_ctx.rr_graph; e_rr_type rr_type = rr_graph.node_type(inode); bool inode_inter_cluster = is_inter_cluster_node(rr_graph, inode); - int node_layer = rr_graph.node_layer(inode); + int node_layer = rr_graph.node_layer_low(inode); // For 3D architectures, draw only visible layers if (!draw_state->draw_layer_display[node_layer].visible) { @@ -480,7 +480,7 @@ void draw_get_rr_src_sink_coords(const t_rr_node& node, float* xcen, float* ycen RRNodeId rr_node = node.id(); t_physical_tile_type_ptr tile_type = device_ctx.grid.get_physical_type({rr_graph.node_xlow(rr_node), rr_graph.node_ylow(rr_node), - rr_graph.node_layer(rr_node)}); + rr_graph.node_layer_low(rr_node)}); //Number of classes (i.e. src/sinks) we need to draw float num_class = tile_type->class_inf.size(); @@ -569,8 +569,8 @@ RRNodeId draw_check_rr_node_hit(float click_x, float click_y) { const DeviceContext& device_ctx = g_vpr_ctx.device(); const RRGraphView& rr_graph = device_ctx.rr_graph; - for (const RRNodeId& inode : device_ctx.rr_graph.nodes()) { - int layer_num = rr_graph.node_layer(inode); + for (const RRNodeId inode : device_ctx.rr_graph.nodes()) { + int layer_num = rr_graph.node_layer_low(inode); if (!draw_state->draw_layer_display[layer_num].visible) { continue; /* Don't check RR nodes on currently invisible layers*/ } @@ -715,7 +715,7 @@ void draw_rr_costs(ezgl::renderer* g, const vtr::vector& rr_cos int transparency_factor = get_rr_node_transparency(inode); // continue if rr_node layer is not visible - int layer_num = rr_graph.node_layer(inode); + int layer_num = rr_graph.node_layer_low(inode); if (!draw_state->draw_layer_display[layer_num].visible) continue; @@ -771,7 +771,7 @@ void draw_get_rr_pin_coords(const t_rr_node& node, float* xcen, float* ycen, con i = rr_graph.node_xlow(rr_node); j = rr_graph.node_ylow(rr_node); - int layer_num = rr_graph.node_layer(rr_node); + int layer_num = rr_graph.node_layer_low(rr_node); xc = draw_coords->tile_x[i]; yc = draw_coords->tile_y[j]; @@ -823,7 +823,7 @@ int get_rr_node_transparency(RRNodeId rr_node) { const DeviceContext& device_ctx = g_vpr_ctx.device(); const RRGraphView& rr_graph = device_ctx.rr_graph; - int layer_num = rr_graph.node_layer(rr_node); + int layer_num = rr_graph.node_layer_low(rr_node); return draw_state->draw_layer_display[layer_num].alpha; } diff --git a/vpr/src/draw/draw_rr_edges.cpp b/vpr/src/draw/draw_rr_edges.cpp index a9caa433407..929aacbc9d2 100644 --- a/vpr/src/draw/draw_rr_edges.cpp +++ b/vpr/src/draw/draw_rr_edges.cpp @@ -418,7 +418,7 @@ e_side get_pin_side(RRNodeId pin_node, RRNodeId chan_node) { t_physical_tile_loc tile_loc = { rr_graph.node_xlow(pin_node), rr_graph.node_ylow(pin_node), - rr_graph.node_layer(pin_node)}; + rr_graph.node_layer_low(pin_node)}; const auto& grid_type = device_ctx.grid.get_physical_type(tile_loc); int width_offset = device_ctx.grid.get_width_offset(tile_loc); @@ -508,7 +508,7 @@ void draw_pin_to_chan_edge(RRNodeId pin_node, RRNodeId chan_node, ezgl::renderer t_physical_tile_loc tile_loc = { rr_graph.node_xlow(pin_node), rr_graph.node_ylow(pin_node), - rr_graph.node_layer(pin_node)}; + rr_graph.node_layer_low(pin_node)}; const auto& grid_type = device_ctx.grid.get_physical_type(tile_loc); const e_rr_type channel_type = rr_graph.node_type(chan_node); @@ -605,11 +605,11 @@ void draw_rr_edge(RRNodeId inode, RRNodeId prev_node, ezgl::color color, ezgl::r e_rr_type rr_type = rr_graph.node_type(inode); bool inode_inter_cluster = is_inter_cluster_node(rr_graph, inode); - int current_node_layer = rr_graph.node_layer(inode); + int current_node_layer = rr_graph.node_layer_low(inode); e_rr_type prev_type = rr_graph.node_type(prev_node); bool prev_node_inter_cluster = is_inter_cluster_node(rr_graph, prev_node); - int prev_node_layer = rr_graph.node_layer(prev_node); + int prev_node_layer = rr_graph.node_layer_low(prev_node); t_draw_layer_display edge_visibility = get_element_visibility_and_transparency(prev_node_layer, current_node_layer); diff --git a/vpr/src/draw/search_bar.cpp b/vpr/src/draw/search_bar.cpp index af194987451..e3c9586f072 100644 --- a/vpr/src/draw/search_bar.cpp +++ b/vpr/src/draw/search_bar.cpp @@ -269,7 +269,7 @@ void auto_zoom_rr_node(RRNodeId rr_node_id) { t_physical_tile_loc tile_loc = { rr_graph.node_xlow(rr_node_id), rr_graph.node_ylow(rr_node_id), - rr_graph.node_layer(rr_node_id)}; + rr_graph.node_layer_low(rr_node_id)}; t_physical_tile_type_ptr type = device_ctx.grid.get_physical_type(tile_loc); int width_offset = device_ctx.grid.get_width_offset(tile_loc); int height_offset = device_ctx.grid.get_height_offset(tile_loc); diff --git a/vpr/src/pack/sync_netlists_to_routing_flat.cpp b/vpr/src/pack/sync_netlists_to_routing_flat.cpp index e1da710d40b..7e03d3b8fd8 100644 --- a/vpr/src/pack/sync_netlists_to_routing_flat.cpp +++ b/vpr/src/pack/sync_netlists_to_routing_flat.cpp @@ -51,7 +51,7 @@ inline ClusterBlockId get_cluster_block_from_rr_node(RRNodeId inode) { t_physical_tile_loc node_phy_tile_loc(rr_graph.node_xlow(inode), rr_graph.node_ylow(inode), - rr_graph.node_layer(inode)); + rr_graph.node_layer_low(inode)); auto physical_tile = device_ctx.grid.get_physical_type(node_phy_tile_loc); int source_pin = rr_graph.node_pin_num(inode); @@ -67,7 +67,7 @@ inline ClusterBlockId get_cluster_block_from_rr_node(RRNodeId inode) { ClusterBlockId clb = place_ctx.grid_blocks().block_at_location({rr_graph.node_xlow(inode) - width_offset, rr_graph.node_ylow(inode) - height_offset, subtile, - rr_graph.node_layer(inode)}); + rr_graph.node_layer_low(inode)}); return clb; } @@ -207,7 +207,7 @@ static void sync_pb_routes_to_routing(void) { ClusterBlockId clb = get_cluster_block_from_rr_node(source_inode); auto physical_tile = device_ctx.grid.get_physical_type({rr_graph.node_xlow(source_inode), rr_graph.node_ylow(source_inode), - rr_graph.node_layer(source_inode)}); + rr_graph.node_layer_low(source_inode)}); int source_pin = rr_graph.node_pin_num(source_inode); int sink_pin = rr_graph.node_pin_num(sink_inode); @@ -329,7 +329,7 @@ static void sync_clustered_netlist_to_routing(void) { auto physical_tile = device_ctx.grid.get_physical_type({rr_graph.node_xlow(rt_node.inode), rr_graph.node_ylow(rt_node.inode), - rr_graph.node_layer(rt_node.inode)}); + rr_graph.node_layer_low(rt_node.inode)}); int pin_index = rr_graph.node_pin_num(rt_node.inode); diff --git a/vpr/src/place/net_cost_handler.cpp b/vpr/src/place/net_cost_handler.cpp index a8adccadb35..243bd0cba88 100644 --- a/vpr/src/place/net_cost_handler.cpp +++ b/vpr/src/place/net_cost_handler.cpp @@ -197,28 +197,18 @@ void NetCostHandler::alloc_and_load_for_fast_vertical_cost_update_() { * if someday we have architectures with widely varying connectivity between different layers in a stack. */ - /* - * To calculate the accumulative number of inter-die connections we first need to get the number of + /* To calculate the accumulative number of inter-die connections we first need to get the number of * inter-die connection per location. To be able to work for the cases that RR Graph is read instead * of being made from the architecture file, we calculate this number by iterating over the RR graph. Once - * tile_num_inter_die_conn is populated, we can start populating acc_tile_num_inter_die_conn_. First, - * we populate the first row and column. Then, we iterate over the rest of blocks and get the number of - * inter-die connections by adding up the number of inter-die block at that location + the accumulation - * for the block below and left to it. Then, since the accumulated number of inter-die connection to - * the block on the lower left connection of the block is added twice, that part needs to be removed. + * tile_num_inter_die_conn is populated, we can start populating acc_tile_num_inter_die_conn_. */ - for (const RRNodeId src_rr_node : rr_graph.nodes()) { - for (const t_edge_size rr_edge_idx : rr_graph.edges(src_rr_node)) { - const RRNodeId sink_rr_node = rr_graph.edge_sink_node(src_rr_node, rr_edge_idx); - if (rr_graph.node_layer(src_rr_node) != rr_graph.node_layer(sink_rr_node)) { - // We assume that the nodes driving the inter-layer connection or being driven by it - // are not stretched across multiple tiles - int src_x = rr_graph.node_xhigh(src_rr_node); - int src_y = rr_graph.node_yhigh(src_rr_node); - VTR_ASSERT(rr_graph.node_xlow(src_rr_node) == src_x && rr_graph.node_ylow(src_rr_node) == src_y); - - tile_num_inter_die_conn[src_x][src_y]++; - } + + for (const RRNodeId node : rr_graph.nodes()) { + if (rr_graph.node_type(node) == e_rr_type::CHANZ) { + int x = rr_graph.node_xlow(node); + int y = rr_graph.node_ylow(node); + VTR_ASSERT_SAFE(x == rr_graph.node_xhigh(node) && y == rr_graph.node_yhigh(node)); + tile_num_inter_die_conn[x][y]++; } } diff --git a/vpr/src/route/DecompNetlistRouter.tpp b/vpr/src/route/DecompNetlistRouter.tpp index 21d800ec0b3..7198ade89f3 100644 --- a/vpr/src/route/DecompNetlistRouter.tpp +++ b/vpr/src/route/DecompNetlistRouter.tpp @@ -450,7 +450,7 @@ inline bool is_close_to_cutline(RRNodeId inode, Axis cutline_axis, int cutline_p vtr::Rect tile_bb = device_ctx.grid.get_tile_bb({rr_graph.node_xlow(inode), rr_graph.node_ylow(inode), - rr_graph.node_layer(inode)}); + rr_graph.node_layer_low(inode)}); /* Cutlines are considered to be at x + 0.5, set a thickness of +1 here by checking for equality */ if (cutline_axis == Axis::X) { @@ -467,7 +467,7 @@ inline bool is_close_to_bb(RRNodeId inode, const t_bb& bb, int thickness) { vtr::Rect tile_bb = device_ctx.grid.get_tile_bb({rr_graph.node_xlow(inode), rr_graph.node_ylow(inode), - rr_graph.node_layer(inode)}); + rr_graph.node_layer_low(inode)}); int xlow = tile_bb.xmin() - thickness; int ylow = tile_bb.ymin() - thickness; diff --git a/vpr/src/route/check_route.cpp b/vpr/src/route/check_route.cpp index b4153c40fd0..2c6613d1a99 100644 --- a/vpr/src/route/check_route.cpp +++ b/vpr/src/route/check_route.cpp @@ -304,8 +304,8 @@ static bool check_adjacent(RRNodeId from_node, RRNodeId to_node, bool is_flat) { return false; } - /* Now we know the rr graph says these two nodes are adjacent. Double * - * check that this makes sense, to verify the rr graph. */ + // Now we know the rr graph says these two nodes are adjacent. Double + // check that this makes sense, to verify the rr graph. VTR_ASSERT(reached); int num_adj = 0; @@ -313,14 +313,14 @@ static bool check_adjacent(RRNodeId from_node, RRNodeId to_node, bool is_flat) { auto from_rr = RRNodeId(from_node); auto to_rr = RRNodeId(to_node); e_rr_type from_type = rr_graph.node_type(from_rr); - int from_layer = rr_graph.node_layer(from_rr); + int from_layer = rr_graph.node_layer_low(from_rr); int from_xlow = rr_graph.node_xlow(from_rr); int from_ylow = rr_graph.node_ylow(from_rr); int from_xhigh = rr_graph.node_xhigh(from_rr); int from_yhigh = rr_graph.node_yhigh(from_rr); int from_ptc = rr_graph.node_ptc_num(from_rr); e_rr_type to_type = rr_graph.node_type(to_rr); - int to_layer = rr_graph.node_layer(to_rr); + int to_layer = rr_graph.node_layer_low(to_rr); int to_xlow = rr_graph.node_xlow(to_rr); int to_ylow = rr_graph.node_ylow(to_rr); int to_xhigh = rr_graph.node_xhigh(to_rr); diff --git a/vpr/src/route/connection_router.tpp b/vpr/src/route/connection_router.tpp index 36a80052983..b22a879706b 100644 --- a/vpr/src/route/connection_router.tpp +++ b/vpr/src/route/connection_router.tpp @@ -178,7 +178,7 @@ void ConnectionRouter::timing_driven_route_connection_from_heap(RRNodeId s if (rr_graph_->node_type(sink_node) == e_rr_type::SINK) { // We need to get a bounding box for the sink's entire tile vtr::Rect tile_bb = grid_.get_tile_bb({rr_graph_->node_xlow(sink_node), rr_graph_->node_ylow(sink_node), - rr_graph_->node_layer(sink_node)}); + rr_graph_->node_layer_low(sink_node)}); target_bb.xmin = tile_bb.xmin(); target_bb.ymin = tile_bb.ymin(); @@ -191,8 +191,8 @@ void ConnectionRouter::timing_driven_route_connection_from_heap(RRNodeId s target_bb.ymax = rr_graph_->node_yhigh(sink_node); } - target_bb.layer_min = rr_graph_->node_layer(RRNodeId(sink_node)); - target_bb.layer_max = rr_graph_->node_layer(RRNodeId(sink_node)); + target_bb.layer_min = rr_graph_->node_layer_low(RRNodeId(sink_node)); + target_bb.layer_max = rr_graph_->node_layer_high(RRNodeId(sink_node)); // Start measuring path search time std::chrono::steady_clock::time_point begin_time = std::chrono::steady_clock::now(); @@ -408,8 +408,8 @@ inline void expand_highfanout_bounding_box(t_bb& bb, const t_bb& net_bb, RRNodeI bb.ymin = std::max(net_bb.ymin, std::min(bb.ymin, rr_graph->node_ylow(inode))); bb.xmax = std::min(net_bb.xmax, std::max(bb.xmax, rr_graph->node_xhigh(inode))); bb.ymax = std::min(net_bb.ymax, std::max(bb.ymax, rr_graph->node_yhigh(inode))); - bb.layer_min = std::min(bb.layer_min, rr_graph->node_layer(inode)); - bb.layer_max = std::max(bb.layer_max, rr_graph->node_layer(inode)); + bb.layer_min = std::min(bb.layer_min, rr_graph->node_layer_low(inode)); + bb.layer_max = std::max(bb.layer_max, rr_graph->node_layer_high(inode)); } /* Expand bb by HIGH_FANOUT_BB_FAC and clip against net_bb */ @@ -446,7 +446,7 @@ t_bb ConnectionRouter::add_high_fanout_route_tree_to_heap( int target_bin_x = grid_to_bin_x(rr_graph_->node_xlow(target_node), spatial_rt_lookup); int target_bin_y = grid_to_bin_y(rr_graph_->node_ylow(target_node), spatial_rt_lookup); - auto target_layer = rr_graph_->node_layer(target_node); + short target_layer = rr_graph_->node_layer_low(target_node); int chan_nodes_added = 0; @@ -455,8 +455,8 @@ t_bb ConnectionRouter::add_high_fanout_route_tree_to_heap( highfanout_bb.xmax = rr_graph_->node_xhigh(target_node); highfanout_bb.ymin = rr_graph_->node_ylow(target_node); highfanout_bb.ymax = rr_graph_->node_yhigh(target_node); - highfanout_bb.layer_min = target_layer; - highfanout_bb.layer_max = target_layer; + highfanout_bb.layer_min = rr_graph_->node_layer_low(target_node); + highfanout_bb.layer_max = rr_graph_->node_layer_high(target_node); //Add existing routing starting from the target bin. //If the target's bin has insufficient existing routing add from the surrounding bins @@ -489,7 +489,7 @@ t_bb ConnectionRouter::add_high_fanout_route_tree_to_heap( if (!inside_bb(rr_node_to_add, net_bounding_box)) continue; - auto rt_node_layer_num = rr_graph_->node_layer(rr_node_to_add); + auto rt_node_layer_num = rr_graph_->node_layer_low(rr_node_to_add); if (rt_node_layer_num == target_layer) found_node_on_same_layer = true; diff --git a/vpr/src/route/overuse_report.cpp b/vpr/src/route/overuse_report.cpp index 63025630184..bd958ff79af 100644 --- a/vpr/src/route/overuse_report.cpp +++ b/vpr/src/route/overuse_report.cpp @@ -17,10 +17,16 @@ */ static void generate_node_to_net_lookup(const Netlist<>& net_list, std::map>& rr_node_to_net_map); + +///@brief Print out information specific to IPIN/OPIN type rr nodes static void report_overused_ipin_opin(std::ostream& os, RRNodeId node_id, const std::map>& rr_node_to_net_map); + +///@brief Print out information specific to CHANX/CHANY type rr nodes static void report_overused_chanx_chany(std::ostream& os, RRNodeId node_id); + +///@brief Print out information specific to SOURCE/SINK type rr nodes static void report_overused_source_sink(std::ostream& os, RRNodeId node_id); static void report_congested_nets(const Netlist<>& net_list, const AtomLookup& atom_lookup, @@ -112,7 +118,7 @@ void report_overused_nodes(const Netlist<>& net_list, size_t inode = 0; for (const auto& lookup_pair : over_used_nodes_to_nets_lookup) { const RRNodeId node_id = lookup_pair.first; - const auto& congested_nets = lookup_pair.second; + const std::set& congested_nets = lookup_pair.second; os << "************************************************\n\n"; //Separation line @@ -123,12 +129,12 @@ void report_overused_nodes(const Netlist<>& net_list, os << "Capacity = " << rr_graph.node_capacity(node_id) << "\n\n"; /* Report selective info based on the rr node type */ - auto node_type = rr_graph.node_type(node_id); + e_rr_type node_type = rr_graph.node_type(node_id); os << "Node type = " << rr_graph.node_type_string(node_id) << '\n'; bool report_sinks = false; int x = rr_graph.node_xlow(node_id); int y = rr_graph.node_ylow(node_id); - int layer_num = rr_graph.node_layer(node_id); + int layer_num = rr_graph.node_layer_low(node_id); switch (node_type) { case e_rr_type::IPIN: case e_rr_type::OPIN: @@ -149,6 +155,8 @@ void report_overused_nodes(const Netlist<>& net_list, report_sinks = true; break; + // TODO: handle CHANZ nodes + default: break; } @@ -219,7 +227,6 @@ static void generate_node_to_net_lookup(const Netlist<>& net_list, } } -///@brief Print out information specific to IPIN/OPIN type rr nodes static void report_overused_ipin_opin(std::ostream& os, RRNodeId node_id, const std::map>& rr_node_to_net_map) { @@ -230,7 +237,7 @@ static void report_overused_ipin_opin(std::ostream& os, t_physical_tile_loc grid_loc; grid_loc.x = rr_graph.node_xlow(node_id); grid_loc.y = rr_graph.node_ylow(node_id); - grid_loc.layer_num = rr_graph.node_layer(node_id); + grid_loc.layer_num = rr_graph.node_layer_low(node_id); const t_physical_tile_type_ptr physical_type = device_ctx.grid.get_physical_type(grid_loc); VTR_ASSERT_MSG(grid_loc.x == rr_graph.node_xhigh(node_id) && grid_loc.y == rr_graph.node_yhigh(node_id), @@ -276,7 +283,6 @@ static void report_overused_ipin_opin(std::ostream& os, } } -///@brief Print out information specific to CHANX/CHANY type rr nodes static void report_overused_chanx_chany(std::ostream& os, RRNodeId node_id) { const auto& device_ctx = g_vpr_ctx.device(); const auto& rr_graph = device_ctx.rr_graph; @@ -290,7 +296,6 @@ static void report_overused_chanx_chany(std::ostream& os, RRNodeId node_id) { os << rr_graph.node_coordinate_to_string(node_id) << '\n'; } -///@brief Print out information specific to SOURCE/SINK type rr nodes static void report_overused_source_sink(std::ostream& os, RRNodeId node_id) { const auto& device_ctx = g_vpr_ctx.device(); const auto& rr_graph = device_ctx.rr_graph; @@ -391,11 +396,11 @@ static void log_single_overused_node_status(int overuse_index, RRNodeId node_id) const auto& route_ctx = g_vpr_ctx.routing(); int x = rr_graph.node_xlow(node_id); int y = rr_graph.node_ylow(node_id); - int layer_num = rr_graph.node_layer(node_id); - auto physical_blk = device_ctx.grid.get_physical_type({x, y, layer_num}); + int layer_num = rr_graph.node_layer_low(node_id); + t_physical_tile_type_ptr physical_blk = device_ctx.grid.get_physical_type({x, y, layer_num}); //Determines if direction or side is available for printing - auto node_type = rr_graph.node_type(node_id); + e_rr_type node_type = rr_graph.node_type(node_id); //Overuse # VTR_LOG("%6d", overuse_index); diff --git a/vpr/src/route/parallel_connection_router.cpp b/vpr/src/route/parallel_connection_router.cpp index 8fdba6acd38..2016b40f390 100644 --- a/vpr/src/route/parallel_connection_router.cpp +++ b/vpr/src/route/parallel_connection_router.cpp @@ -332,7 +332,7 @@ void ParallelConnectionRouter::timing_driven_expand_neighbour(const RTExpl // IPIN's of the target block should be contained within it's bounding box int to_xlow = this->rr_graph_->node_xlow(to_node); int to_ylow = this->rr_graph_->node_ylow(to_node); - int to_layer = this->rr_graph_->node_layer(to_node); + int to_layer = this->rr_graph_->node_layer_low(to_node); int to_xhigh = this->rr_graph_->node_xhigh(to_node); int to_yhigh = this->rr_graph_->node_yhigh(to_node); if (to_xlow < target_bb.xmin diff --git a/vpr/src/route/route_common.cpp b/vpr/src/route/route_common.cpp index e32fc4d490a..a12cd5e2187 100644 --- a/vpr/src/route/route_common.cpp +++ b/vpr/src/route/route_common.cpp @@ -456,7 +456,7 @@ static float comp_initial_acc_cost(RRNodeId node_id, if (rr_type == e_rr_type::CHANX) { int y = rr_graph.node_ylow(node_id); - int layer = rr_graph.node_layer(node_id); + int layer = rr_graph.node_layer_low(node_id); for (int x = rr_graph.node_xlow(node_id); x <= rr_graph.node_xhigh(node_id); x++) { max_util = std::max(max_util, chanx_util[layer][x][y]); } @@ -464,7 +464,7 @@ static float comp_initial_acc_cost(RRNodeId node_id, } else { VTR_ASSERT_SAFE(rr_type == e_rr_type::CHANY); int x = rr_graph.node_xlow(node_id); - int layer = rr_graph.node_layer(node_id); + int layer = rr_graph.node_layer_low(node_id); for (int y = rr_graph.node_ylow(node_id); y <= rr_graph.node_yhigh(node_id); y++) { max_util = std::max(max_util, chany_util[layer][x][y]); } @@ -777,8 +777,8 @@ t_bb load_net_route_bb(const Netlist<>& net_list, int ymin = rr_graph.node_ylow(driver_rr); int xmax = rr_graph.node_xhigh(driver_rr); int ymax = rr_graph.node_yhigh(driver_rr); - int layer_min = rr_graph.node_layer(driver_rr); - int layer_max = rr_graph.node_layer(driver_rr); + int layer_min = rr_graph.node_layer_low(driver_rr); + int layer_max = rr_graph.node_layer_high(driver_rr); auto net_sinks = net_list.net_sinks(net_id); for (size_t ipin = 1; ipin < net_sinks.size() + 1; ++ipin) { //Start at 1 since looping through sinks @@ -788,19 +788,19 @@ t_bb load_net_route_bb(const Netlist<>& net_list, VTR_ASSERT(rr_graph.node_xlow(sink_rr) <= rr_graph.node_xhigh(sink_rr)); VTR_ASSERT(rr_graph.node_ylow(sink_rr) <= rr_graph.node_yhigh(sink_rr)); - VTR_ASSERT(rr_graph.node_layer(sink_rr) >= 0); - VTR_ASSERT(rr_graph.node_layer(sink_rr) <= (int)device_ctx.grid.get_num_layers() - 1); + VTR_ASSERT(rr_graph.node_layer_low(sink_rr) >= 0); + VTR_ASSERT(rr_graph.node_layer_low(sink_rr) <= (int)device_ctx.grid.get_num_layers() - 1); vtr::Rect tile_bb = device_ctx.grid.get_tile_bb({rr_graph.node_xlow(sink_rr), rr_graph.node_ylow(sink_rr), - rr_graph.node_layer(sink_rr)}); + rr_graph.node_layer_low(sink_rr)}); xmin = std::min(xmin, tile_bb.xmin()); xmax = std::max(xmax, tile_bb.xmax()); ymin = std::min(ymin, tile_bb.ymin()); ymax = std::max(ymax, tile_bb.ymax()); - layer_min = std::min(layer_min, rr_graph.node_layer(sink_rr)); - layer_max = std::max(layer_max, rr_graph.node_layer(sink_rr)); + layer_min = std::min(layer_min, rr_graph.node_layer_low(sink_rr)); + layer_max = std::max(layer_max, rr_graph.node_layer_high(sink_rr)); } // Want the channels on all 4 sides to be usable, even if bb_factor = 0. @@ -869,7 +869,7 @@ void reserve_locally_used_opins(HeapInterface* heap, float pres_fac, float acc_f auto port_eq = get_port_equivalency_from_class_physical_num(type, iclass); VTR_ASSERT(port_eq == PortEquivalence::INSTANCE); - /* Always 0 for pads and for RECEIVER (IPIN) classes */ + // Always 0 for pads and for RECEIVER (IPIN) classes for (ipin = 0; ipin < num_local_opin; ipin++) { RRNodeId inode = route_ctx.clb_opins_used_locally[blk_id][iclass][ipin]; VTR_ASSERT(inode && size_t(inode) < rr_graph.num_nodes()); diff --git a/vpr/src/route/route_common.h b/vpr/src/route/route_common.h index 9c67467cc54..74343ff84c3 100644 --- a/vpr/src/route/route_common.h +++ b/vpr/src/route/route_common.h @@ -67,11 +67,11 @@ inline bool inside_bb(RRNodeId inode, const t_bb& bb) { if (dir == Direction::DEC) { x = rr_graph.node_xhigh(inode); y = rr_graph.node_yhigh(inode); - z = rr_graph.node_layer(inode); + z = rr_graph.node_layer_high(inode); } else { x = rr_graph.node_xlow(inode); y = rr_graph.node_ylow(inode); - z = rr_graph.node_layer(inode); + z = rr_graph.node_layer_low(inode); } return x >= bb.xmin && x <= bb.xmax && y >= bb.ymin && y <= bb.ymax && z >= bb.layer_min && z <= bb.layer_max; diff --git a/vpr/src/route/route_utilization.cpp b/vpr/src/route/route_utilization.cpp index c01d0a62c8c..194c736d79b 100644 --- a/vpr/src/route/route_utilization.cpp +++ b/vpr/src/route/route_utilization.cpp @@ -71,7 +71,7 @@ vtr::Matrix calculate_routing_usage(e_rr_type rr_type, bool is_flat, bool #ifndef NO_GRAPHICS if (!is_print) { t_draw_state* draw_state = get_draw_state_vars(); - int layer_num = rr_graph.node_layer(rr_node); + int layer_num = rr_graph.node_layer_low(rr_node); if (!draw_state->draw_layer_display[layer_num].visible) continue; // don't count usage if layer is not visible } diff --git a/vpr/src/route/route_utils.cpp b/vpr/src/route/route_utils.cpp index 0ca62ef1964..ed308079621 100644 --- a/vpr/src/route/route_utils.cpp +++ b/vpr/src/route/route_utils.cpp @@ -614,10 +614,10 @@ t_bb calc_current_bb(const RouteTree& tree) { //and xlow/ylow for xmax/ymax calculations bb.xmin = std::min(bb.xmin, rr_graph.node_xhigh(rt_node.inode)); bb.ymin = std::min(bb.ymin, rr_graph.node_yhigh(rt_node.inode)); - bb.layer_min = std::min(bb.layer_min, rr_graph.node_layer(rt_node.inode)); + bb.layer_min = std::min(bb.layer_min, rr_graph.node_layer_high(rt_node.inode)); bb.xmax = std::max(bb.xmax, rr_graph.node_xlow(rt_node.inode)); bb.ymax = std::max(bb.ymax, rr_graph.node_ylow(rt_node.inode)); - bb.layer_max = std::max(bb.layer_max, rr_graph.node_layer(rt_node.inode)); + bb.layer_max = std::max(bb.layer_max, rr_graph.node_layer_low(rt_node.inode)); } VTR_ASSERT(bb.xmin <= bb.xmax); diff --git a/vpr/src/route/router_lookahead/router_lookahead_compressed_map.cpp b/vpr/src/route/router_lookahead/router_lookahead_compressed_map.cpp index a519d65bf8a..3e231e35426 100644 --- a/vpr/src/route/router_lookahead/router_lookahead_compressed_map.cpp +++ b/vpr/src/route/router_lookahead/router_lookahead_compressed_map.cpp @@ -422,8 +422,10 @@ std::pair CompressedMapLookahead::get_expected_delay_and_cong(RRNo auto& device_ctx = g_vpr_ctx.device(); auto& rr_graph = device_ctx.rr_graph; - int from_layer_num = rr_graph.node_layer(from_node); - int to_layer_num = rr_graph.node_layer(to_node); + // TODO: handle CHANZ nodes that span multiple layers + int from_layer_num = rr_graph.node_layer_low(from_node); + // to_node is a SINK, so its layer_low == layer_high + int to_layer_num = rr_graph.node_layer_low(to_node); auto [delta_x, delta_y] = util::get_xy_deltas(from_node, to_node); delta_x = abs(delta_x); delta_y = abs(delta_y); @@ -444,7 +446,7 @@ std::pair CompressedMapLookahead::get_expected_delay_and_cong(RRNo auto from_tile_index = std::distance(&device_ctx.physical_tile_types[0], from_tile_type); - auto from_ptc = rr_graph.node_ptc_num(from_node); + int from_ptc = rr_graph.node_ptc_num(from_node); std::tie(expected_delay_cost, expected_cong_cost) = util::get_cost_from_src_opin(src_opin_delays[from_layer_num][from_tile_index][from_ptc][to_layer_num], delta_x, @@ -469,7 +471,7 @@ std::pair CompressedMapLookahead::get_expected_delay_and_cong(RRNo } else if (from_type == e_rr_type::CHANX || from_type == e_rr_type::CHANY) { //When estimating costs from a wire, we directly look-up the result in the wire lookahead (f_wire_cost_map) - auto from_cost_index = rr_graph.node_cost_index(from_node); + RRIndexedDataId from_cost_index = rr_graph.node_cost_index(from_node); int from_seg_index = device_ctx.rr_indexed_data[from_cost_index].seg_index; VTR_ASSERT(from_seg_index >= 0); diff --git a/vpr/src/route/router_lookahead/router_lookahead_extended_map.cpp b/vpr/src/route/router_lookahead/router_lookahead_extended_map.cpp index 28126de5951..270e950f1fc 100644 --- a/vpr/src/route/router_lookahead/router_lookahead_extended_map.cpp +++ b/vpr/src/route/router_lookahead/router_lookahead_extended_map.cpp @@ -73,11 +73,11 @@ std::pair ExtendedMapLookahead::get_src_opin_cost(RRNodeId from_no t_physical_tile_type_ptr tile_type = device_ctx.grid.get_physical_type({rr_graph.node_xlow(from_node), rr_graph.node_ylow(from_node), - rr_graph.node_layer(from_node)}); - auto tile_index = tile_type->index; + rr_graph.node_layer_low(from_node)}); + int tile_index = tile_type->index; - auto from_ptc = rr_graph.node_ptc_num(from_node); - int from_layer_num = rr_graph.node_layer(from_node); + int from_ptc = rr_graph.node_ptc_num(from_node); + int from_layer_num = rr_graph.node_layer_low(from_node); if (this->src_opin_delays[from_layer_num][tile_index][from_ptc].empty()) { //During lookahead profiling we were unable to find any wires which connected @@ -152,13 +152,13 @@ float ExtendedMapLookahead::get_chan_ipin_delays(RRNodeId to_node) const { e_rr_type to_type = rr_graph.node_type(to_node); VTR_ASSERT(to_type == e_rr_type::SINK || to_type == e_rr_type::IPIN); - auto to_tile_type = device_ctx.grid.get_physical_type({rr_graph.node_xlow(to_node), - rr_graph.node_ylow(to_node), - rr_graph.node_layer(to_node)}); - auto to_tile_index = to_tile_type->index; + t_physical_tile_type_ptr to_tile_type = device_ctx.grid.get_physical_type({rr_graph.node_xlow(to_node), + rr_graph.node_ylow(to_node), + rr_graph.node_layer_low(to_node)}); + int to_tile_index = to_tile_type->index; - auto to_ptc = rr_graph.node_ptc_num(to_node); - int to_layer_num = rr_graph.node_layer(to_node); + int to_ptc = rr_graph.node_ptc_num(to_node); + int to_layer_num = rr_graph.node_layer_low(to_node); float site_pin_delay = 0.f; if (this->chan_ipins_delays[to_layer_num][to_tile_index].size() != 0) { @@ -192,11 +192,10 @@ std::pair ExtendedMapLookahead::get_expected_delay_and_cong(RRNode int to_x = rr_graph.node_xlow(to_node); int to_y = rr_graph.node_ylow(to_node); - int to_layer_num = rr_graph.node_layer(to_node); + int to_layer_num = rr_graph.node_layer_low(to_node); - int dx, dy; - dx = to_x - from_x; - dy = to_y - from_y; + int dx = to_x - from_x; + int dy = to_y - from_y; e_rr_type from_type = rr_graph.node_type(from_node); if (from_type == e_rr_type::SOURCE || from_type == e_rr_type::OPIN) { diff --git a/vpr/src/route/router_lookahead/router_lookahead_map.cpp b/vpr/src/route/router_lookahead/router_lookahead_map.cpp index 6a9b7e16eb3..ed9cf0680e5 100644 --- a/vpr/src/route/router_lookahead/router_lookahead_map.cpp +++ b/vpr/src/route/router_lookahead/router_lookahead_map.cpp @@ -206,17 +206,17 @@ float MapLookahead::get_expected_cost_flat_router(RRNodeId current_node, RRNodeI t_physical_tile_type_ptr from_physical_type = device_ctx.grid.get_physical_type({rr_graph.node_xlow(current_node), rr_graph.node_ylow(current_node), - rr_graph.node_layer(current_node)}); + rr_graph.node_layer_low(current_node)}); int from_node_ptc_num = rr_graph.node_ptc_num(current_node); t_physical_tile_type_ptr to_physical_type = device_ctx.grid.get_physical_type({rr_graph.node_xlow(target_node), rr_graph.node_ylow(target_node), - rr_graph.node_layer(target_node)}); + rr_graph.node_layer_low(target_node)}); float delay_offset_cost = 0.; float cong_offset_cost = 0.; int to_node_ptc_num = rr_graph.node_ptc_num(target_node); - int to_layer_num = rr_graph.node_layer(target_node); + int to_layer_num = rr_graph.node_layer_low(target_node); // We have not checked the multi-layer FPGA for flat routing - VTR_ASSERT(rr_graph.node_layer(current_node) == rr_graph.node_layer(target_node)); + VTR_ASSERT(rr_graph.node_layer_low(current_node) == rr_graph.node_layer_low(target_node)); if (from_rr_type == e_rr_type::CHANX || from_rr_type == e_rr_type::CHANY) { std::tie(delay_cost, cong_cost) = get_expected_delay_and_cong(current_node, target_node, params, R_upstream); @@ -258,8 +258,8 @@ float MapLookahead::get_expected_cost_flat_router(RRNodeId current_node, RRNodeI auto [delta_x, delta_y] = util::get_xy_deltas(current_node, target_node); delta_x = abs(delta_x); delta_y = abs(delta_y); - delay_cost = params.criticality * chann_distance_based_min_cost[rr_graph.node_layer(current_node)][to_layer_num][delta_x][delta_y].delay; - cong_cost = (1. - params.criticality) * chann_distance_based_min_cost[rr_graph.node_layer(current_node)][to_layer_num][delta_x][delta_y].congestion; + delay_cost = params.criticality * chann_distance_based_min_cost[rr_graph.node_layer_low(current_node)][to_layer_num][delta_x][delta_y].delay; + cong_cost = (1. - params.criticality) * chann_distance_based_min_cost[rr_graph.node_layer_low(current_node)][to_layer_num][delta_x][delta_y].congestion; delay_offset_cost = params.criticality * tile_min_cost.at(to_physical_type->index).at(to_node_ptc_num).delay; cong_offset_cost = (1. - params.criticality) * tile_min_cost.at(to_physical_type->index).at(to_node_ptc_num).congestion; @@ -289,8 +289,8 @@ float MapLookahead::get_expected_cost_flat_router(RRNodeId current_node, RRNodeI auto [delta_x, delta_y] = util::get_xy_deltas(current_node, target_node); delta_x = abs(delta_x); delta_y = abs(delta_y); - delay_cost = params.criticality * chann_distance_based_min_cost[rr_graph.node_layer(current_node)][to_layer_num][delta_x][delta_y].delay; - cong_cost = (1. - params.criticality) * chann_distance_based_min_cost[rr_graph.node_layer(current_node)][to_layer_num][delta_x][delta_y].congestion; + delay_cost = params.criticality * chann_distance_based_min_cost[rr_graph.node_layer_low(current_node)][to_layer_num][delta_x][delta_y].delay; + cong_cost = (1. - params.criticality) * chann_distance_based_min_cost[rr_graph.node_layer_low(current_node)][to_layer_num][delta_x][delta_y].congestion; delay_offset_cost = params.criticality * tile_min_cost.at(to_physical_type->index).at(to_node_ptc_num).delay; cong_offset_cost = (1. - params.criticality) * tile_min_cost.at(to_physical_type->index).at(to_node_ptc_num).congestion; @@ -309,8 +309,9 @@ std::pair MapLookahead::get_expected_delay_and_cong(RRNodeId from_ const auto& device_ctx = g_vpr_ctx.device(); const auto& rr_graph = device_ctx.rr_graph; - int from_layer_num = rr_graph.node_layer(from_node); - int to_layer_num = rr_graph.node_layer(to_node); + // TODO: handle CHANZ nodes that span multiple layers + int from_layer_num = rr_graph.node_layer_low(from_node); + int to_layer_num = rr_graph.node_layer_low(to_node); auto [delta_x, delta_y] = util::get_xy_deltas(from_node, to_node); delta_x = abs(delta_x); delta_y = abs(delta_y); diff --git a/vpr/src/route/router_lookahead/router_lookahead_map_utils.cpp b/vpr/src/route/router_lookahead/router_lookahead_map_utils.cpp index 23f2ac3db49..fb0072109b5 100644 --- a/vpr/src/route/router_lookahead/router_lookahead_map_utils.cpp +++ b/vpr/src/route/router_lookahead/router_lookahead_map_utils.cpp @@ -756,7 +756,7 @@ t_routing_cost_map get_routing_cost_map(int longest_seg_length, continue; } // TODO: Temporary - After testing benchmarks this can be deleted - VTR_ASSERT(rr_graph.node_layer(start_node) == (int)from_layer_num); + VTR_ASSERT(rr_graph.node_layer_low(start_node) == (int)from_layer_num); sample_nodes.emplace_back(start_node); } @@ -771,7 +771,7 @@ t_routing_cost_map get_routing_cost_map(int longest_seg_length, for (RRNodeId rr_node : rr_graph.nodes()) { e_rr_type rr_type = rr_graph.node_type(rr_node); if (rr_type != chan_type) continue; - if (rr_graph.node_layer(rr_node) != (int)from_layer_num) continue; + if (rr_graph.node_layer_low(rr_node) != (int)from_layer_num) continue; RRIndexedDataId cost_index = rr_graph.node_cost_index(rr_node); VTR_ASSERT(cost_index != RRIndexedDataId(UNDEFINED)); @@ -966,7 +966,7 @@ static void dijkstra_flood_to_wires(int itile, root.node = node; int ptc = rr_graph.node_ptc_num(node); - int root_layer_num = rr_graph.node_layer(node); + int root_layer_num = rr_graph.node_layer_low(node); /* * Perform Dijkstra from the SOURCE/OPIN of interest, stopping at the first @@ -994,7 +994,7 @@ static void dijkstra_flood_to_wires(int itile, pq.pop(); e_rr_type curr_rr_type = rr_graph.node_type(curr.node); - int curr_layer_num = rr_graph.node_layer(curr.node); + int curr_layer_num = rr_graph.node_layer_low(curr.node); if (curr_rr_type == e_rr_type::CHANX || curr_rr_type == e_rr_type::CHANY || curr_rr_type == e_rr_type::SINK) { //We stop expansion at any CHANX/CHANY/SINK int seg_index; @@ -1075,7 +1075,7 @@ static void dijkstra_flood_to_ipins(RRNodeId node, util::t_chan_ipins_delays& ch root.node = node; root.level = 0; - int root_layer = rr_graph.node_layer(node); + int root_layer = rr_graph.node_layer_low(node); /* * Perform Djikstra from the CHAN of interest, stopping at the the first @@ -1105,7 +1105,7 @@ static void dijkstra_flood_to_ipins(RRNodeId node, util::t_chan_ipins_delays& ch if (curr_rr_type == e_rr_type::IPIN) { int node_x = rr_graph.node_xlow(curr.node); int node_y = rr_graph.node_ylow(curr.node); - int node_layer = rr_graph.node_layer(curr.node); + int node_layer = rr_graph.node_layer_low(curr.node); auto tile_type = device_ctx.grid.get_physical_type({node_x, node_y, node_layer}); int itile = tile_type->index; @@ -1126,8 +1126,8 @@ static void dijkstra_flood_to_ipins(RRNodeId node, util::t_chan_ipins_delays& ch continue; } - //We allow expansion through SOURCE/OPIN/IPIN types - auto cost_index = rr_graph.node_cost_index(curr.node); + // We allow expansion through SOURCE/OPIN/IPIN types + RRIndexedDataId cost_index = rr_graph.node_cost_index(curr.node); float new_cong = device_ctx.rr_indexed_data[cost_index].base_cost; //Current nodes congestion cost for (RREdgeId edge : rr_graph.edge_range(curr.node)) { @@ -1136,7 +1136,7 @@ static void dijkstra_flood_to_ipins(RRNodeId node, util::t_chan_ipins_delays& ch RRNodeId next_node = rr_graph.rr_nodes().edge_sink_node(edge); - if (rr_graph.node_layer(next_node) != root_layer) { + if (rr_graph.node_layer_low(next_node) != root_layer) { //Don't change the layer continue; } @@ -1345,7 +1345,7 @@ static void run_dijkstra(RRNodeId start_node, VTR_ASSERT_SAFE(rr_graph.node_ylow(curr_node) == rr_graph.node_yhigh(curr_node)); int ipin_x = rr_graph.node_xlow(curr_node); int ipin_y = rr_graph.node_ylow(curr_node); - int ipin_layer = rr_graph.node_layer(curr_node); + int ipin_layer = rr_graph.node_layer_low(curr_node); if (ipin_x >= start_x && ipin_y >= start_y) { auto [delta_x, delta_y] = util::get_xy_deltas(start_node, curr_node); diff --git a/vpr/src/route/router_lookahead/router_lookahead_simple.cpp b/vpr/src/route/router_lookahead/router_lookahead_simple.cpp index d12a5dee14e..85a8aadb5af 100644 --- a/vpr/src/route/router_lookahead/router_lookahead_simple.cpp +++ b/vpr/src/route/router_lookahead/router_lookahead_simple.cpp @@ -68,8 +68,9 @@ std::pair SimpleLookahead::get_expected_delay_and_cong(RRNodeId fr e_rr_type from_type = rr_graph.node_type(from_node); util::Cost_Entry cost_entry(0, 0); if (is_chanxy(from_type) || is_chanz(from_type)) { - int from_layer_num = rr_graph.node_layer(from_node); - int to_layer_num = rr_graph.node_layer(to_node); + // TODO: handle CHANZ nodes + int from_layer_num = rr_graph.node_layer_low(from_node); + int to_layer_num = rr_graph.node_layer_low(to_node); auto [delta_x, delta_y] = util::get_xy_deltas(from_node, to_node); delta_x = abs(delta_x); diff --git a/vpr/src/route/rr_graph_generation/clock_connection_builders.cpp b/vpr/src/route/rr_graph_generation/clock_connection_builders.cpp index 188e1384e0c..f7d987a2ff8 100644 --- a/vpr/src/route/rr_graph_generation/clock_connection_builders.cpp +++ b/vpr/src/route/rr_graph_generation/clock_connection_builders.cpp @@ -110,7 +110,8 @@ RRNodeId RoutingToClockConnection::create_virtual_clock_network_sink_node(int la rr_graph_builder.set_node_name(node_index, arch->default_clock_network_name); rr_graph_builder.set_node_class_num(node_index, ptc); rr_graph_builder.set_node_coordinates(node_index, x, y, x, y); - rr_graph_builder.set_node_layer(node_index, layer); + rr_graph_builder.set_node_layer_low(node_index, layer); + rr_graph_builder.set_node_layer_high(node_index, layer); rr_graph_builder.set_node_capacity(node_index, 1); rr_graph_builder.set_node_cost_index(node_index, RRIndexedDataId(SINK_COST_INDEX)); diff --git a/vpr/src/route/rr_graph_generation/clock_network_builders.cpp b/vpr/src/route/rr_graph_generation/clock_network_builders.cpp index 14d2b57bc20..c8e7dc71bda 100644 --- a/vpr/src/route/rr_graph_generation/clock_network_builders.cpp +++ b/vpr/src/route/rr_graph_generation/clock_network_builders.cpp @@ -342,7 +342,8 @@ int ClockRib::create_chanx_wire(int layer, rr_graph_builder.set_node_type(chanx_node, e_rr_type::CHANX); rr_graph_builder.set_node_coordinates(chanx_node, x_start, y, x_end, y); - rr_graph_builder.set_node_layer(chanx_node, layer); + rr_graph_builder.set_node_layer_low(chanx_node, layer); + rr_graph_builder.set_node_layer_high(chanx_node, layer); rr_graph_builder.set_node_capacity(chanx_node, 1); rr_graph_builder.set_node_track_num(chanx_node, ptc_num); rr_graph_builder.set_node_rc_index(chanx_node, NodeRCIndex(find_create_rr_rc_data( @@ -683,7 +684,8 @@ int ClockSpine::create_chany_wire(int layer, rr_graph_builder.set_node_type(chany_node, e_rr_type::CHANY); rr_graph_builder.set_node_coordinates(chany_node, x, y_start, x, y_end); - rr_graph_builder.set_node_layer(chany_node, layer); + rr_graph_builder.set_node_layer_low(chany_node, layer); + rr_graph_builder.set_node_layer_high(chany_node, layer); rr_graph_builder.set_node_capacity(chany_node, 1); rr_graph_builder.set_node_track_num(chany_node, ptc_num); rr_graph_builder.set_node_rc_index(chany_node, NodeRCIndex(find_create_rr_rc_data( diff --git a/vpr/src/route/rr_graph_generation/rr_graph.cpp b/vpr/src/route/rr_graph_generation/rr_graph.cpp index e0aea9da2b2..551ac9c0b0a 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph.cpp +++ b/vpr/src/route/rr_graph_generation/rr_graph.cpp @@ -2309,7 +2309,8 @@ static void add_classes_rr_graph(RRGraphBuilder& rr_graph_builder, VTR_ASSERT(root_loc.x <= std::numeric_limits::max() && root_loc.y <= std::numeric_limits::max()); rr_graph_builder.set_node_coordinates(class_inode, (short)root_loc.x, (short)root_loc.y, (short)(root_loc.x + physical_type->width - 1), (short)(root_loc.y + physical_type->height - 1)); VTR_ASSERT(root_loc.layer_num <= std::numeric_limits::max()); - rr_graph_builder.set_node_layer(class_inode, root_loc.layer_num); + rr_graph_builder.set_node_layer_low(class_inode, root_loc.layer_num); + rr_graph_builder.set_node_layer_high(class_inode, root_loc.layer_num); float R = 0.; float C = 0.; rr_graph_builder.set_node_rc_index(class_inode, NodeRCIndex(find_create_rr_rc_data(R, C, mutable_device_ctx.rr_rc_data))); @@ -2366,7 +2367,8 @@ static void add_pins_rr_graph(RRGraphBuilder& rr_graph_builder, root_loc.y + y_offset, root_loc.x + x_offset, root_loc.y + y_offset); - rr_graph_builder.set_node_layer(node_id, root_loc.layer_num); + rr_graph_builder.set_node_layer_low(node_id, root_loc.layer_num); + rr_graph_builder.set_node_layer_high(node_id, root_loc.layer_num); rr_graph_builder.add_node_side(node_id, pin_side); } } @@ -3098,7 +3100,8 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, rr_graph_builder.set_node_coordinates(node, x_coord, start, x_coord, end); } - rr_graph_builder.set_node_layer(node, layer); + rr_graph_builder.set_node_layer_low(node, layer); + rr_graph_builder.set_node_layer_high(node, layer); int length = end - start + 1; float R = length * seg_details[track].Rmetal(); @@ -3188,7 +3191,10 @@ static void build_inter_die_3d_rr_chan(RRGraphBuilder& rr_graph_builder, break; } - rr_graph_builder.set_node_layer(node, 0); + // TODO: layer numbers should be extracted from link info + rr_graph_builder.set_node_layer_low(node, 0); + rr_graph_builder.set_node_layer_high(node, 1); + rr_graph_builder.set_node_coordinates(node, x_coord, y_coord, x_coord, y_coord); // TODO: the index doesn't make any sense. We need to an RRIndexedDataId for CHANZ nodes rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(const_index_offset + seg_details[start_track - 1].index())); 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 2cefaa1a423..68c7adbbf0a 100644 --- a/vpr/src/route/rr_graph_generation/rr_node_indices.cpp +++ b/vpr/src/route/rr_graph_generation/rr_node_indices.cpp @@ -463,7 +463,7 @@ bool verify_rr_node_indices(const DeviceGrid& grid, describe_rr_node(rr_graph, grid, rr_indexed_data, inode, is_flat).c_str()); } - if (rr_graph.node_layer(inode) != l) { + if (l < rr_graph.node_layer_low(inode) && l > rr_graph.node_layer_high(inode)) { VPR_ERROR(VPR_ERROR_ROUTE, "RR node layer does not match between rr_nodes and rr_node_indices (%s/%s): %s", rr_node_typename[rr_graph.node_type(inode)], rr_node_typename[rr_type], diff --git a/vpr/src/route/rr_graph_generation/tileable_rr_graph/tileable_rr_graph_node_builder.cpp b/vpr/src/route/rr_graph_generation/tileable_rr_graph/tileable_rr_graph_node_builder.cpp index 45a631b254a..5c1f7fca5bb 100644 --- a/vpr/src/route/rr_graph_generation/tileable_rr_graph/tileable_rr_graph_node_builder.cpp +++ b/vpr/src/route/rr_graph_generation/tileable_rr_graph/tileable_rr_graph_node_builder.cpp @@ -478,7 +478,8 @@ static void load_one_grid_opin_nodes_basic_info(RRGraphBuilder& rr_graph_builder rr_graph_builder.set_node_pin_num(node, pin_num); rr_graph_builder.set_node_capacity(node, 1); - rr_graph_builder.set_node_layer(node, layer); + rr_graph_builder.set_node_layer_low(node, layer); + rr_graph_builder.set_node_layer_high(node, layer); // cost index is a FIXED value for OPIN rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(OPIN_COST_INDEX)); @@ -531,7 +532,8 @@ static void load_one_grid_ipin_nodes_basic_info(RRGraphBuilder& rr_graph_builder rr_graph_builder.set_node_pin_num(node, pin_num); rr_graph_builder.set_node_capacity(node, 1); - rr_graph_builder.set_node_layer(node, layer); + rr_graph_builder.set_node_layer_low(node, layer); + rr_graph_builder.set_node_layer_high(node, layer); // cost index is a FIXED value for OPIN rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(IPIN_COST_INDEX)); @@ -577,7 +579,8 @@ static void load_one_grid_source_nodes_basic_info(RRGraphBuilder& rr_graph_build grid_coordinate.x() + phy_tile_type->width - 1, grid_coordinate.y() + phy_tile_type->height - 1); rr_graph_builder.set_node_class_num(node, iclass); - rr_graph_builder.set_node_layer(node, (int)layer); + rr_graph_builder.set_node_layer_low(node, (short)layer); + rr_graph_builder.set_node_layer_high(node, (short)layer); // The capacity should be the number of pins in this class rr_graph_builder.set_node_capacity(node, phy_tile_type->class_inf[iclass].num_pins); @@ -623,7 +626,8 @@ static void load_one_grid_sink_nodes_basic_info(RRGraphBuilder& rr_graph_builder grid_coordinate.x() + phy_tile_type->width - 1, grid_coordinate.y() + phy_tile_type->height - 1); rr_graph_builder.set_node_class_num(node, iclass); - rr_graph_builder.set_node_layer(node, layer); + rr_graph_builder.set_node_layer_low(node, layer); + rr_graph_builder.set_node_layer_high(node, layer); rr_graph_builder.set_node_capacity(node, 1); @@ -663,7 +667,8 @@ static void load_one_grid_mux_nodes_basic_info(RRGraphBuilder& rr_graph_builder, rr_graph_builder.set_node_mux_num(node, i_mux); rr_graph_builder.set_node_capacity(node, 1); - rr_graph_builder.set_node_layer(node, layer); + rr_graph_builder.set_node_layer_low(node, layer); + rr_graph_builder.set_node_layer_high(node, layer); // cost index is a FIXED value for MUX rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(MUX_COST_INDEX)); @@ -841,7 +846,8 @@ static void load_one_chan_rr_nodes_basic_info(const RRGraphView& rr_graph, rr_node_track_ids[node].push_back(itrack); rr_graph_builder.set_node_capacity(node, 1); - rr_graph_builder.set_node_layer(node, layer); + rr_graph_builder.set_node_layer_low(node, layer); + rr_graph_builder.set_node_layer_high(node, layer); // assign switch id size_t seg_id = chan_details.get_track_segment_id(itrack); diff --git a/vpr/src/route/serial_connection_router.cpp b/vpr/src/route/serial_connection_router.cpp index 85538d12301..4ad7ef06e59 100644 --- a/vpr/src/route/serial_connection_router.cpp +++ b/vpr/src/route/serial_connection_router.cpp @@ -255,8 +255,8 @@ void SerialConnectionRouter::timing_driven_expand_neighbour(const RTExplor " (to node location %d,%d,%d x %d,%d,%d outside of expanded" " net bounding box %d,%d,%d x %d,%d,%d)\n", from_node, size_t(from_edge), size_t(to_node), - this->rr_graph_->node_xlow(to_node), this->rr_graph_->node_ylow(to_node), this->rr_graph_->node_layer(to_node), - this->rr_graph_->node_xhigh(to_node), this->rr_graph_->node_yhigh(to_node), this->rr_graph_->node_layer(to_node), + this->rr_graph_->node_xlow(to_node), this->rr_graph_->node_ylow(to_node), this->rr_graph_->node_layer_low(to_node), + this->rr_graph_->node_xhigh(to_node), this->rr_graph_->node_yhigh(to_node), this->rr_graph_->node_layer_low(to_node), bounding_box.xmin, bounding_box.ymin, bounding_box.layer_min, bounding_box.xmax, bounding_box.ymax, bounding_box.layer_max); return; /* Node is outside (expanded) bounding box. */ @@ -273,7 +273,7 @@ void SerialConnectionRouter::timing_driven_expand_neighbour(const RTExplor // IPIN's of the target block should be contained within it's bounding box int to_xlow = this->rr_graph_->node_xlow(to_node); int to_ylow = this->rr_graph_->node_ylow(to_node); - int to_layer = this->rr_graph_->node_layer(to_node); + int to_layer = this->rr_graph_->node_layer_low(to_node); int to_xhigh = this->rr_graph_->node_xhigh(to_node); int to_yhigh = this->rr_graph_->node_yhigh(to_node); if (to_xlow < target_bb.xmin diff --git a/vpr/src/util/vpr_utils.cpp b/vpr/src/util/vpr_utils.cpp index f6e31eeabde..e2049b5fd1e 100644 --- a/vpr/src/util/vpr_utils.cpp +++ b/vpr/src/util/vpr_utils.cpp @@ -62,15 +62,15 @@ std::string rr_node_arch_name(RRNodeId inode, bool is_flat) { std::string rr_node_arch_name; if (rr_graph.node_type(inode) == e_rr_type::OPIN || rr_graph.node_type(inode) == e_rr_type::IPIN) { //Pin names - auto type = device_ctx.grid.get_physical_type({rr_graph.node_xlow(rr_node), - rr_graph.node_ylow(rr_node), - rr_graph.node_layer(rr_node)}); + t_physical_tile_type_ptr type = device_ctx.grid.get_physical_type({rr_graph.node_xlow(rr_node), + rr_graph.node_ylow(rr_node), + rr_graph.node_layer_low(rr_node)}); rr_node_arch_name += block_type_pin_index_to_name(type, rr_graph.node_pin_num(rr_node), is_flat); } else if (rr_graph.node_type(inode) == e_rr_type::SOURCE || rr_graph.node_type(inode) == e_rr_type::SINK) { //Set of pins associated with SOURCE/SINK - auto type = device_ctx.grid.get_physical_type({rr_graph.node_xlow(rr_node), - rr_graph.node_ylow(rr_node), - rr_graph.node_layer(rr_node)}); + t_physical_tile_type_ptr type = device_ctx.grid.get_physical_type({rr_graph.node_xlow(rr_node), + rr_graph.node_ylow(rr_node), + rr_graph.node_layer_low(rr_node)}); auto pin_names = block_type_class_index_to_pin_names(type, rr_graph.node_class_num(rr_node), is_flat); if (pin_names.size() > 1) { rr_node_arch_name += rr_graph.node_type_string(inode); @@ -84,7 +84,7 @@ std::string rr_node_arch_name(RRNodeId inode, bool is_flat) { } else { VTR_ASSERT(rr_graph.node_type(inode) == e_rr_type::CHANX || rr_graph.node_type(inode) == e_rr_type::CHANY); //Wire segment name - auto cost_index = rr_graph.node_cost_index(inode); + RRIndexedDataId cost_index = rr_graph.node_cost_index(inode); int seg_index = device_ctx.rr_indexed_data[cost_index].seg_index; rr_node_arch_name += rr_graph.rr_segments(RRSegmentId(seg_index)).name; @@ -1633,32 +1633,32 @@ bool is_inter_cluster_node(const RRGraphView& rr_graph_view, e_rr_type node_type = rr_graph_view.node_type(node_id); if (node_type == e_rr_type::CHANX || node_type == e_rr_type::CHANY || node_type == e_rr_type::CHANZ || node_type == e_rr_type::MUX) { return true; + } + + int x_low = rr_graph_view.node_xlow(node_id); + int y_low = rr_graph_view.node_ylow(node_id); + int layer = rr_graph_view.node_layer_low(node_id); + int node_ptc = rr_graph_view.node_ptc_num(node_id); + const t_physical_tile_type_ptr physical_tile = g_vpr_ctx.device().grid.get_physical_type({x_low, y_low, layer}); + if (node_type == e_rr_type::IPIN || node_type == e_rr_type::OPIN) { + return is_pin_on_tile(physical_tile, node_ptc); } else { - int x_low = rr_graph_view.node_xlow(node_id); - int y_low = rr_graph_view.node_ylow(node_id); - int layer = rr_graph_view.node_layer(node_id); - int node_ptc = rr_graph_view.node_ptc_num(node_id); - const t_physical_tile_type_ptr physical_tile = g_vpr_ctx.device().grid.get_physical_type({x_low, y_low, layer}); - if (node_type == e_rr_type::IPIN || node_type == e_rr_type::OPIN) { - return is_pin_on_tile(physical_tile, node_ptc); - } else { - VTR_ASSERT_DEBUG(node_type == e_rr_type::SINK || node_type == e_rr_type::SOURCE); - return is_class_on_tile(physical_tile, node_ptc); - } + VTR_ASSERT_DEBUG(node_type == e_rr_type::SINK || node_type == e_rr_type::SOURCE); + return is_class_on_tile(physical_tile, node_ptc); } } int get_rr_node_max_ptc(const RRGraphView& rr_graph_view, RRNodeId node_id, bool is_flat) { - auto node_type = rr_graph_view.node_type(node_id); + e_rr_type node_type = rr_graph_view.node_type(node_id); VTR_ASSERT(node_type == e_rr_type::IPIN || node_type == e_rr_type::OPIN || node_type == e_rr_type::SINK || node_type == e_rr_type::SOURCE); const DeviceContext& device_ctx = g_vpr_ctx.device(); - auto physical_type = device_ctx.grid.get_physical_type({rr_graph_view.node_xlow(node_id), - rr_graph_view.node_ylow(node_id), - rr_graph_view.node_layer(node_id)}); + t_physical_tile_type_ptr physical_type = device_ctx.grid.get_physical_type({rr_graph_view.node_xlow(node_id), + rr_graph_view.node_ylow(node_id), + rr_graph_view.node_layer_low(node_id)}); if (node_type == e_rr_type::SINK || node_type == e_rr_type::SOURCE) { return get_tile_class_max_ptc(physical_type, is_flat); @@ -1743,7 +1743,7 @@ std::pair get_rr_node_cluster_blk_id_pb_graph_p int pin_physical_num = device_ctx.rr_graph.node_ptc_num(rr_node_id); int x = device_ctx.rr_graph.node_xlow(rr_node_id); int y = device_ctx.rr_graph.node_ylow(rr_node_id); - int layer = device_ctx.rr_graph.node_layer(rr_node_id); + int layer = device_ctx.rr_graph.node_layer_low(rr_node_id); t_physical_tile_type_ptr physical_tile = device_ctx.grid.get_physical_type({x, y, layer}); @@ -1774,19 +1774,19 @@ AtomPinId get_rr_node_atom_pin_id(RRNodeId rr_node_id) { bool node_in_same_physical_tile(RRNodeId node_first, RRNodeId node_second) { const auto& device_ctx = g_vpr_ctx.device(); const auto& rr_graph = device_ctx.rr_graph; - auto firse_rr_type = rr_graph.node_type(node_first); - auto second_rr_type = rr_graph.node_type(node_second); + e_rr_type first_rr_type = rr_graph.node_type(node_first); + e_rr_type second_rr_type = rr_graph.node_type(node_second); // If one of the given node's type is CHANX/Y nodes are definitely not in the same physical tile - if (firse_rr_type == e_rr_type::CHANX || firse_rr_type == e_rr_type::CHANY || second_rr_type == e_rr_type::CHANX || second_rr_type == e_rr_type::CHANY) { + if (first_rr_type == e_rr_type::CHANX || first_rr_type == e_rr_type::CHANY || second_rr_type == e_rr_type::CHANX || second_rr_type == e_rr_type::CHANY) { return false; } else { - VTR_ASSERT(firse_rr_type == e_rr_type::IPIN || firse_rr_type == e_rr_type::OPIN || firse_rr_type == e_rr_type::SINK || firse_rr_type == e_rr_type::SOURCE); + VTR_ASSERT(first_rr_type == e_rr_type::IPIN || first_rr_type == e_rr_type::OPIN || first_rr_type == e_rr_type::SINK || first_rr_type == e_rr_type::SOURCE); VTR_ASSERT(second_rr_type == e_rr_type::IPIN || second_rr_type == e_rr_type::OPIN || second_rr_type == e_rr_type::SINK || second_rr_type == e_rr_type::SOURCE); - int first_layer = rr_graph.node_layer(node_first); + int first_layer = rr_graph.node_layer_low(node_first); int first_x = rr_graph.node_xlow(node_first); int first_y = rr_graph.node_ylow(node_first); - int sec_layer = rr_graph.node_layer(node_second); + int sec_layer = rr_graph.node_layer_low(node_second); int sec_x = rr_graph.node_xlow(node_second); int sec_y = rr_graph.node_ylow(node_second); @@ -1983,10 +1983,12 @@ float get_min_cross_layer_delay() { const auto& rr_graph = g_vpr_ctx.device().rr_graph; float min_delay = std::numeric_limits::max(); - for (const auto& driver_node : rr_graph.nodes()) { + // TODO: rewrite this function by using CHANZ nodes + + for (const RRNodeId driver_node : rr_graph.nodes()) { for (size_t edge_id = 0; edge_id < rr_graph.num_edges(driver_node); edge_id++) { - const auto& sink_node = rr_graph.edge_sink_node(driver_node, edge_id); - if (rr_graph.node_layer(driver_node) != rr_graph.node_layer(sink_node)) { + const RRNodeId sink_node = rr_graph.edge_sink_node(driver_node, edge_id); + if (rr_graph.node_layer_low(driver_node) != rr_graph.node_layer_low(sink_node)) { int i_switch = rr_graph.edge_switch(driver_node, edge_id); float edge_delay = rr_graph.rr_switch_inf(RRSwitchId(i_switch)).Tdel; min_delay = std::min(min_delay, edge_delay); diff --git a/vpr/src/util/vpr_utils.h b/vpr/src/util/vpr_utils.h index fe1986eea55..8d2ab33df1a 100644 --- a/vpr/src/util/vpr_utils.h +++ b/vpr/src/util/vpr_utils.h @@ -340,8 +340,7 @@ void apply_route_constraints(const UserRouteConstraints& constraint); /** * @brief Iterate over all inter-layer switch types and return the minimum delay of it. - * useful four router lookahead to to have some estimate of the cost of crossing a layer - * @return + * Useful for router lookahead to have some estimate of the cost of crossing a layer */ float get_min_cross_layer_delay(); From 5dbe2e1f9824b8233b05ed262d74ef1630f72ff2 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Fri, 12 Sep 2025 16:08:41 -0400 Subject: [PATCH 28/58] update t_rr_node::length() to handle CHANZ nodes --- libs/librrgraph/src/base/rr_node.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/librrgraph/src/base/rr_node.cpp b/libs/librrgraph/src/base/rr_node.cpp index 4362d624ef2..c9abe98dabe 100644 --- a/libs/librrgraph/src/base/rr_node.cpp +++ b/libs/librrgraph/src/base/rr_node.cpp @@ -3,9 +3,9 @@ //Returns the max 'length' over the x or y direction short t_rr_node::length() const { - return std::max( - storage_->node_yhigh(id_) - storage_->node_ylow(id_), - storage_->node_xhigh(id_) - storage_->node_xlow(id_)); + return std::max({storage_->node_yhigh(id_) - storage_->node_ylow(id_), + storage_->node_xhigh(id_) - storage_->node_xlow(id_), + storage_->node_layer_high(id_) - storage_->node_layer_low(id_)}); } From a6c40a957d08a8caff1ff34ace3d3f21346a28d2 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Fri, 12 Sep 2025 16:15:47 -0400 Subject: [PATCH 29/58] update get_min_cross_layer_delay() to use CHANZ nodes --- vpr/src/util/vpr_utils.cpp | 5 ++--- vpr/src/util/vpr_utils.h | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/vpr/src/util/vpr_utils.cpp b/vpr/src/util/vpr_utils.cpp index e2049b5fd1e..56121dfa4bf 100644 --- a/vpr/src/util/vpr_utils.cpp +++ b/vpr/src/util/vpr_utils.cpp @@ -1983,12 +1983,11 @@ float get_min_cross_layer_delay() { const auto& rr_graph = g_vpr_ctx.device().rr_graph; float min_delay = std::numeric_limits::max(); - // TODO: rewrite this function by using CHANZ nodes - for (const RRNodeId driver_node : rr_graph.nodes()) { for (size_t edge_id = 0; edge_id < rr_graph.num_edges(driver_node); edge_id++) { const RRNodeId sink_node = rr_graph.edge_sink_node(driver_node, edge_id); - if (rr_graph.node_layer_low(driver_node) != rr_graph.node_layer_low(sink_node)) { + + if (rr_graph.node_type(sink_node) == e_rr_type::CHANZ) { int i_switch = rr_graph.edge_switch(driver_node, edge_id); float edge_delay = rr_graph.rr_switch_inf(RRSwitchId(i_switch)).Tdel; min_delay = std::min(min_delay, edge_delay); diff --git a/vpr/src/util/vpr_utils.h b/vpr/src/util/vpr_utils.h index 8d2ab33df1a..3c3f4e324fd 100644 --- a/vpr/src/util/vpr_utils.h +++ b/vpr/src/util/vpr_utils.h @@ -339,8 +339,8 @@ void add_pb_child_to_list(std::list& pb_list, const t_pb* parent_pb void apply_route_constraints(const UserRouteConstraints& constraint); /** - * @brief Iterate over all inter-layer switch types and return the minimum delay of it. - * Useful for router lookahead to have some estimate of the cost of crossing a layer + * @brief Iterate over all inter-layer switch types and return the minimum delay of them. + * Useful for router lookahead to have some estimate of the cost of crossing a layer. */ float get_min_cross_layer_delay(); From 25ddc9a09356c09818a4b65de2e8aa603d4227f1 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Fri, 12 Sep 2025 16:32:55 -0400 Subject: [PATCH 30/58] doxygen comment for t_wire_cost_map --- libs/librrgraph/src/base/rr_node.h | 2 +- .../router_lookahead/router_lookahead_map.h | 33 +++++++++++++------ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/libs/librrgraph/src/base/rr_node.h b/libs/librrgraph/src/base/rr_node.h index a4e50a118c3..e44926013e8 100644 --- a/libs/librrgraph/src/base/rr_node.h +++ b/libs/librrgraph/src/base/rr_node.h @@ -20,7 +20,7 @@ // The RR graph has since been refactored into the t_rr_graph_storage object. // To prevent requiring all callsites where the std::vector to be // changed at once, t_rr_graph_storage implements an interface that appears -// similiar to std::vector, even though the underlying storage is +// similar to std::vector, even though the underlying storage is // no longer a array of t_rr_node's. // // The t_rr_node class forwards all data accesses to t_rr_graph_storage, and diff --git a/vpr/src/route/router_lookahead/router_lookahead_map.h b/vpr/src/route/router_lookahead/router_lookahead_map.h index 3c93943dba3..dd2b980ba99 100644 --- a/vpr/src/route/router_lookahead/router_lookahead_map.h +++ b/vpr/src/route/router_lookahead/router_lookahead_map.h @@ -41,16 +41,29 @@ class MapLookahead : public RouterLookahead { float get_opin_distance_min_delay(int physical_tile_idx, int from_layer, int to_layer, int dx, int dy) const override; }; -/* provides delay/congestion estimates to travel specified distances - * in the x/y direction */ -// This is a 6D array storing the cost to travel from a node of type CHANX/CHANY to a point that is dx, dy further, and is on the "layer_num" layer. -// To store this information, the first index is the layer number that the node under consideration is on, the second index is the layer number of the target node, the third index represents the type of channel (X/Y) -// that the node under consideration belongs to, the forth is the segment type (specified in the architecture file under the "segmentlist" tag), the fourth is the -// target "layer_num" mentioned above, the fifth is dx, and the last one is dy. -typedef vtr::NdMatrix t_wire_cost_map; //[0..num_layers][0..num_layers][0..1][[0..num_seg_types-1][0..device_ctx.grid.width()-1][0..device_ctx.grid.height()-1] - //[0..1] entry distinguish between CHANX/CHANY start nodes respectively - // The first index is the layer number that the node under consideration is on, and the second index - // is the layer number that the target node is on. +/** + * @brief Provides delay/congestion estimates to travel specified distances + * in the x/y direction + * + * This is a 6D array storing the cost to travel from a node of type CHANX/CHANY/CHANZ + * to a point that is dx, dy further, and is on the "layer_num" layer. + * + * To store this information: + * - The first index is the layer number that the node under consideration is on. + * - The second index is the layer number of the target node. + * - The third index represents the type of channel (X/Y/Z) that the node under consideration belongs to. + * - The forth is the segment type (specified in the architecture file under the "segmentlist" tag). + * - The fifth is dx. + * - The last one is dy. + * + * @note [0..num_layers][0..num_layers][0..2][0..num_seg_types-1][0..device_ctx.grid.width()-1][0..device_ctx.grid.height()-1] + * - [0..2] entry distinguish between CHANX/CHANY/CHANZ start nodes respectively + * - The first index is the layer number that the node under consideration is on. + * - The second index is the layer number that the target node is on. + */ +typedef vtr::NdMatrix t_wire_cost_map; + + void read_router_lookahead(const std::string& file); void write_router_lookahead(const std::string& file); From 0cb5979d8f8a7d94a43c5324f681b515ebde9684 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Fri, 12 Sep 2025 19:09:51 -0400 Subject: [PATCH 31/58] find starting chanxy and chanz nodes separately --- libs/libarchfpga/src/logic_types.h | 3 +- .../router_lookahead/router_lookahead_map.cpp | 56 ++++--- .../router_lookahead_map_utils.cpp | 150 ++++++++++-------- .../router_lookahead_map_utils.h | 5 +- 4 files changed, 125 insertions(+), 89 deletions(-) diff --git a/libs/libarchfpga/src/logic_types.h b/libs/libarchfpga/src/logic_types.h index 07dbf5ac85e..5453d5394c6 100644 --- a/libs/libarchfpga/src/logic_types.h +++ b/libs/libarchfpga/src/logic_types.h @@ -31,7 +31,8 @@ enum class e_parallel_axis { /** Y_AXIS: Data that describes an y-directed wire segment (CHANY) */ Y_AXIS, /** BOTH_AXIS: Data that can be applied to both x-directed and y-directed wire segment */ - BOTH_AXIS + BOTH_AXIS, + Z_AXIS }; /* diff --git a/vpr/src/route/router_lookahead/router_lookahead_map.cpp b/vpr/src/route/router_lookahead/router_lookahead_map.cpp index ed9cf0680e5..30714e6c819 100644 --- a/vpr/src/route/router_lookahead/router_lookahead_map.cpp +++ b/vpr/src/route/router_lookahead/router_lookahead_map.cpp @@ -188,7 +188,7 @@ float MapLookahead::get_expected_cost(RRNodeId current_node, RRNodeId target_nod } else if (from_rr_type == e_rr_type::IPIN) { // Change if you're allowing route-throughs return (device_ctx.rr_indexed_data[RRIndexedDataId(SINK_COST_INDEX)].base_cost); } else { // Change this if you want to investigate route-throughs - return (0.); + return 0.f; } } } @@ -309,7 +309,6 @@ std::pair MapLookahead::get_expected_delay_and_cong(RRNodeId from_ const auto& device_ctx = g_vpr_ctx.device(); const auto& rr_graph = device_ctx.rr_graph; - // TODO: handle CHANZ nodes that span multiple layers int from_layer_num = rr_graph.node_layer_low(from_node); int to_layer_num = rr_graph.node_layer_low(to_node); auto [delta_x, delta_y] = util::get_xy_deltas(from_node, to_node); @@ -362,15 +361,28 @@ std::pair MapLookahead::get_expected_delay_and_cong(RRNodeId from_ .c_str()) .c_str()); - } else if (from_type == e_rr_type::CHANX || from_type == e_rr_type::CHANY) { - //When estimating costs from a wire, we directly look-up the result in the wire lookahead (f_wire_cost_map) + } else if (from_type == e_rr_type::CHANX || from_type == e_rr_type::CHANY || from_type == e_rr_type::CHANZ) { + // When estimating costs from a wire, we directly look-up the result in the wire lookahead (f_wire_cost_map) + + // For CHANZ nodes, if the direction is + // 1) incremental --> `chanz_node` now drives other nodes on node_layer_high(chanz_node). + // 2) decremental --> `chanz_node` now drives other nodes on node_layer_low(chanz_node). + // 3) decremental --> `chanz_node` now drives other nodes on both layers, so we choose the target layer + if (from_type == e_rr_type::CHANZ) { + Direction chanz_node_dir = rr_graph.node_direction(from_node); + if (chanz_node_dir == Direction::INC) { + from_layer_num = rr_graph.node_layer_high(from_node); + } else if (chanz_node_dir == Direction::BIDIR) { + from_layer_num = to_layer_num; + } + } - auto from_cost_index = rr_graph.node_cost_index(from_node); + RRIndexedDataId from_cost_index = rr_graph.node_cost_index(from_node); int from_seg_index = device_ctx.rr_indexed_data[from_cost_index].seg_index; VTR_ASSERT(from_seg_index >= 0); - /* now get the expected cost from our lookahead map */ + // Now get the expected cost from our lookahead map util::Cost_Entry cost_entry = get_wire_cost_entry(from_type, from_seg_index, from_layer_num, @@ -392,9 +404,9 @@ std::pair MapLookahead::get_expected_delay_and_cong(RRNodeId from_ .c_str()); expected_delay_cost = cost_entry.delay * params.criticality; expected_cong_cost = cost_entry.congestion * (1 - params.criticality); - } else if (from_type == e_rr_type::IPIN) { /* Change if you're allowing route-throughs */ + } else if (from_type == e_rr_type::IPIN) { // Change if you're allowing route-throughs return std::make_pair(0., device_ctx.rr_indexed_data[RRIndexedDataId(SINK_COST_INDEX)].base_cost); - } else { /* Change this if you want to investigate route-throughs */ + } else { // Change this if you want to investigate route-throughs return std::make_pair(0., 0.); } @@ -404,8 +416,8 @@ std::pair MapLookahead::get_expected_delay_and_cong(RRNodeId from_ void MapLookahead::compute(const std::vector& segment_inf) { vtr::ScopedStartFinishTimer timer("Computing router lookahead map"); - //First compute the delay map when starting from the various wire types - //(CHANX/CHANY)in the routing architecture + // First compute the delay map when starting from the various wire types + // (CHANX/CHANY/CHANZ) in the routing architecture compute_router_wire_lookahead(segment_inf, route_verbosity_); //Next, compute which wire types are accessible (and the cost to reach them) @@ -505,29 +517,37 @@ static void compute_router_wire_lookahead(const std::vector& segm const auto& device_ctx = g_vpr_ctx.device(); const auto& grid = device_ctx.grid; + const size_t num_layers = grid.get_num_layers(); + const size_t chan_type_dim_size = (num_layers == 1) ? 2 : 3; + //Re-allocate - f_wire_cost_map = t_wire_cost_map({static_cast(grid.get_num_layers()), - static_cast(grid.get_num_layers()), - 2, + f_wire_cost_map = t_wire_cost_map({num_layers, + num_layers, + chan_type_dim_size, segment_inf_vec.size(), device_ctx.grid.width(), device_ctx.grid.height()}); int longest_seg_length = 0; - for (const auto& seg_inf : segment_inf_vec) { + for (const t_segment_inf& seg_inf : segment_inf_vec) { longest_seg_length = std::max(longest_seg_length, seg_inf.length); } // Profile each wire segment type - for (size_t from_layer_num = 0; from_layer_num < grid.get_num_layers(); from_layer_num++) { + for (size_t from_layer_num = 0; from_layer_num < num_layers; from_layer_num++) { for (const t_segment_inf& segment_inf : segment_inf_vec) { std::vector chan_types; - if (segment_inf.parallel_axis == e_parallel_axis::X_AXIS) + if (segment_inf.parallel_axis == e_parallel_axis::X_AXIS) { chan_types.push_back(e_rr_type::CHANX); - else if (segment_inf.parallel_axis == e_parallel_axis::Y_AXIS) + } else if (segment_inf.parallel_axis == e_parallel_axis::Y_AXIS) { chan_types.push_back(e_rr_type::CHANY); - else //Both for BOTH_AXIS segments and special segments such as clock_networks we want to search in both directions. + } else if (segment_inf.parallel_axis == e_parallel_axis::Z_AXIS) { + chan_types.push_back(e_rr_type::CHANZ); + } else { + VTR_ASSERT(segment_inf.parallel_axis == e_parallel_axis::BOTH_AXIS); + // Both for BOTH_AXIS segments and special segments such as clock_networks we want to search in both directions. chan_types.insert(chan_types.end(), {e_rr_type::CHANX, e_rr_type::CHANY}); + } for (e_rr_type chan_type : chan_types) { util::t_routing_cost_map routing_cost_map = util::get_routing_cost_map(longest_seg_length, diff --git a/vpr/src/route/router_lookahead/router_lookahead_map_utils.cpp b/vpr/src/route/router_lookahead/router_lookahead_map_utils.cpp index fb0072109b5..f05621f68cd 100644 --- a/vpr/src/route/router_lookahead/router_lookahead_map_utils.cpp +++ b/vpr/src/route/router_lookahead/router_lookahead_map_utils.cpp @@ -543,37 +543,60 @@ t_ipin_primitive_sink_delays compute_intra_tile_dijkstra(const RRGraphView& rr_g return pin_delays; } -/* returns index of a node from which to start routing */ -RRNodeId get_start_node(int layer, int start_x, int start_y, int target_x, int target_y, e_rr_type rr_type, int seg_index, int track_offset) { +RRNodeId get_chanxy_start_node(int layer, int start_x, int start_y, int target_x, int target_y, e_rr_type rr_type, int seg_index, int track_offset) { const auto& device_ctx = g_vpr_ctx.device(); const auto& rr_graph = device_ctx.rr_graph; const auto& node_lookup = rr_graph.node_lookup(); - RRNodeId result = RRNodeId::INVALID(); + VTR_ASSERT(rr_type == e_rr_type::CHANX || rr_type == e_rr_type::CHANY); - if (rr_type != e_rr_type::CHANX && rr_type != e_rr_type::CHANY) { - VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Must start lookahead routing from CHANX or CHANY node\n"); - } + RRNodeId result = RRNodeId::INVALID(); - /* determine which direction the wire should go in based on the start & target coordinates */ + // Determine which direction the wire should go in based on the start & target coordinates Direction direction = Direction::INC; if ((rr_type == e_rr_type::CHANX && target_x < start_x) || (rr_type == e_rr_type::CHANY && target_y < start_y)) { direction = Direction::DEC; } - int start_lookup_x = start_x; - int start_lookup_y = start_y; - - /* find first node in channel that has specified segment index and goes in the desired direction */ - for (const RRNodeId& node_id : node_lookup.find_channel_nodes(layer, start_lookup_x, start_lookup_y, rr_type)) { + // Find first node in channel that has specified segment index and goes in the desired direction + for (const RRNodeId node_id : node_lookup.find_channel_nodes(layer, start_x, start_y, rr_type)) { VTR_ASSERT(rr_graph.node_type(node_id) == rr_type); Direction node_direction = rr_graph.node_direction(node_id); - auto node_cost_ind = rr_graph.node_cost_index(node_id); + RRIndexedDataId node_cost_ind = rr_graph.node_cost_index(node_id); int node_seg_ind = device_ctx.rr_indexed_data[node_cost_ind].seg_index; if ((node_direction == direction || node_direction == Direction::BIDIR) && node_seg_ind == seg_index) { - /* found first track that has the specified segment index and goes in the desired direction */ + // Found first track that has the specified segment index and goes in the desired direction + result = node_id; + if (track_offset == 0) { + break; + } + track_offset -= 2; + } + } + + return result; +} + +RRNodeId get_chanz_start_node(int start_x, int start_y, int seg_index, int track_offset, Direction dir) { + const auto& device_ctx = g_vpr_ctx.device(); + const auto& rr_graph = device_ctx.rr_graph; + const auto& node_lookup = rr_graph.node_lookup(); + + RRNodeId result = RRNodeId::INVALID(); + + // CHANZ nodes currently span across all layers, so the value of layer is irrelevant. + const int layer = 0; + + // Find first node in channel that has specified segment index and goes in the desired direction + for (const RRNodeId node_id : node_lookup.find_channel_nodes(layer, start_x, start_y, e_rr_type::CHANZ)) { + Direction node_direction = rr_graph.node_direction(node_id); + RRIndexedDataId node_cost_ind = rr_graph.node_cost_index(node_id); + int node_seg_ind = device_ctx.rr_indexed_data[node_cost_ind].seg_index; + + if ((node_direction == dir || node_direction == Direction::BIDIR) && node_seg_ind == seg_index) { + // Found first track that has the specified segment index and goes in the desired direction result = node_id; if (track_offset == 0) { break; @@ -692,7 +715,7 @@ std::pair get_xy_deltas(RRNodeId from_node, RRNodeId to_node) { t_routing_cost_map get_routing_cost_map(int longest_seg_length, unsigned from_layer_num, - const e_rr_type& chan_type, + const e_rr_type chan_type, const t_segment_inf& segment_inf, const std::unordered_map>& sample_locs, bool sample_all_locs, @@ -701,43 +724,32 @@ t_routing_cost_map get_routing_cost_map(int longest_seg_length, const auto& rr_graph = device_ctx.rr_graph; const auto& grid = device_ctx.grid; - //Start sampling at the lower left non-corner + // Start sampling at the lower left non-corner int ref_x = 1; int ref_y = 1; - //Sample from locations near the reference location (to capture maximum distance paths) - //Also sample from locations at least the longest wire length away from the edge (to avoid - //edge effects for shorter distances) - std::vector ref_increments = {0, - 1, - longest_seg_length, - longest_seg_length + 1}; + // Sample from locations near the reference location (to capture maximum distance paths) + // Also sample from locations at least the longest wire length away from the edge (to avoid + // edge effects for shorter distances) + std::vector ref_increments{0, 1, longest_seg_length, longest_seg_length + 1}; - //Uniquify the increments (avoid sampling the same locations repeatedly if they happen to - //overlap) + // Uniquify the increments (avoid sampling the same locations repeatedly if they happen to overlap) std::stable_sort(ref_increments.begin(), ref_increments.end()); ref_increments.erase(std::unique(ref_increments.begin(), ref_increments.end()), ref_increments.end()); - //Upper right non-corner - int target_x = device_ctx.grid.width() - 2; - int target_y = device_ctx.grid.height() - 2; + // Upper right non-corner + const int target_x = device_ctx.grid.width() - 2; + const int target_y = device_ctx.grid.height() - 2; - //if arch file specifies die_number="layer_num" doesn't require inter-cluster - //programmable routing resources, then we shouldn't profile wire segment types in - //the current layer + // If arch file specifies die_number="layer_num" doesn't have inter-cluster + // programmable routing resources, then we shouldn't profile wire segment types in + // the current layer if (!device_ctx.inter_cluster_prog_routing_resources[from_layer_num]) { return t_routing_cost_map(); } - //First try to pick good representative sample locations for each type + // First try to pick good representative sample locations for each type std::vector sample_nodes; - std::vector chan_types; - if (segment_inf.parallel_axis == e_parallel_axis::X_AXIS) - chan_types.push_back(e_rr_type::CHANX); - else if (segment_inf.parallel_axis == e_parallel_axis::Y_AXIS) - chan_types.push_back(e_rr_type::CHANY); - else //Both for BOTH_AXIS segments and special segments such as clock_networks we want to search in both directions. - chan_types.insert(chan_types.end(), {e_rr_type::CHANX, e_rr_type::CHANY}); for (int ref_inc : ref_increments) { int sample_x = ref_x + ref_inc; @@ -747,31 +759,35 @@ t_routing_cost_map get_routing_cost_map(int longest_seg_length, if (sample_y >= int(grid.height())) continue; for (int track_offset = 0; track_offset < MAX_TRACK_OFFSET; track_offset += 2) { - /* get the rr node index from which to start routing */ - RRNodeId start_node = get_start_node(from_layer_num, sample_x, sample_y, - target_x, target_y, //non-corner upper right - chan_type, segment_inf.seg_index, track_offset); + // Get the rr node index from which to start routing - if (!start_node) { - continue; + RRNodeId start_node; + if (is_chanxy(chan_type)) { + start_node = get_chanxy_start_node(from_layer_num, sample_x, sample_y, + target_x, target_y, + chan_type, segment_inf.seg_index, track_offset); + } else { + VTR_ASSERT(is_chanz(chan_type)); + Direction direction = (from_layer_num == 0) ? Direction::DEC : Direction::INC; + start_node = get_chanz_start_node(sample_x, sample_x, segment_inf.seg_index, track_offset, direction); } - // TODO: Temporary - After testing benchmarks this can be deleted - VTR_ASSERT(rr_graph.node_layer_low(start_node) == (int)from_layer_num); - sample_nodes.emplace_back(start_node); + if (start_node) { + sample_nodes.emplace_back(start_node); + } } } - //If we failed to find any representative sample locations, search exhaustively - // - //This is to ensure we sample 'unusual' wire types which may not exist in all channels - //(e.g. clock routing) + // If we failed to find any representative sample locations, search exhaustively + // This is to ensure we sample 'unusual' wire types which may not exist in all channels (e.g. clock routing) if (sample_nodes.empty()) { // Try an exhaustive search to find a suitable sample point for (RRNodeId rr_node : rr_graph.nodes()) { e_rr_type rr_type = rr_graph.node_type(rr_node); if (rr_type != chan_type) continue; - if (rr_graph.node_layer_low(rr_node) != (int)from_layer_num) continue; + if (is_chanxy(rr_type) && rr_graph.node_layer_low(rr_node) != (int)from_layer_num) continue; + if (is_chanz(rr_type) && rr_graph.node_direction(rr_node) == Direction::INC && from_layer_num != 1) continue; + if (is_chanz(rr_type) && rr_graph.node_direction(rr_node) == Direction::DEC && from_layer_num != 0) continue; RRIndexedDataId cost_index = rr_graph.node_cost_index(rr_node); VTR_ASSERT(cost_index != RRIndexedDataId(UNDEFINED)); @@ -788,10 +804,10 @@ t_routing_cost_map get_routing_cost_map(int longest_seg_length, } } - //Finally, now that we have a list of sample locations, run a Dijkstra flood from - //each sample location to profile the routing network from this type + // Finally, now that we have a list of sample locations, run a Dijkstra flood from + // each sample location to profile the routing network from this type - t_routing_cost_map routing_cost_map({(size_t)device_ctx.grid.get_num_layers(), device_ctx.grid.width(), device_ctx.grid.height()}); + t_routing_cost_map routing_cost_map({device_ctx.grid.get_num_layers(), device_ctx.grid.width(), device_ctx.grid.height()}); if (sample_nodes.empty()) { VTR_LOGV_WARN(route_verbosity > 1, @@ -800,7 +816,7 @@ t_routing_cost_map get_routing_cost_map(int longest_seg_length, segment_inf.name.c_str(), segment_inf.length); } else { - //reset cost for this segment + // reset cost for this segment routing_cost_map.fill(Expansion_Cost_Entry()); // to avoid multiple memory allocation and de-allocations in run_dijkstra() @@ -1294,8 +1310,6 @@ static void run_intra_tile_dijkstra(const RRGraphView& rr_graph, } } -/* runs Dijkstra's algorithm from specified node until all nodes have been visited. Each time a pin is visited, the delay/congestion information - * to that pin is stored is added to an entry in the routing_cost_map */ static void run_dijkstra(RRNodeId start_node, int start_x, int start_y, @@ -1303,43 +1317,43 @@ static void run_dijkstra(RRNodeId start_node, util::t_dijkstra_data& data, const std::unordered_map>& sample_locs, bool sample_all_locs) { - auto& device_ctx = g_vpr_ctx.device(); + const DeviceContext& device_ctx = g_vpr_ctx.device(); const auto& rr_graph = device_ctx.rr_graph; - auto& node_expanded = data.node_expanded; + vtr::vector& node_expanded = data.node_expanded; node_expanded.resize(rr_graph.num_nodes()); std::fill(node_expanded.begin(), node_expanded.end(), false); - auto& node_visited_costs = data.node_visited_costs; + vtr::vector& node_visited_costs = data.node_visited_costs; node_visited_costs.resize(rr_graph.num_nodes()); std::fill(node_visited_costs.begin(), node_visited_costs.end(), -1.0); - /* a priority queue for expansion */ + // A priority queue for expansion std::priority_queue& pq = data.pq; - //Clear priority queue if non-empty + // Clear priority queue if non-empty while (!pq.empty()) { pq.pop(); } - /* first entry has no upstream delay or congestion */ + // First entry has no upstream delay or congestion pq.emplace(start_node, UNDEFINED, 0, 0, 0, true); - /* now do routing */ + // Now do routing while (!pq.empty()) { util::PQ_Entry current = pq.top(); pq.pop(); RRNodeId curr_node = current.rr_node; - /* check that we haven't already expanded from this node */ + // Check that we haven't already expanded from this node if (node_expanded[curr_node]) { continue; } //VTR_LOG("Expanding with delay=%10.3g cong=%10.3g (%s)\n", current.delay, current.congestion_upstream, describe_rr_node(rr_graph, device_ctx.grid, device_ctx.rr_indexed_data, curr_node).c_str()); - /* if this node is an ipin record its congestion/delay in the routing_cost_map */ + // If this node is an ipin record its congestion/delay in the routing_cost_map if (rr_graph.node_type(curr_node) == e_rr_type::IPIN) { VTR_ASSERT_SAFE(rr_graph.node_xlow(curr_node) == rr_graph.node_xhigh(curr_node)); VTR_ASSERT_SAFE(rr_graph.node_ylow(curr_node) == rr_graph.node_yhigh(curr_node)); diff --git a/vpr/src/route/router_lookahead/router_lookahead_map_utils.h b/vpr/src/route/router_lookahead/router_lookahead_map_utils.h index 2a67ed10865..3d23058dbb6 100644 --- a/vpr/src/route/router_lookahead/router_lookahead_map_utils.h +++ b/vpr/src/route/router_lookahead/router_lookahead_map_utils.h @@ -319,7 +319,8 @@ t_ipin_primitive_sink_delays compute_intra_tile_dijkstra(const RRGraphView& rr_g const t_physical_tile_loc& tile_loc); /* returns index of a node from which to start routing */ -RRNodeId get_start_node(int layer, int start_x, int start_y, int target_x, int target_y, e_rr_type rr_type, int seg_index, int track_offset); +RRNodeId get_chanxy_start_node(int layer, int start_x, int start_y, int target_x, int target_y, e_rr_type rr_type, int seg_index, int track_offset); +RRNodeId get_chanz_start_node(int start_x, int start_y, int seg_index, int track_offset, Direction dir); /** * @brief Computes the absolute delta_x and delta_y offset @@ -333,7 +334,7 @@ std::pair get_xy_deltas(RRNodeId from_node, RRNodeId to_node); t_routing_cost_map get_routing_cost_map(int longest_seg_length, unsigned from_layer_num, - const e_rr_type& chan_type, + const e_rr_type chan_type, const t_segment_inf& segment_inf, const std::unordered_map>& sample_locs, bool sample_all_locs, From e6ec35e226024934530931b11a9ffa45ce839dd5 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Fri, 12 Sep 2025 19:24:02 -0400 Subject: [PATCH 32/58] update set_lookahead_map_costs() and fill_in_missing_lookahead_entries() to handle chanz nodes --- .../router_lookahead/router_lookahead_map.cpp | 28 ++++++++++++++----- .../router_lookahead_map_utils.cpp | 3 +- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/vpr/src/route/router_lookahead/router_lookahead_map.cpp b/vpr/src/route/router_lookahead/router_lookahead_map.cpp index 30714e6c819..fcce25245c1 100644 --- a/vpr/src/route/router_lookahead/router_lookahead_map.cpp +++ b/vpr/src/route/router_lookahead/router_lookahead_map.cpp @@ -141,6 +141,7 @@ static void set_lookahead_map_costs(unsigned from_layer_num, /* fills in missing lookahead map entries by copying the cost of the closest valid entry */ static void fill_in_missing_lookahead_entries(int segment_index, e_rr_type chan_type); + /* returns a cost entry in the f_wire_cost_map that is near the specified coordinates (and preferably towards (0,0)) */ static util::Cost_Entry get_nearby_cost_entry(int from_layer_num, int x, int y, int to_layer_num, int segment_index, int chan_index); @@ -565,8 +566,8 @@ static void compute_router_wire_lookahead(const std::vector& segm // and store it in the lookahead cost map set_lookahead_map_costs(from_layer_num, segment_inf.seg_index, chan_type, routing_cost_map); - /* fill in missing entries in the lookahead cost map by copying the closest cost entries (cost map was computed based on - * a reference coordinate > (0,0) so some entries that represent a cross-chip distance have not been computed) */ + // Fill in missing entries in the lookahead cost map by copying the closest cost entries (cost map was computed based on + // a reference coordinate > (0,0) so some entries that represent a cross-chip distance have not been computed) fill_in_missing_lookahead_entries(segment_inf.seg_index, chan_type); } } @@ -577,7 +578,14 @@ static void set_lookahead_map_costs(unsigned from_layer_num, int segment_index, e_rr_type chan_type, util::t_routing_cost_map& routing_cost_map) { - int chan_index = (chan_type == e_rr_type::CHANX) ? 0 : 1; + int chan_index; + switch (chan_type) { + case e_rr_type::CHANX: chan_index = 0; break; + case e_rr_type::CHANY: chan_index = 1; break; + case e_rr_type::CHANZ: chan_index = 2; break; + default: + VTR_ASSERT(false); + } // set the lookahead cost map entries with a representative cost entry from routing_cost_map for (unsigned to_layer = 0; to_layer < routing_cost_map.dim_size(0); to_layer++) { @@ -591,11 +599,17 @@ static void set_lookahead_map_costs(unsigned from_layer_num, } } -/* fills in missing lookahead map entries by copying the cost of the closest valid entry */ static void fill_in_missing_lookahead_entries(int segment_index, e_rr_type chan_type) { - int chan_index = (chan_type == e_rr_type::CHANX) ? 0 : 1; - - auto& device_ctx = g_vpr_ctx.device(); + const DeviceContext& device_ctx = g_vpr_ctx.device(); + + int chan_index; + switch (chan_type) { + case e_rr_type::CHANX: chan_index = 0; break; + case e_rr_type::CHANY: chan_index = 1; break; + case e_rr_type::CHANZ: chan_index = 2; break; + default: + VTR_ASSERT(false); + } const int num_layers = device_ctx.grid.get_num_layers(); const int grid_width = device_ctx.grid.width(); diff --git a/vpr/src/route/router_lookahead/router_lookahead_map_utils.cpp b/vpr/src/route/router_lookahead/router_lookahead_map_utils.cpp index f05621f68cd..fcde65eaa44 100644 --- a/vpr/src/route/router_lookahead/router_lookahead_map_utils.cpp +++ b/vpr/src/route/router_lookahead/router_lookahead_map_utils.cpp @@ -1390,12 +1390,11 @@ static void run_dijkstra(RRNodeId start_node, } } -/* iterates over the children of the specified node and selectively pushes them onto the priority queue */ static void expand_dijkstra_neighbours(util::PQ_Entry parent_entry, vtr::vector& node_visited_costs, vtr::vector& node_expanded, std::priority_queue& pq) { - auto& device_ctx = g_vpr_ctx.device(); + const DeviceContext& device_ctx = g_vpr_ctx.device(); const auto& rr_graph = device_ctx.rr_graph; RRNodeId parent = parent_entry.rr_node; From df26028cfa38c494390e860458ec106b0afd05ae Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Sun, 14 Sep 2025 15:14:55 -0400 Subject: [PATCH 33/58] parse axis="z" for segment type --- libs/libarchfpga/src/read_xml_arch_file.cpp | 41 +++++++++++-------- libs/librrgraph/src/base/rr_node_types.h | 4 +- .../router_lookahead/router_lookahead.cpp | 4 +- .../router_lookahead_compressed_map.cpp | 2 +- .../router_lookahead/router_lookahead_map.cpp | 12 ++++-- .../router_lookahead_map_utils.cpp | 12 ++++-- 6 files changed, 47 insertions(+), 28 deletions(-) diff --git a/libs/libarchfpga/src/read_xml_arch_file.cpp b/libs/libarchfpga/src/read_xml_arch_file.cpp index 297c6d577a2..b2b42dacdbe 100644 --- a/libs/libarchfpga/src/read_xml_arch_file.cpp +++ b/libs/libarchfpga/src/read_xml_arch_file.cpp @@ -347,6 +347,7 @@ static void process_clock_routing(pugi::xml_node parent, static std::vector process_segments(pugi::xml_node Parent, const std::vector& switches, + int num_layers, const bool timing_enabled, const bool switchblocklist_required, const pugiutil::loc_data& loc_data); @@ -463,7 +464,7 @@ void xml_read_arch(const char* ArchFile, /* Process segments. This depends on switches */ Next = get_single_child(architecture, "segmentlist", loc_data); - arch->Segments = process_segments(Next, arch->switches, timing_enabled, switchblocklist_required, loc_data); + arch->Segments = process_segments(Next, arch->switches, num_of_avail_layers, timing_enabled, switchblocklist_required, loc_data); Next = get_single_child(architecture, "switchblocklist", loc_data, SWITCHBLOCKLIST_REQD); if (Next) { @@ -3805,6 +3806,7 @@ static void process_complex_blocks(pugi::xml_node Node, static std::vector process_segments(pugi::xml_node Parent, const std::vector& switches, + int num_layers, const bool timing_enabled, const bool switchblocklist_required, const pugiutil::loc_data& loc_data) { @@ -3815,20 +3817,20 @@ static std::vector process_segments(pugi::xml_node Parent, pugi::xml_node SubElem; pugi::xml_node Node; - /* Count the number of segs and check they are in fact - * of segment elements. */ + // Count the number of segs and check they are in fact of segment elements. int NumSegs = count_children(Parent, "segment", loc_data); - /* Alloc segment list */ + // Alloc segment list if (NumSegs > 0) { Segs.resize(NumSegs); } - /* Load the segments. */ + // Load the segments. Node = get_first_child(Parent, "segment", loc_data); - bool x_axis_seg_found = false; /*Flags to see if we have any x-directed segment type specified*/ - bool y_axis_seg_found = false; /*Flags to see if we have any y-directed segment type specified*/ + bool x_axis_seg_found = false; // Flags to see if we have any x-directed segment type specified + bool y_axis_seg_found = false; // Flags to see if we have any y-directed segment type specified + bool z_axis_seg_found = false; // Flags to see if we have any z-directed segment type specified for (int i = 0; i < NumSegs; ++i) { /* Get segment name */ @@ -3885,16 +3887,19 @@ static std::vector process_segments(pugi::xml_node Parent, } else if (strcmp(tmp, "y") == 0) { Segs[i].parallel_axis = e_parallel_axis::Y_AXIS; y_axis_seg_found = true; + } else if (strcmp(tmp, "z") == 0) { + Segs[i].parallel_axis = e_parallel_axis::Y_AXIS; + z_axis_seg_found = true; } else { archfpga_throw(loc_data.filename_c_str(), loc_data.line(Node), - vtr::string_fmt("Unsopported parralel axis type: %s\n", tmp).c_str()); + vtr::string_fmt("Unsupported parallel axis type: %s\n", tmp).c_str()); } } else { x_axis_seg_found = true; y_axis_seg_found = true; } - /*Get segment resource type*/ + // Get segment resource type tmp = get_attribute(Node, "res_type", loc_data, ReqOpt::OPTIONAL).as_string(nullptr); if (tmp) { @@ -3903,7 +3908,7 @@ static std::vector process_segments(pugi::xml_node Parent, Segs[i].res_type = static_cast(std::distance(RES_TYPE_STRING.begin(), it)); } else { archfpga_throw(loc_data.filename_c_str(), loc_data.line(Node), - vtr::string_fmt("Unsopported segment res_type: %s\n", tmp).c_str()); + vtr::string_fmt("Unsupported segment res_type: %s\n", tmp).c_str()); } } @@ -3912,16 +3917,16 @@ static std::vector process_segments(pugi::xml_node Parent, * (*Segs)[i].Cmetal_per_m = get_attribute(Node, "Cmetal_per_m", false, * 0.);*/ - //Set of expected subtags (exact subtags are dependent on parameters) + // Set of expected subtags (exact subtags are dependent on parameters) std::vector expected_subtags; if (!Segs[i].longline) { - //Long line doesn't accpet or since it assumes full population + // Long line doesn't accept or since it assumes full population expected_subtags.emplace_back("sb"); expected_subtags.emplace_back("cb"); } - /* Get the type */ + // Get the type tmp = get_attribute(Node, "type", loc_data).value(); if (0 == strcmp(tmp, "bidir")) { Segs[i].directionality = BI_DIRECTIONAL; @@ -4089,7 +4094,12 @@ static std::vector process_segments(pugi::xml_node Parent, if (!x_axis_seg_found || !y_axis_seg_found) { archfpga_throw(loc_data.filename_c_str(), loc_data.line(Node), - vtr::string_fmt("Atleast one segment per-axis needs to get specified if no segments with non-specified (default) axis attribute exist.").c_str()); + vtr::string_fmt("At least one segment per-axis needs to get specified if no segments with non-specified (default) axis attribute exist.").c_str()); + } + + if (num_layers > 1 && !z_axis_seg_found) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(Node), + vtr::string_fmt("At least one segment along Z axis needs to get specified if for 3D architectures.").c_str()); } return Segs; @@ -4311,14 +4321,13 @@ static void process_switch_blocks(pugi::xml_node Parent, t_arch* arch, const pug static void process_cb_sb(pugi::xml_node Node, std::vector& list, const pugiutil::loc_data& loc_data) { const char* tmp = nullptr; - int i; int len = list.size(); // Check the type. We only support 'pattern' for now. // Should add frac back eventually. tmp = get_attribute(Node, "type", loc_data).value(); if (0 == strcmp(tmp, "pattern")) { - i = 0; + int i = 0; // Get the content string tmp = Node.child_value(); diff --git a/libs/librrgraph/src/base/rr_node_types.h b/libs/librrgraph/src/base/rr_node_types.h index 1cce4542f18..963b8c25d18 100644 --- a/libs/librrgraph/src/base/rr_node_types.h +++ b/libs/librrgraph/src/base/rr_node_types.h @@ -29,10 +29,10 @@ enum class e_rr_type : unsigned char { OPIN, /// ClassicLookahead::get_expected_delay_and_cong(RRNodeId node, RRNodeId target_node, const t_conn_cost_params& params, float R_upstream) const { - auto& device_ctx = g_vpr_ctx.device(); + const DeviceContext& device_ctx = g_vpr_ctx.device(); const auto& rr_graph = device_ctx.rr_graph; e_rr_type rr_type = rr_graph.node_type(node); @@ -82,7 +82,7 @@ std::pair ClassicLookahead::get_expected_delay_and_cong(RRNodeId n if (rr_type == e_rr_type::CHANX || rr_type == e_rr_type::CHANY) { auto [num_segs_same_dir, num_segs_ortho_dir] = get_expected_segs_to_target(node, target_node); - auto cost_index = rr_graph.node_cost_index(node); + RRIndexedDataId cost_index = rr_graph.node_cost_index(node); int ortho_cost_index = device_ctx.rr_indexed_data[cost_index].ortho_cost_index; const auto& same_data = device_ctx.rr_indexed_data[cost_index]; diff --git a/vpr/src/route/router_lookahead/router_lookahead_compressed_map.cpp b/vpr/src/route/router_lookahead/router_lookahead_compressed_map.cpp index 3e231e35426..c332205378c 100644 --- a/vpr/src/route/router_lookahead/router_lookahead_compressed_map.cpp +++ b/vpr/src/route/router_lookahead/router_lookahead_compressed_map.cpp @@ -121,7 +121,7 @@ static void compute_router_wire_compressed_lookahead(const std::vector(grid.get_num_layers()), 2, segment_inf_vec.size(), - static_cast(grid.get_num_layers()), + grid.get_num_layers(), static_cast(num_sampling_points)}); int longest_seg_length = 0; diff --git a/vpr/src/route/router_lookahead/router_lookahead_map.cpp b/vpr/src/route/router_lookahead/router_lookahead_map.cpp index fcce25245c1..47342ff91d4 100644 --- a/vpr/src/route/router_lookahead/router_lookahead_map.cpp +++ b/vpr/src/route/router_lookahead/router_lookahead_map.cpp @@ -496,16 +496,20 @@ float MapLookahead::get_opin_distance_min_delay(int physical_tile_idx, int from_ /******** Function Definitions ********/ static util::Cost_Entry get_wire_cost_entry(e_rr_type rr_type, int seg_index, int from_layer_num, int delta_x, int delta_y, int to_layer_num) { - VTR_ASSERT_SAFE(rr_type == e_rr_type::CHANX || rr_type == e_rr_type::CHANY); + VTR_ASSERT_SAFE(rr_type == e_rr_type::CHANX || rr_type == e_rr_type::CHANY || rr_type == e_rr_type::CHANZ); VTR_ASSERT_SAFE(from_layer_num < static_cast(f_wire_cost_map.dim_size(0))); VTR_ASSERT_SAFE(to_layer_num < static_cast(f_wire_cost_map.dim_size(1))); VTR_ASSERT_SAFE(seg_index < static_cast(f_wire_cost_map.dim_size(3))); VTR_ASSERT_SAFE(delta_x < static_cast(f_wire_cost_map.dim_size(4))); VTR_ASSERT_SAFE(delta_y < static_cast(f_wire_cost_map.dim_size(5))); - int chan_index = 0; - if (rr_type == e_rr_type::CHANY) { - chan_index = 1; + int chan_index; + switch (rr_type) { + case e_rr_type::CHANX: chan_index = 0; break; + case e_rr_type::CHANY: chan_index = 1; break; + case e_rr_type::CHANZ: chan_index = 2; break; + default: + VTR_ASSERT(false); } return f_wire_cost_map[from_layer_num][to_layer_num][chan_index][seg_index][delta_x][delta_y]; diff --git a/vpr/src/route/router_lookahead/router_lookahead_map_utils.cpp b/vpr/src/route/router_lookahead/router_lookahead_map_utils.cpp index fcde65eaa44..3dbf1c5bd00 100644 --- a/vpr/src/route/router_lookahead/router_lookahead_map_utils.cpp +++ b/vpr/src/route/router_lookahead/router_lookahead_map_utils.cpp @@ -141,7 +141,7 @@ PQ_Entry::PQ_Entry(RRNodeId set_rr_node, int /*switch_ind*/, float parent_delay, this->congestion_upstream = parent_congestion_upstream; this->R_upstream = parent_R_upstream; if (!starting_node) { - auto cost_index = rr_graph.node_cost_index(RRNodeId(set_rr_node)); + RRIndexedDataId cost_index = rr_graph.node_cost_index(RRNodeId(set_rr_node)); //this->delay += rr_graph.node_C(RRNodeId(set_rr_node)) * (g_rr_switch_inf[switch_ind].R + 0.5*rr_graph.node_R(RRNodeId(set_rr_node))) + // g_rr_switch_inf[switch_ind].Tdel; @@ -920,9 +920,10 @@ void dump_readable_router_lookahead_map(const std::string& file_name, const std: VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Unable to open file '%s' for writing\n", file_name.c_str()); } + const int chan_type_dim_size = (num_layers == 1) ? 2 : 3; VTR_ASSERT(dim_sizes[0] == num_layers); VTR_ASSERT(dim_sizes[1] == num_layers); - VTR_ASSERT(dim_sizes[2] == 2); + VTR_ASSERT(dim_sizes[2] == chan_type_dim_size); VTR_ASSERT(dim_sizes.size() == 5 || (dim_sizes.size() == 6 && dim_sizes[4] == grid_width && dim_sizes[5] == grid_height)); ofs << "from_layer," @@ -934,9 +935,14 @@ void dump_readable_router_lookahead_map(const std::string& file_name, const std: "cong_cost," "delay_cost\n"; + std::vector chan_types{e_rr_type::CHANX, e_rr_type::CHANY}; + if (num_layers > 1) { + chan_types.push_back(e_rr_type::CHANZ); + } + for (int from_layer_num = 0; from_layer_num < num_layers; from_layer_num++) { for (int to_layer_num = 0; to_layer_num < num_layers; to_layer_num++) { - for (e_rr_type chan_type : {e_rr_type::CHANX, e_rr_type::CHANY}) { + for (e_rr_type chan_type : chan_types) { for (int seg_index = 0; seg_index < dim_sizes[3]; seg_index++) { for (int dx = 0; dx < grid_width; dx++) { for (int dy = 0; dy < grid_height; dy++) { From 40d89f0a69dc39145de39bb3097bde22a2de98a4 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Sun, 14 Sep 2025 20:46:32 -0400 Subject: [PATCH 34/58] alloc_and_load_rr_indexed_data supports CHANZ --- libs/libarchfpga/src/echo_arch.cpp | 8 - libs/libarchfpga/src/physical_types.h | 1 - .../librrgraph/src/base/get_parallel_segs.cpp | 4 +- libs/librrgraph/src/base/rr_graph_type.h | 2 +- libs/librrgraph/src/io/rr_graph_reader.cpp | 4 +- libs/librrgraph/src/io/rr_graph_reader.h | 4 +- .../src/io/rr_graph_uxsdcxx_serializer.h | 32 ++- .../utils/alloc_and_load_rr_indexed_data.cpp | 253 +++++++++--------- .../utils/alloc_and_load_rr_indexed_data.h | 5 +- vpr/src/base/stats.cpp | 2 +- vpr/src/base/stats.h | 3 +- vpr/src/base/vpr_types.h | 2 +- vpr/src/power/power.cpp | 4 +- .../route/rr_graph_generation/rr_graph.cpp | 34 +-- vpr/src/route/rr_graph_generation/rr_graph.h | 7 +- .../rr_graph_generation/rr_graph_area.cpp | 28 +- .../route/rr_graph_generation/rr_graph_area.h | 2 +- .../tileable_rr_graph_builder.cpp | 10 +- .../tileable_rr_graph_builder.h | 4 +- 19 files changed, 211 insertions(+), 198 deletions(-) diff --git a/libs/libarchfpga/src/echo_arch.cpp b/libs/libarchfpga/src/echo_arch.cpp index 70456a8a204..0878a7adfd0 100644 --- a/libs/libarchfpga/src/echo_arch.cpp +++ b/libs/libarchfpga/src/echo_arch.cpp @@ -257,14 +257,6 @@ void PrintArchInfo(FILE* Echo, const t_arch* arch) { //wire_switch == arch_opin_switch fprintf(Echo, "\t\t\t\ttype unidir mux_name for within die connections: %s\n", arch->switches[seg.arch_wire_switch].name.c_str()); - //if there is more than one layer available, print the segment switch name that is used for connection between two dice - for (const auto& layout : arch->grid_layouts) { - int num_layers = (int)layout.layers.size(); - if (num_layers > 1) { - fprintf(Echo, "\t\t\t\ttype unidir mux_name for between two dice connections: %s\n", - arch->switches[seg.arch_inter_die_switch].name.c_str()); - } - } } else { //Should be bidir fprintf(Echo, "\t\t\t\ttype bidir wire_switch %s arch_opin_switch %s\n", arch->switches[seg.arch_wire_switch].name.c_str(), diff --git a/libs/libarchfpga/src/physical_types.h b/libs/libarchfpga/src/physical_types.h index faf0e8bac1c..7e7c1c3de60 100644 --- a/libs/libarchfpga/src/physical_types.h +++ b/libs/libarchfpga/src/physical_types.h @@ -1840,7 +1840,6 @@ inline bool operator==(const t_segment_inf& a, const t_segment_inf& b) { && a.length == b.length && a.arch_wire_switch == b.arch_wire_switch && a.arch_opin_switch == b.arch_opin_switch - && a.arch_inter_die_switch == b.arch_inter_die_switch && a.frac_cb == b.frac_cb && a.frac_sb == b.frac_sb && a.longline == b.longline diff --git a/libs/librrgraph/src/base/get_parallel_segs.cpp b/libs/librrgraph/src/base/get_parallel_segs.cpp index b9c0ad81a2c..4719e073fe0 100644 --- a/libs/librrgraph/src/base/get_parallel_segs.cpp +++ b/libs/librrgraph/src/base/get_parallel_segs.cpp @@ -6,7 +6,9 @@ std::vector get_parallel_segs(const std::vector& s bool keep_original_index /* = false */) { std::vector result; for (size_t i = 0; i < segment_inf.size(); ++i) { - if (segment_inf[i].parallel_axis == parallel_axis || segment_inf[i].parallel_axis == e_parallel_axis::BOTH_AXIS) { + e_parallel_axis seg_axis = segment_inf[i].parallel_axis; + if (seg_axis == parallel_axis + || (parallel_axis != e_parallel_axis::Z_AXIS && seg_axis == e_parallel_axis::BOTH_AXIS)) { result.push_back(segment_inf[i]); if (!keep_original_index) { result.back().seg_index = i; diff --git a/libs/librrgraph/src/base/rr_graph_type.h b/libs/librrgraph/src/base/rr_graph_type.h index a3362b248ef..4f419d29348 100644 --- a/libs/librrgraph/src/base/rr_graph_type.h +++ b/libs/librrgraph/src/base/rr_graph_type.h @@ -43,7 +43,7 @@ enum class e_graph_type { * * Each entry maps a unified segment index to a pair containing: * - The index in the corresponding axis-specific segment vector - * - The axis of the segment (X or Y) + * - The axis of the segment (X/Y/Z) * * @see get_parallel_segs for more details. */ diff --git a/libs/librrgraph/src/io/rr_graph_reader.cpp b/libs/librrgraph/src/io/rr_graph_reader.cpp index 875587695b8..ff0f8b9e4ae 100644 --- a/libs/librrgraph/src/io/rr_graph_reader.cpp +++ b/libs/librrgraph/src/io/rr_graph_reader.cpp @@ -65,8 +65,8 @@ void load_rr_file(RRGraphBuilder* rr_graph_builder, e_graph_type graph_type, const t_arch* arch, t_chan_width* chan_width, - const enum e_base_cost_type base_cost_type, - int* wire_to_rr_ipin_switch, + const e_base_cost_type base_cost_type, + RRSwitchId* wire_to_rr_ipin_switch, int* wire_to_rr_ipin_switch_between_dice, const char* read_rr_graph_name, std::string* loaded_rr_graph_filename, diff --git a/libs/librrgraph/src/io/rr_graph_reader.h b/libs/librrgraph/src/io/rr_graph_reader.h index 038addb22fc..1f3efbe2ae9 100644 --- a/libs/librrgraph/src/io/rr_graph_reader.h +++ b/libs/librrgraph/src/io/rr_graph_reader.h @@ -22,8 +22,8 @@ void load_rr_file(RRGraphBuilder* rr_graph_builder, e_graph_type graph_type, const t_arch* arch, t_chan_width* chan_width, - const enum e_base_cost_type base_cost_type, - int* wire_to_rr_ipin_switch, + const e_base_cost_type base_cost_type, + RRSwitchId* wire_to_rr_ipin_switch, int* wire_to_rr_ipin_switch_between_dice, const char* read_rr_graph_name, std::string* loaded_rr_graph_filename, diff --git a/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h b/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h index 2813600bb50..5a7d8d3e636 100644 --- a/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h +++ b/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h @@ -274,7 +274,7 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { RrGraphSerializer( const e_graph_type graph_type, const enum e_base_cost_type base_cost_type, - int* wire_to_rr_ipin_switch, + RRSwitchId* wire_to_rr_ipin_switch, int* wire_to_rr_ipin_switch_between_dice, bool do_check_rr_graph, const char* read_rr_graph_name, @@ -326,7 +326,7 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { , is_flat_(is_flat) { // Initialize internal data init_side_map(); - init_segment_inf_x_y(); + init_segment_inf_xyz(); curr_tmp_block_type_id = -1; curr_tmp_height_offset = -1; curr_tmp_width_offset = -1; @@ -391,9 +391,9 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { /** * @brief This function separates the segments in segment_inf_ based on whether their parallel axis - * is X or Y, and it stores them in segment_inf_x_ and segment_inf_y_. + * is X or Y or Z, and it stores them in segment_inf_x_ and segment_inf_y_ and segment_inf_z_. */ - void init_segment_inf_x_y(){ + void init_segment_inf_xyz(){ /* Create a temp copy to convert from vtr::vector to std::vector * This is required because the ``alloc_and_load_rr_indexed_data()`` function supports only std::vector data @@ -410,7 +410,7 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { t_unified_to_parallel_seg_index seg_index_map; segment_inf_x_ = get_parallel_segs(rr_segs, seg_index_map, e_parallel_axis::X_AXIS); segment_inf_y_ = get_parallel_segs(rr_segs, seg_index_map, e_parallel_axis::Y_AXIS); - + segment_inf_z_ = get_parallel_segs(rr_segs, seg_index_map, e_parallel_axis::Z_AXIS); } /** @@ -423,12 +423,15 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { int find_segment_index_along_axis(int segment_id, e_parallel_axis axis) const { const std::vector* segment_inf_vec_ptr; - if (axis == e_parallel_axis::X_AXIS) + if (axis == e_parallel_axis::X_AXIS) { segment_inf_vec_ptr = &segment_inf_x_; - else + } else if (axis == e_parallel_axis::Y_AXIS) { segment_inf_vec_ptr = &segment_inf_y_; + } else { + segment_inf_vec_ptr = &segment_inf_z_; + } - for(std::vector::size_type i=0; i < (*segment_inf_vec_ptr).size(); i++){ + for(std::vector::size_type i=0; i < segment_inf_vec_ptr->size(); i++){ if((*segment_inf_vec_ptr)[i].seg_index == segment_id) return static_cast(i); } @@ -844,9 +847,8 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { rr_graph_builder_->set_node_cost_index(node_id, RRIndexedDataId(CHANX_COST_INDEX_START + segment_inf_x_.size() + seg_ind_y)); seg_index_[rr_graph.node_cost_index(node.id())] = segment_id; } else if (rr_graph.node_type(node.id()) == e_rr_type::CHANZ) { - // TODO: Don't use CHANX info - int seg_ind_z = find_segment_index_along_axis(segment_id, e_parallel_axis::X_AXIS); - rr_graph_builder_->set_node_cost_index(node_id, RRIndexedDataId(CHANX_COST_INDEX_START + seg_ind_z)); + int seg_ind_z = find_segment_index_along_axis(segment_id, e_parallel_axis::Z_AXIS); + rr_graph_builder_->set_node_cost_index(node_id, RRIndexedDataId(CHANX_COST_INDEX_START + segment_inf_x_.size() + segment_inf_y_.size() + seg_ind_z)); seg_index_[rr_graph.node_cost_index(node.id())] = segment_id; } return inode; @@ -1038,7 +1040,7 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { inline void* init_rr_graph_rr_nodes(void*& /*ctx*/) final { rr_nodes_->clear(); - seg_index_.resize(CHANX_COST_INDEX_START + segment_inf_x_.size() + segment_inf_y_.size(), -1); + seg_index_.resize(CHANX_COST_INDEX_START + segment_inf_x_.size() + segment_inf_y_.size() + segment_inf_z_.size(), -1); return nullptr; } inline void finish_rr_graph_rr_nodes(void*& /*ctx*/) final { @@ -1202,7 +1204,7 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { } VTR_ASSERT(wire_to_rr_ipin_switch_ != nullptr); - *wire_to_rr_ipin_switch_ = most_frequent_switch.first; + *wire_to_rr_ipin_switch_ = (RRSwitchId)most_frequent_switch.first; VTR_ASSERT(wire_to_rr_ipin_switch_between_dice_ != nullptr); *wire_to_rr_ipin_switch_between_dice_ = most_frequent_switch_between_dice.first; @@ -1835,6 +1837,7 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { temp_rr_segs, segment_inf_x_, segment_inf_y_, + segment_inf_z_, *rr_indexed_data_, *wire_to_rr_ipin_switch_, base_cost_type_, @@ -2186,7 +2189,7 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { std::array side_map_; // Output for loads, and constant data for writes. - int* wire_to_rr_ipin_switch_; + RRSwitchId* wire_to_rr_ipin_switch_; int* wire_to_rr_ipin_switch_between_dice_; t_chan_width* chan_width_; t_rr_graph_storage* rr_nodes_; @@ -2214,6 +2217,7 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { const vtr::vector& segment_inf_; std::vector segment_inf_x_; // [num_segs_along_x_axis-1:0] - vector of segment information for segments along the x-axis. std::vector segment_inf_y_; // [num_segs_along_y_axis-1:0] - vector of segment information for segments along the y-axis. + std::vector segment_inf_z_; // [num_segs_along_z_axis-1:0] - vector of segment information for segments along the z-axis. const std::vector& physical_tile_types_; const DeviceGrid& grid_; MetadataStorage* rr_node_metadata_; diff --git a/libs/librrgraph/src/utils/alloc_and_load_rr_indexed_data.cpp b/libs/librrgraph/src/utils/alloc_and_load_rr_indexed_data.cpp index 2007b713537..89d44d0878a 100644 --- a/libs/librrgraph/src/utils/alloc_and_load_rr_indexed_data.cpp +++ b/libs/librrgraph/src/utils/alloc_and_load_rr_indexed_data.cpp @@ -25,13 +25,36 @@ static float get_delay_normalization_fac(const vtr::vector& rr_indexed_data); -static void calculate_average_switch(const RRGraphView& rr_graph, int inode, double& avg_switch_R, double& avg_switch_T, double& avg_switch_Cinternal, int& num_switches, int& num_shorts, short& buffered, vtr::vector>& fan_in_list); +/** + * @brief Computes average R, Tdel, and Cinternal of fan-in switches for a given node. + * + * Iterates over all incoming edges of @p inode, skipping SHORT switches, + * and averages their electrical properties. Also counts shorts, tracks the + * number of valid switches, and determines whether the node is buffered + * (true if any fan-in switch is buffered). + * + * @note It is not safe to assume that each node of the same wire type has the same switches with the same + * delays, therefore we take their average to take into account the possible differences + */ +static void calculate_average_switch(const RRGraphView& rr_graph, + RRNodeId inode, + double& avg_switch_R, + double& avg_switch_T, + double& avg_switch_Cinternal, + int& num_switches, + int& num_shorts, + short& buffered, + vtr::vector>& fan_in_list); static void fixup_rr_indexed_data_T_values(vtr::vector& rr_indexed_data, size_t num_segment); static std::vector count_rr_segment_types(const RRGraphView& rr_graph, const vtr::vector& rr_indexed_data); -static void print_rr_index_info(const vtr::vector& rr_indexed_data, const char* fname, const std::vector& segment_inf, size_t y_chan_cost_offset); +static void print_rr_index_info(const vtr::vector& rr_indexed_data, + const char* fname, + const std::vector& segment_inf, + size_t y_chan_cost_offset, + size_t z_chan_cost_offset); /******************** Subroutine definitions *********************************/ @@ -53,23 +76,23 @@ void alloc_and_load_rr_indexed_data(const RRGraphView& rr_graph, const std::vector& segment_inf, const std::vector& segment_inf_x, const std::vector& segment_inf_y, + const std::vector& segment_inf_z, vtr::vector& rr_indexed_data, - int wire_to_ipin_switch, - enum e_base_cost_type base_cost_type, + RRSwitchId wire_to_ipin_switch, + e_base_cost_type base_cost_type, const bool echo_enabled, const char* echo_file_name) { - (void)segment_inf; - int total_num_segment = segment_inf_x.size() + segment_inf_y.size(); - /*CHAX & CHANY segment lsit sizes may differ. but if we're using uniform channels, they - * will each have size equal to segment_inf.size()*/ + int total_num_segment = segment_inf_x.size() + segment_inf_y.size() + segment_inf_z.size(); + + // CHAX & CHANY segment list sizes may differ, but if we're using uniform channels, they will have equal sizes int num_rr_indexed_data = CHANX_COST_INDEX_START + total_num_segment; rr_indexed_data.resize(num_rr_indexed_data); - /* For rr_types that aren't CHANX or CHANY, base_cost is valid, but most * - * * other fields are invalid. For IPINs, the T_linear field is also valid; * - * * all other fields are invalid. For SOURCES, SINKs and OPINs, all fields * - * * other than base_cost are invalid. Mark invalid fields as OPEN for safety. */ - + // For rr_types that aren't CHANX/CHANY/CHANZ, base_cost is valid, but most + // other fields are invalid. For IPINs, the T_linear field is also valid; + // all other fields are invalid. For SOURCES, SINKs and OPINs, all fields + // other than base_cost are invalid. Mark invalid fields as LIBRRGRAPH_UNDEFINED_VAL + // for safety. for (int i = SOURCE_COST_INDEX; i <= IPIN_COST_INDEX; i++) { rr_indexed_data[RRIndexedDataId(i)].ortho_cost_index = LIBRRGRAPH_UNDEFINED_VAL; rr_indexed_data[RRIndexedDataId(i)].seg_index = LIBRRGRAPH_UNDEFINED_VAL; @@ -80,7 +103,7 @@ void alloc_and_load_rr_indexed_data(const RRGraphView& rr_graph, } //TODO: SM: IPIN t_linear assumes wire_to_ipin_switch which corresponds to within die switch connection - rr_indexed_data[RRIndexedDataId(IPIN_COST_INDEX)].T_linear = rr_graph.rr_switch_inf(RRSwitchId(wire_to_ipin_switch)).Tdel; + rr_indexed_data[RRIndexedDataId(IPIN_COST_INDEX)].T_linear = rr_graph.rr_switch_inf(wire_to_ipin_switch).Tdel; std::vector ortho_costs = find_ortho_cost_index(rr_graph, segment_inf_x, segment_inf_y, e_parallel_axis::X_AXIS); @@ -96,41 +119,37 @@ void alloc_and_load_rr_indexed_data(const RRGraphView& rr_graph, * std::move(y_costs.begin(), y_costs.end(), std::back_inserter(ortho_costs)); */ - /* X-directed segments*/ - - for (size_t iseg = 0; iseg < segment_inf_x.size(); ++iseg) { - int index = iseg + CHANX_COST_INDEX_START; - - rr_indexed_data[RRIndexedDataId(index)].ortho_cost_index = ortho_costs[iseg]; - - int length; - if (segment_inf_x[iseg].longline) - length = grid.width(); - else - length = std::min(segment_inf_x[iseg].length, grid.width()); - - rr_indexed_data[RRIndexedDataId(index)].inv_length = 1. / length; - /*We use the index fo the segment in the **unified** seg_inf vector not iseg which is relative - * to parallel axis segments vector */ - rr_indexed_data[RRIndexedDataId(index)].seg_index = segment_inf_x[iseg].seg_index; - } - - /* Y-directed segments*/ - - for (size_t iseg = segment_inf_x.size(); iseg < ortho_costs.size(); ++iseg) { - int index = iseg + CHANX_COST_INDEX_START; - rr_indexed_data[RRIndexedDataId(index)].ortho_cost_index = ortho_costs[iseg]; + for (size_t iseg = 0; iseg < total_num_segment; ++iseg) { + RRIndexedDataId index = RRIndexedDataId(iseg + CHANX_COST_INDEX_START); + + const t_segment_inf* seg_ptr = nullptr; + int offset = 0; + + if (iseg < segment_inf_x.size()) { + // X-directed + seg_ptr = &segment_inf_x[iseg]; + rr_indexed_data[index].ortho_cost_index = ortho_costs[iseg]; + } else if (iseg < segment_inf_x.size() + segment_inf_y.size()) { + // Y-directed + offset = iseg - segment_inf_x.size(); + seg_ptr = &segment_inf_y[offset]; + rr_indexed_data[index].ortho_cost_index = ortho_costs[iseg]; + } else { + // Z-directed + offset = iseg - segment_inf_x.size() - segment_inf_y.size(); + seg_ptr = &segment_inf_z[offset]; + rr_indexed_data[index].ortho_cost_index = LIBRRGRAPH_UNDEFINED_VAL; + } int length; - if (segment_inf_x[iseg - segment_inf_x.size()].longline) + if (seg_ptr->longline) { length = grid.width(); - else - length = std::min(segment_inf_y[iseg - segment_inf_x.size()].length, grid.width()); + } else { + length = std::min(seg_ptr->length, grid.width()); + } - rr_indexed_data[RRIndexedDataId(index)].inv_length = 1. / length; - /*We use the index fo the segment in the **unified** seg_inf vector not iseg which is relative - * to parallel axis segments vector */ - rr_indexed_data[RRIndexedDataId(index)].seg_index = segment_inf_y[iseg - segment_inf_x.size()].seg_index; + rr_indexed_data[index].inv_length = 1. / length; + rr_indexed_data[index].seg_index = seg_ptr->seg_index; } load_rr_indexed_data_T_values(rr_graph, rr_indexed_data); @@ -142,7 +161,9 @@ void alloc_and_load_rr_indexed_data(const RRGraphView& rr_graph, if (echo_enabled) { print_rr_index_info(rr_indexed_data, echo_file_name, - segment_inf, segment_inf_x.size()); + segment_inf, + segment_inf_x.size(), + segment_inf_x.size() + segment_inf_y.size()); } } @@ -160,12 +181,11 @@ std::vector find_ortho_cost_index(const RRGraphView& rr_graph, const std::vector& segment_inf_y, e_parallel_axis parallel_axis) { size_t num_segments = segment_inf_x.size() + segment_inf_y.size(); - std::vector> dest_nodes_count; - - // x segments are perpendicular to y segments - dest_nodes_count.resize(num_segments); + // dest_nodes_count[seg][perp_seg] counts how many times each segment type is connected to perpendicular segment types + std::vector> dest_nodes_count(num_segments); + // x segments are perpendicular to y segments for (size_t iseg = 0; iseg < segment_inf_x.size(); iseg++) { dest_nodes_count[iseg].resize(segment_inf_y.size()); } @@ -174,8 +194,6 @@ std::vector find_ortho_cost_index(const RRGraphView& rr_graph, dest_nodes_count[iseg].resize(segment_inf_x.size()); } - std::vector ortho_cost_indices(dest_nodes_count.size(), 0); - // Go through all rr_Nodes. Look at the ones with CHAN type. Count all outgoing edges to CHAN typed nodes from each CHAN type node. for (const RRNodeId rr_node : rr_graph.nodes()) { for (size_t iedge = 0; iedge < rr_graph.num_edges(rr_node); ++iedge) { @@ -194,23 +212,19 @@ std::vector find_ortho_cost_index(const RRGraphView& rr_graph, } else { dest_nodes_count[from_node_cost_index - CHANX_COST_INDEX_START][to_node_cost_index - CHANX_COST_INDEX_START]++; } - } else { - continue; } } } - for (size_t iseg = 0; iseg < segment_inf_x.size(); iseg++) { - dest_nodes_count[iseg].resize(segment_inf_y.size()); - } + std::vector ortho_cost_indices(num_segments, 0); for (size_t iseg = 0; iseg < segment_inf_x.size(); iseg++) { - ortho_cost_indices[iseg] = std::max_element(dest_nodes_count[iseg].begin(), dest_nodes_count[iseg].end()) - dest_nodes_count[iseg].begin(); + ortho_cost_indices[iseg] = std::ranges::max_element(dest_nodes_count[iseg]) - dest_nodes_count[iseg].begin(); ortho_cost_indices[iseg] += CHANX_COST_INDEX_START + segment_inf_x.size(); } for (size_t iseg = segment_inf_x.size(); iseg < num_segments; iseg++) { - ortho_cost_indices[iseg] = std::max_element(dest_nodes_count[iseg].begin(), dest_nodes_count[iseg].end()) - dest_nodes_count[iseg].begin(); + ortho_cost_indices[iseg] = std::ranges::max_element(dest_nodes_count[iseg]) - dest_nodes_count[iseg].begin(); ortho_cost_indices[iseg] += CHANX_COST_INDEX_START; } @@ -330,12 +344,9 @@ static void load_rr_indexed_data_base_costs(const RRGraphView& rr_graph, enum e_base_cost_type base_cost_type, const bool echo_enabled, const char* echo_file_name) { - /* Loads the base_cost member of rr_indexed_data according to the specified * - * base_cost_type. */ + // Loads the base_cost member of rr_indexed_data according to the specified base_cost_type. float delay_normalization_fac; - size_t index; - if (base_cost_type == DEMAND_ONLY || base_cost_type == DEMAND_ONLY_NORMALIZED_LENGTH) { delay_normalization_fac = 1.; } else { @@ -361,7 +372,7 @@ static void load_rr_indexed_data_base_costs(const RRGraphView& rr_graph, float max_length = 0; float min_length = 1; if (base_cost_type == DELAY_NORMALIZED_LENGTH_BOUNDED) { - for (index = CHANX_COST_INDEX_START; index < rr_indexed_data.size(); index++) { + for (size_t index = CHANX_COST_INDEX_START; index < rr_indexed_data.size(); index++) { float length = (1 / rr_indexed_data[RRIndexedDataId(index)].inv_length); max_length = std::max(max_length, length); } @@ -371,13 +382,11 @@ static void load_rr_indexed_data_base_costs(const RRGraphView& rr_graph, // perhaps consider lowering cost of wires which connect to IPINs // so they get explored earlier (same rational as lowering IPIN costs) - for (index = CHANX_COST_INDEX_START; index < rr_indexed_data.size(); index++) { + for (size_t index = CHANX_COST_INDEX_START; index < rr_indexed_data.size(); index++) { if (base_cost_type == DELAY_NORMALIZED || base_cost_type == DEMAND_ONLY) { rr_indexed_data[RRIndexedDataId(index)].base_cost = delay_normalization_fac; - } else if (base_cost_type == DELAY_NORMALIZED_LENGTH || base_cost_type == DEMAND_ONLY_NORMALIZED_LENGTH) { rr_indexed_data[RRIndexedDataId(index)].base_cost = delay_normalization_fac / rr_indexed_data[RRIndexedDataId(index)].inv_length; - } else if (base_cost_type == DELAY_NORMALIZED_LENGTH_BOUNDED) { float length = (1 / rr_indexed_data[RRIndexedDataId(index)].inv_length); if (max_length != min_length) { @@ -416,7 +425,7 @@ static void load_rr_indexed_data_base_costs(const RRGraphView& rr_graph, * router, the base_cost values will get changed all the time and being * * able to restore them from a saved version is useful. */ - for (index = 0; index < rr_indexed_data.size(); index++) { + for (size_t index = 0; index < rr_indexed_data.size(); index++) { rr_indexed_data[RRIndexedDataId(index)].saved_base_cost = rr_indexed_data[RRIndexedDataId(index)].base_cost; } } @@ -501,47 +510,41 @@ static void load_rr_indexed_data_T_values(const RRGraphView& rr_graph, vtr::vector> C_total(rr_indexed_data.size()); vtr::vector> R_total(rr_indexed_data.size()); - /* - * Not all wire-to-wire switches connecting from some wire segment will necessarily have the same delay. - * i.e. a mux with less inputs will have smaller delay than a mux with a greater number of inputs. - * So to account for these differences we will get the average R/Tdel/Cinternal values by first averaging - * them for a single wire segment, and then by averaging this value over all the average values corresponding - * to the switches node - */ + + // Not all wire-to-wire switches connecting from some wire segment will necessarily have the same delay. + // i.e. a mux with less inputs will have smaller delay than a mux with a greater number of inputs. + // So to account for these differences we will get the average R/Tdel/Cinternal values by first averaging + // them for a single wire segment, and then by averaging this value over all the average values corresponding + // to the switches node vtr::vector> switch_R_total(rr_indexed_data.size()); vtr::vector> switch_T_total(rr_indexed_data.size()); vtr::vector> switch_Cinternal_total(rr_indexed_data.size()); vtr::vector switches_buffered(rr_indexed_data.size(), LIBRRGRAPH_UNDEFINED_VAL); - /* - * Walk through the RR graph and collect all R and C values of all the nodes, - * as well as their fan-in switches R, T_del, and Cinternal values. - * - * The median of R and C values for each cost index is assigned to the indexed - * data. - */ + // Walk through the RR graph and collect all R and C values of all the nodes, + // as well as their fan-in switches R, T_del, and Cinternal values. + // The median of R and C values for each cost index is assigned to the indexed data. for (const RRNodeId rr_id : rr_graph.nodes()) { e_rr_type rr_type = rr_graph.node_type(rr_id); - if (rr_type != e_rr_type::CHANX && rr_type != e_rr_type::CHANY) { + if (!is_chanxy(rr_type) && !is_chanz(rr_type)) { continue; } - auto cost_index = rr_graph.node_cost_index(rr_id); + RRIndexedDataId cost_index = rr_graph.node_cost_index(rr_id); - auto node_cords = rr_graph.node_coordinate_to_string(RRNodeId(rr_id)); - - /* get average switch parameters */ + // Get average switch parameters double avg_switch_R = 0; double avg_switch_T = 0; double avg_switch_Cinternal = 0; int num_switches = 0; int num_shorts = 0; short buffered = LIBRRGRAPH_UNDEFINED_VAL; - calculate_average_switch(rr_graph, (size_t)rr_id, avg_switch_R, avg_switch_T, avg_switch_Cinternal, num_switches, num_shorts, buffered, fan_in_list); + calculate_average_switch(rr_graph, rr_id, avg_switch_R, avg_switch_T, avg_switch_Cinternal, num_switches, num_shorts, buffered, fan_in_list); if (num_switches == 0) { if (num_shorts == 0) { + std::string node_cords = rr_graph.node_coordinate_to_string(RRNodeId(rr_id)); VTR_LOG_WARN("Node: %d with RR_type: %s at Location:%s, had no out-going switches\n", rr_id, rr_graph.node_type_string(rr_id), node_cords.c_str()); } @@ -557,11 +560,11 @@ static void load_rr_indexed_data_T_values(const RRGraphView& rr_graph, switch_T_total[cost_index].push_back(avg_switch_T); switch_Cinternal_total[cost_index].push_back(avg_switch_Cinternal); if (buffered == LIBRRGRAPH_UNDEFINED_VAL) { - /* this segment does not have any outgoing edges to other general routing wires */ + // This segment does not have any outgoing edges to other general routing wires continue; } - /* need to make sure all wire switches of a given wire segment type have the same 'buffered' value */ + // Need to make sure all wire switches of a given wire segment type have the same 'buffered' value if (switches_buffered[cost_index] == LIBRRGRAPH_UNDEFINED_VAL) { switches_buffered[cost_index] = buffered; } else { @@ -578,9 +581,8 @@ static void load_rr_indexed_data_T_values(const RRGraphView& rr_graph, } unsigned num_occurences_of_no_instances_with_cost_index = 0; - for (size_t cost_index = CHANX_COST_INDEX_START; - cost_index < rr_indexed_data.size(); cost_index++) { - if (num_nodes_of_index[RRIndexedDataId(cost_index)] == 0) { /* Segments don't exist. */ + for (size_t cost_index = CHANX_COST_INDEX_START; cost_index < rr_indexed_data.size(); cost_index++) { + if (num_nodes_of_index[RRIndexedDataId(cost_index)] == 0) { // Segments don't exist. rr_indexed_data[RRIndexedDataId(cost_index)].T_linear = 0.0; rr_indexed_data[RRIndexedDataId(cost_index)].T_quadratic = 0.0; rr_indexed_data[RRIndexedDataId(cost_index)].C_load = 0.0; @@ -614,14 +616,13 @@ static void load_rr_indexed_data_T_values(const RRGraphView& rr_graph, + 0.5 * Rnode * (Cnode + Cinternalsw); rr_indexed_data[RRIndexedDataId(cost_index)].T_quadratic = 0.; rr_indexed_data[RRIndexedDataId(cost_index)].C_load = 0.; - } else { /* Pass transistor, does not have an internal capacitance*/ + } else { // Pass transistor, does not have an internal capacitance rr_indexed_data[RRIndexedDataId(cost_index)].C_load = Cnode; /* See Dec. 23, 1997 notes for deriviation of formulae. */ rr_indexed_data[RRIndexedDataId(cost_index)].T_linear = Tsw + 0.5 * Rsw * Cnode; - rr_indexed_data[RRIndexedDataId(cost_index)].T_quadratic = (Rsw + Rnode) * 0.5 - * Cnode; + rr_indexed_data[RRIndexedDataId(cost_index)].T_quadratic = (Rsw + Rnode) * 0.5 * Cnode; } } } @@ -631,15 +632,15 @@ static void load_rr_indexed_data_T_values(const RRGraphView& rr_graph, } } -/* - * This routine calculates the average R/Tdel/Cinternal values of all the switches corresponding - * to the fan-in edges of the input inode. - * - * It is not safe to assume that each node of the same wire type has the same switches with the same - * delays, therefore we take their average to take into account the possible differences - */ -static void calculate_average_switch(const RRGraphView& rr_graph, int inode, double& avg_switch_R, double& avg_switch_T, double& avg_switch_Cinternal, int& num_switches, int& num_shorts, short& buffered, vtr::vector>& fan_in_list) { - auto node = RRNodeId(inode); +static void calculate_average_switch(const RRGraphView& rr_graph, + RRNodeId inode, + double& avg_switch_R, + double& avg_switch_T, + double& avg_switch_Cinternal, + int& num_switches, + int& num_shorts, + short& buffered, + vtr::vector>& fan_in_list) { avg_switch_R = 0; avg_switch_T = 0; @@ -647,27 +648,30 @@ static void calculate_average_switch(const RRGraphView& rr_graph, int inode, dou num_switches = 0; num_shorts = 0; buffered = LIBRRGRAPH_UNDEFINED_VAL; - for (const auto& edge : fan_in_list[node]) { - /* want to get C/R/Tdel/Cinternal of switches that connect this track segment to other track segments */ - if (rr_graph.node_type(node) == e_rr_type::CHANX || rr_graph.node_type(node) == e_rr_type::CHANY) { - int switch_index = rr_graph.rr_nodes().edge_switch(edge); - if (rr_graph.rr_switch_inf(RRSwitchId(switch_index)).type() == SwitchType::SHORT) { + for (const RREdgeId edge : fan_in_list[inode]) { + // Want to get C/R/Tdel/Cinternal of switches that connect this track segment to other track segments + e_rr_type node_type = rr_graph.node_type(inode); + + if (is_chanxy(node_type) || is_chanz(node_type)) { + RRSwitchId switch_index = (RRSwitchId)rr_graph.rr_nodes().edge_switch(edge); + + if (rr_graph.rr_switch_inf(switch_index).type() == SwitchType::SHORT) { num_shorts++; continue; } - avg_switch_R += rr_graph.rr_switch_inf(RRSwitchId(switch_index)).R; - avg_switch_T += rr_graph.rr_switch_inf(RRSwitchId(switch_index)).Tdel; - avg_switch_Cinternal += rr_graph.rr_switch_inf(RRSwitchId(switch_index)).Cinternal; + avg_switch_R += rr_graph.rr_switch_inf(switch_index).R; + avg_switch_T += rr_graph.rr_switch_inf(switch_index).Tdel; + avg_switch_Cinternal += rr_graph.rr_switch_inf(switch_index).Cinternal; if (buffered == LIBRRGRAPH_UNDEFINED_VAL) { - if (rr_graph.rr_switch_inf(RRSwitchId(switch_index)).buffered()) { + if (rr_graph.rr_switch_inf(switch_index).buffered()) { buffered = 1; } else { buffered = 0; } - } else if (buffered != rr_graph.rr_switch_inf(RRSwitchId(switch_index)).buffered()) { + } else if (buffered != rr_graph.rr_switch_inf((switch_index)).buffered()) { // If a previous buffering state is inconsistent with the current one, // the node should be treated as buffered, as there are only two possible // values for the buffering state (except for the UNDEFINED case). @@ -698,15 +702,19 @@ static void fixup_rr_indexed_data_T_values(vtr::vector& rr_indexed_data, const char* fname, const std::vector& segment_inf, - size_t y_chan_cost_offset) { + size_t y_chan_cost_offset, + size_t z_chan_cost_offset) { std::ofstream out_file; out_file.open(fname, std::ios_base::app); @@ -739,7 +748,7 @@ static void print_rr_index_info(const vtr::vector& segment_inf, const std::vector& segment_inf_x, const std::vector& segment_inf_y, + const std::vector& segment_inf_z, vtr::vector& rr_indexed_data, - int wire_to_ipin_switch, - enum e_base_cost_type base_cost_type, + RRSwitchId wire_to_ipin_switch, + e_base_cost_type base_cost_type, const bool echo_enabled, const char* echo_file_name); diff --git a/vpr/src/base/stats.cpp b/vpr/src/base/stats.cpp index b8e139079a2..7ece122c4bc 100644 --- a/vpr/src/base/stats.cpp +++ b/vpr/src/base/stats.cpp @@ -69,7 +69,7 @@ void routing_stats(const Netlist<>& net_list, float R_minW_pmos, float grid_logic_tile_area, e_directionality directionality, - int wire_to_ipin_switch, + RRSwitchId wire_to_ipin_switch, bool is_flat) { auto& device_ctx = g_vpr_ctx.device(); auto& rr_graph = device_ctx.rr_graph; diff --git a/vpr/src/base/stats.h b/vpr/src/base/stats.h index e986827fd4d..1f9efe45afd 100644 --- a/vpr/src/base/stats.h +++ b/vpr/src/base/stats.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include "netlist.h" #include "rr_graph_type.h" @@ -20,7 +21,7 @@ void routing_stats(const Netlist<>& net_list, float R_minW_pmos, float grid_logic_tile_area, e_directionality directionality, - int wire_to_ipin_switch, + RRSwitchId wire_to_ipin_switch, bool is_flat); /** diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index 85d85906eb2..1d6b30cc455 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -1480,7 +1480,7 @@ struct t_det_routing_arch { /// keeps track of the type of RR graph switch /// that connects wires to ipins in the RR graph - int wire_to_rr_ipin_switch; + RRSwitchId wire_to_rr_ipin_switch; /// keeps track of the type of RR graph switch that connects wires /// from another die to ipins in different die in the RR graph diff --git a/vpr/src/power/power.cpp b/vpr/src/power/power.cpp index 4ea38c8fcf5..1adedffd271 100644 --- a/vpr/src/power/power.cpp +++ b/vpr/src/power/power.cpp @@ -979,7 +979,7 @@ static void power_usage_routing(t_power_usage* power_usage, connectionbox_fanout = 0; switchbox_fanout = 0; for (t_edge_size iedge = 0; iedge < rr_graph.num_edges(rr_id); iedge++) { - if (rr_graph.edge_switch(rr_id, iedge) == routing_arch.wire_to_rr_ipin_switch) { + if ((RRSwitchId)rr_graph.edge_switch(rr_id, iedge) == routing_arch.wire_to_rr_ipin_switch) { connectionbox_fanout++; } else if (rr_graph.edge_switch(rr_id, iedge) == routing_arch.delayless_switch) { /* Do nothing */ @@ -1225,7 +1225,7 @@ void power_routing_init(const t_det_routing_arch& routing_arch) { case e_rr_type::CHANX: case e_rr_type::CHANY: for (t_edge_size iedge = 0; iedge < rr_graph.num_edges(rr_node_idx); iedge++) { - if (rr_graph.edge_switch(rr_node_idx, iedge) == routing_arch.wire_to_rr_ipin_switch) { + if ((RRSwitchId)rr_graph.edge_switch(rr_node_idx, iedge) == routing_arch.wire_to_rr_ipin_switch) { fanout_to_IPIN++; } else if (rr_graph.edge_switch(rr_node_idx, iedge) != routing_arch.delayless_switch) { fanout_to_seg++; diff --git a/vpr/src/route/rr_graph_generation/rr_graph.cpp b/vpr/src/route/rr_graph_generation/rr_graph.cpp index 551ac9c0b0a..a0cf8e861ce 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph.cpp +++ b/vpr/src/route/rr_graph_generation/rr_graph.cpp @@ -612,7 +612,7 @@ static void build_rr_graph(e_graph_type graph_type, const e_clock_modeling clock_modeling, const std::vector& directs, const std::vector& scatter_gather_patterns, - int* wire_to_rr_ipin_switch, + RRSwitchId* wire_to_rr_ipin_switch, bool is_flat, int* Warnings, const int route_verbosity); @@ -955,7 +955,7 @@ static void build_rr_graph(e_graph_type graph_type, const e_clock_modeling clock_modeling, const std::vector& directs, const std::vector& scatter_gather_patterns, - int* wire_to_rr_ipin_switch, + RRSwitchId* wire_to_rr_ipin_switch, bool is_flat, int* Warnings, const int route_verbosity) { @@ -995,6 +995,7 @@ static void build_rr_graph(e_graph_type graph_type, t_unified_to_parallel_seg_index segment_index_map; std::vector segment_inf_x = get_parallel_segs(segment_inf, segment_index_map, e_parallel_axis::X_AXIS); std::vector segment_inf_y = get_parallel_segs(segment_inf, segment_index_map, e_parallel_axis::Y_AXIS); + std::vector segment_inf_z = get_parallel_segs(segment_inf, segment_index_map, e_parallel_axis::Z_AXIS); std::vector seg_details_x; std::vector seg_details_y; @@ -1383,10 +1384,10 @@ static void build_rr_graph(e_graph_type graph_type, // edge subsets. Must be done after RR switches have been allocated device_ctx.rr_graph_builder.partition_edges(); - //Save the channel widths for the newly constructed graph + // Save the channel widths for the newly constructed graph device_ctx.chan_width = nodes_per_chan; - rr_graph_externals(segment_inf, segment_inf_x, segment_inf_y, *wire_to_rr_ipin_switch, base_cost_type); + rr_graph_externals(segment_inf, segment_inf_x, segment_inf_y, segment_inf_z, *wire_to_rr_ipin_switch, base_cost_type); const VibDeviceGrid vib_grid; check_rr_graph(device_ctx.rr_graph, @@ -1519,14 +1520,14 @@ void build_tile_rr_graph(RRGraphBuilder& rr_graph_builder, delayless_switch); std::vector> switch_fanin_remap; - int dummy_int; + RRSwitchId dummy_sw_id; alloc_and_load_rr_switch_inf(rr_graph_builder, switch_fanin_remap, sw_map, det_routing_arch.R_minW_nmos, det_routing_arch.R_minW_pmos, det_routing_arch.wire_to_arch_ipin_switch, - &dummy_int); + &dummy_sw_id); rr_graph_builder.partition_edges(); } @@ -1553,7 +1554,7 @@ void alloc_and_load_rr_switch_inf(RRGraphBuilder& rr_graph_builder, const float R_minW_nmos, const float R_minW_pmos, const int wire_to_arch_ipin_switch, - int* wire_to_rr_ipin_switch) { + RRSwitchId* wire_to_rr_ipin_switch) { // we will potentially be creating a couple of versions of each arch switch where // each version corresponds to a different fan-in. We will need to fill device_ctx.rr_switch_inf // with this expanded list of switches. @@ -1587,7 +1588,7 @@ void alloc_and_load_rr_switch_inf(RRGraphBuilder& rr_graph_builder, // return a representative switch if (arch_switch_fanins[wire_to_arch_ipin_switch].count(UNDEFINED)) { // only have one ipin cblock switch. OK. - (*wire_to_rr_ipin_switch) = arch_switch_fanins[wire_to_arch_ipin_switch][UNDEFINED]; + (*wire_to_rr_ipin_switch) = (RRSwitchId)arch_switch_fanins[wire_to_arch_ipin_switch][UNDEFINED]; } else if (arch_switch_fanins[wire_to_arch_ipin_switch].size() != 0) { VPR_FATAL_ERROR(VPR_ERROR_ARCH, "Not currently allowing an ipin cblock switch to have multiple fan-ins"); @@ -1597,7 +1598,7 @@ void alloc_and_load_rr_switch_inf(RRGraphBuilder& rr_graph_builder, // //Instead of throwing an error we issue a warning. This means that check_rr_graph() etc. will run to give more information //and allow graphics to be brought up for users to debug their architectures. - (*wire_to_rr_ipin_switch) = UNDEFINED; + (*wire_to_rr_ipin_switch) = RRSwitchId::INVALID(); VTR_LOG_WARN("No switch found for the ipin cblock in RR graph. Check if there is an error in arch file, or if no connection blocks are being built in RR graph\n"); } } @@ -1738,18 +1739,19 @@ static void remap_rr_node_switch_indices(RRGraphBuilder& rr_graph_builder, void rr_graph_externals(const std::vector& segment_inf, const std::vector& segment_inf_x, const std::vector& segment_inf_y, - int wire_to_rr_ipin_switch, - enum e_base_cost_type base_cost_type) { - auto& device_ctx = g_vpr_ctx.device(); + const std::vector& segment_inf_z, + RRSwitchId wire_to_rr_ipin_switch, + e_base_cost_type base_cost_type) { + const DeviceContext& device_ctx = g_vpr_ctx.device(); const auto& rr_graph = device_ctx.rr_graph; const auto& grid = device_ctx.grid; auto& mutable_device_ctx = g_vpr_ctx.mutable_device(); - auto& rr_indexed_data = mutable_device_ctx.rr_indexed_data; + vtr::vector& rr_indexed_data = mutable_device_ctx.rr_indexed_data; bool echo_enabled = getEchoEnabled() && isEchoFileEnabled(E_ECHO_RR_GRAPH_INDEXED_DATA); const char* echo_file_name = getEchoFileName(E_ECHO_RR_GRAPH_INDEXED_DATA); - add_rr_graph_C_from_switches(rr_graph.rr_switch_inf(RRSwitchId(wire_to_rr_ipin_switch)).Cin); - alloc_and_load_rr_indexed_data(rr_graph, grid, segment_inf, segment_inf_x, - segment_inf_y, rr_indexed_data, wire_to_rr_ipin_switch, base_cost_type, echo_enabled, echo_file_name); + add_rr_graph_C_from_switches(rr_graph.rr_switch_inf(wire_to_rr_ipin_switch).Cin); + alloc_and_load_rr_indexed_data(rr_graph, grid, segment_inf, segment_inf_x, segment_inf_y, segment_inf_z, + rr_indexed_data, wire_to_rr_ipin_switch, base_cost_type, echo_enabled, echo_file_name); //load_rr_index_segments(segment_inf.size()); } diff --git a/vpr/src/route/rr_graph_generation/rr_graph.h b/vpr/src/route/rr_graph_generation/rr_graph.h index ba61e028998..eb6d7204e66 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph.h +++ b/vpr/src/route/rr_graph_generation/rr_graph.h @@ -51,13 +51,14 @@ void alloc_and_load_rr_switch_inf(RRGraphBuilder& rr_graph_builder, const float R_minW_nmos, const float R_minW_pmos, const int wire_to_arch_ipin_switch, - int* wire_to_rr_ipin_switch); + RRSwitchId* wire_to_rr_ipin_switch); void rr_graph_externals(const std::vector& segment_inf, const std::vector& segment_inf_x, const std::vector& segment_inf_y, - int wire_to_rr_ipin_switch, - enum e_base_cost_type base_cost_type); + const std::vector& segment_inf_z, + RRSwitchId wire_to_rr_ipin_switch, + e_base_cost_type base_cost_type); std::vector> alloc_and_load_actual_fc(const std::vector& types, const int max_pins, diff --git a/vpr/src/route/rr_graph_generation/rr_graph_area.cpp b/vpr/src/route/rr_graph_generation/rr_graph_area.cpp index 6c8f6b1b9c9..c0952b620cd 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph_area.cpp +++ b/vpr/src/route/rr_graph_generation/rr_graph_area.cpp @@ -24,17 +24,17 @@ static const e_trans_area_eq trans_area_eq = AREA_IMPROVED_NMOS_ONLY; /************************ Subroutines local to this module *******************/ -static void count_bidir_routing_transistors(int num_switch, int wire_to_ipin_switch, float R_minW_nmos, float R_minW_pmos, const float trans_sram_bit); +static void count_bidir_routing_transistors(int num_switch, RRSwitchId wire_to_ipin_switch, float R_minW_nmos, float R_minW_pmos, const float trans_sram_bit); static void count_unidir_routing_transistors(std::vector& segment_inf, - int wire_to_ipin_switch, + RRSwitchId wire_to_ipin_switch, float R_minW_nmos, float R_minW_pmos, const float trans_sram_bit, bool is_flat); static float get_cblock_trans(vtr::vector& num_inputs_to_cblock, - int wire_to_ipin_switch, + RRSwitchId wire_to_ipin_switch, int max_inputs_to_cblock, float trans_sram_bit); @@ -54,7 +54,7 @@ static float trans_per_R(float Rtrans, float R_minW_trans); void count_routing_transistors(enum e_directionality directionality, int num_switch, - int wire_to_ipin_switch, + RRSwitchId wire_to_ipin_switch, std::vector& segment_inf, float R_minW_nmos, float R_minW_pmos, @@ -87,7 +87,7 @@ void count_routing_transistors(enum e_directionality directionality, } } -void count_bidir_routing_transistors(int num_switch, int wire_to_ipin_switch, float R_minW_nmos, float R_minW_pmos, const float trans_sram_bit) { +static void count_bidir_routing_transistors(int num_switch, RRSwitchId wire_to_ipin_switch, float R_minW_nmos, float R_minW_pmos, const float trans_sram_bit) { /* Tri-state buffers are designed as a buffer followed by a pass transistor. * * I make Rbuffer = Rpass_transitor = 1/2 Rtri-state_buffer. * * I make the pull-up and pull-down sides of the buffer the same strength -- * @@ -300,12 +300,12 @@ void count_bidir_routing_transistors(int num_switch, int wire_to_ipin_switch, fl VTR_LOG("\n"); } -void count_unidir_routing_transistors(std::vector& /*segment_inf*/, - int wire_to_ipin_switch, - float R_minW_nmos, - float R_minW_pmos, - const float trans_sram_bit, - bool is_flat) { +static void count_unidir_routing_transistors(std::vector& /*segment_inf*/, + RRSwitchId wire_to_ipin_switch, + float R_minW_nmos, + float R_minW_pmos, + const float trans_sram_bit, + bool is_flat) { auto& device_ctx = g_vpr_ctx.device(); const auto& rr_graph = device_ctx.rr_graph; @@ -484,7 +484,7 @@ void count_unidir_routing_transistors(std::vector& /*segment_inf* } static float get_cblock_trans(vtr::vector& num_inputs_to_cblock, - int wire_to_ipin_switch, + RRSwitchId wire_to_ipin_switch, int max_inputs_to_cblock, float trans_sram_bit) { /* Computes the transistors in the input connection block multiplexers and * @@ -508,8 +508,8 @@ static float get_cblock_trans(vtr::vector& num_inputs_to_cblock, for (int i = 1; i <= max_inputs_to_cblock; i++) { trans_per_cblock[i] = trans_per_mux(i, trans_sram_bit, - rr_graph.rr_switch_inf(RRSwitchId(wire_to_ipin_switch)).mux_trans_size); - trans_per_cblock[i] += rr_graph.rr_switch_inf(RRSwitchId(wire_to_ipin_switch)).buf_size; + rr_graph.rr_switch_inf(wire_to_ipin_switch).mux_trans_size); + trans_per_cblock[i] += rr_graph.rr_switch_inf(wire_to_ipin_switch).buf_size; } trans_count = 0.; diff --git a/vpr/src/route/rr_graph_generation/rr_graph_area.h b/vpr/src/route/rr_graph_generation/rr_graph_area.h index cac5c81794e..014ef247172 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph_area.h +++ b/vpr/src/route/rr_graph_generation/rr_graph_area.h @@ -5,7 +5,7 @@ void count_routing_transistors(enum e_directionality directionality, int num_switch, - int wire_to_ipin_switch, + RRSwitchId wire_to_ipin_switch, std::vector& segment_inf, float R_minW_nmos, float R_minW_pmos, diff --git a/vpr/src/route/rr_graph_generation/tileable_rr_graph/tileable_rr_graph_builder.cpp b/vpr/src/route/rr_graph_generation/tileable_rr_graph/tileable_rr_graph_builder.cpp index 491bd952ae3..29f4c52f62b 100644 --- a/vpr/src/route/rr_graph_generation/tileable_rr_graph/tileable_rr_graph_builder.cpp +++ b/vpr/src/route/rr_graph_generation/tileable_rr_graph/tileable_rr_graph_builder.cpp @@ -80,9 +80,9 @@ void build_tileable_unidir_rr_graph(const std::vector& typ const int& wire_to_arch_ipin_switch, const float R_minW_nmos, const float R_minW_pmos, - const enum e_base_cost_type& base_cost_type, + const e_base_cost_type& base_cost_type, const std::vector& directs, - int* wire_to_rr_ipin_switch, + RRSwitchId* wire_to_rr_ipin_switch, const bool& shrink_boundary, const bool& perimeter_cb, const bool& through_channel, @@ -156,6 +156,7 @@ void build_tileable_unidir_rr_graph(const std::vector& typ t_unified_to_parallel_seg_index segment_index_map; std::vector segment_inf_x = get_parallel_segs(segment_inf, segment_index_map, e_parallel_axis::X_AXIS, true); std::vector segment_inf_y = get_parallel_segs(segment_inf, segment_index_map, e_parallel_axis::Y_AXIS, true); + std::vector segment_inf_z = get_parallel_segs(segment_inf, segment_index_map, e_parallel_axis::Z_AXIS, true); // Get vib grid const auto& vib_grid = device_ctx.vib_grid; @@ -264,7 +265,7 @@ void build_tileable_unidir_rr_graph(const std::vector& typ auto clb_to_clb_directs = alloc_and_load_clb_to_clb_directs(directs, delayless_switch); std::vector clb2clb_directs; for (size_t idirect = 0; idirect < directs.size(); ++idirect) { - /* Sanity checks on rr switch id */ + // Sanity checks on rr switch id VTR_ASSERT(true == device_ctx.rr_graph.valid_switch(RRSwitchId(clb_to_clb_directs[idirect].switch_index))); clb2clb_directs.push_back(clb_to_clb_directs[idirect]); } @@ -290,8 +291,7 @@ void build_tileable_unidir_rr_graph(const std::vector& typ // Allocate external data structures // a. cost_index // b. RC tree - rr_graph_externals(segment_inf, segment_inf_x, segment_inf_y, - *wire_to_rr_ipin_switch, base_cost_type); + rr_graph_externals(segment_inf, segment_inf_x, segment_inf_y, segment_inf_z, *wire_to_rr_ipin_switch, base_cost_type); // Sanitizer for the rr_graph, check connectivities of rr_nodes // Essential check for rr_graph, build look-up and diff --git a/vpr/src/route/rr_graph_generation/tileable_rr_graph/tileable_rr_graph_builder.h b/vpr/src/route/rr_graph_generation/tileable_rr_graph/tileable_rr_graph_builder.h index d8395927de1..1793b1fad18 100644 --- a/vpr/src/route/rr_graph_generation/tileable_rr_graph/tileable_rr_graph_builder.h +++ b/vpr/src/route/rr_graph_generation/tileable_rr_graph/tileable_rr_graph_builder.h @@ -25,9 +25,9 @@ void build_tileable_unidir_rr_graph(const std::vector& typ const int& wire_to_arch_ipin_switch, const float R_minW_nmos, const float R_minW_pmos, - const enum e_base_cost_type& base_cost_type, + const e_base_cost_type& base_cost_type, const std::vector& directs, - int* wire_to_rr_ipin_switch, + RRSwitchId* wire_to_rr_ipin_switch, const bool& shrink_boundary, const bool& perimeter_cb, const bool& through_channel, From cb85f96b6e2a76933b69c97bb93f267bb9479049 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Mon, 15 Sep 2025 13:19:58 -0400 Subject: [PATCH 35/58] counz CHANZ segments in count_rr_segment_types() --- libs/libarchfpga/src/read_xml_arch_file.cpp | 2 +- .../utils/alloc_and_load_rr_indexed_data.cpp | 26 +++++++++++++------ vpr/src/base/vpr_types.h | 4 +-- .../route/rr_graph_generation/rr_graph.cpp | 10 +++---- 4 files changed, 26 insertions(+), 16 deletions(-) diff --git a/libs/libarchfpga/src/read_xml_arch_file.cpp b/libs/libarchfpga/src/read_xml_arch_file.cpp index b2b42dacdbe..9864d76da59 100644 --- a/libs/libarchfpga/src/read_xml_arch_file.cpp +++ b/libs/libarchfpga/src/read_xml_arch_file.cpp @@ -3888,7 +3888,7 @@ static std::vector process_segments(pugi::xml_node Parent, Segs[i].parallel_axis = e_parallel_axis::Y_AXIS; y_axis_seg_found = true; } else if (strcmp(tmp, "z") == 0) { - Segs[i].parallel_axis = e_parallel_axis::Y_AXIS; + Segs[i].parallel_axis = e_parallel_axis::Z_AXIS; z_axis_seg_found = true; } else { archfpga_throw(loc_data.filename_c_str(), loc_data.line(Node), diff --git a/libs/librrgraph/src/utils/alloc_and_load_rr_indexed_data.cpp b/libs/librrgraph/src/utils/alloc_and_load_rr_indexed_data.cpp index 89d44d0878a..2a70e845395 100644 --- a/libs/librrgraph/src/utils/alloc_and_load_rr_indexed_data.cpp +++ b/libs/librrgraph/src/utils/alloc_and_load_rr_indexed_data.cpp @@ -19,7 +19,12 @@ /******************* Subroutines local to this module ************************/ -static void load_rr_indexed_data_base_costs(const RRGraphView& rr_graph, vtr::vector& rr_indexed_data, enum e_base_cost_type base_cost_type, const bool echo_enabled, const char* echo_file_name); +static void load_rr_indexed_data_base_costs(const RRGraphView& rr_graph, + vtr::vector& rr_indexed_data, + e_base_cost_type base_cost_type, + const bool echo_enabled, + const char* echo_file_name); static float get_delay_normalization_fac(const vtr::vector& rr_indexed_data, const bool echo_enabled, const char* echo_file_name); @@ -48,7 +53,8 @@ static void calculate_average_switch(const RRGraphView& rr_graph, static void fixup_rr_indexed_data_T_values(vtr::vector& rr_indexed_data, size_t num_segment); -static std::vector count_rr_segment_types(const RRGraphView& rr_graph, const vtr::vector& rr_indexed_data); +static std::vector count_rr_segment_types(const RRGraphView& rr_graph, + const vtr::vector& rr_indexed_data); static void print_rr_index_info(const vtr::vector& rr_indexed_data, const char* fname, @@ -158,9 +164,9 @@ void alloc_and_load_rr_indexed_data(const RRGraphView& rr_graph, load_rr_indexed_data_base_costs(rr_graph, rr_indexed_data, base_cost_type, echo_enabled, echo_file_name); - if (echo_enabled) { + if (true) { print_rr_index_info(rr_indexed_data, - echo_file_name, + "indexed_data.txt", segment_inf, segment_inf_x.size(), segment_inf_x.size() + segment_inf_y.size()); @@ -341,7 +347,7 @@ std::vector find_ortho_cost_index(const RRGraphView& rr_graph, static void load_rr_indexed_data_base_costs(const RRGraphView& rr_graph, vtr::vector& rr_indexed_data, - enum e_base_cost_type base_cost_type, + e_base_cost_type base_cost_type, const bool echo_enabled, const char* echo_file_name) { // Loads the base_cost member of rr_indexed_data according to the specified base_cost_type. @@ -370,7 +376,7 @@ static void load_rr_indexed_data_base_costs(const RRGraphView& rr_graph, /* Load base costs for CHANX and CHANY segments */ float max_length = 0; - float min_length = 1; + const float min_length = 1; if (base_cost_type == DELAY_NORMALIZED_LENGTH_BOUNDED) { for (size_t index = CHANX_COST_INDEX_START; index < rr_indexed_data.size(); index++) { float length = (1 / rr_indexed_data[RRIndexedDataId(index)].inv_length); @@ -430,11 +436,15 @@ static void load_rr_indexed_data_base_costs(const RRGraphView& rr_graph, } } -static std::vector count_rr_segment_types(const RRGraphView& rr_graph, const vtr::vector& rr_indexed_data) { +static std::vector count_rr_segment_types(const RRGraphView& rr_graph, + const vtr::vector& rr_indexed_data) { std::vector rr_segment_type_counts; for (const RRNodeId id : rr_graph.nodes()) { - if (rr_graph.node_type(id) != e_rr_type::CHANX && rr_graph.node_type(id) != e_rr_type::CHANY) continue; + e_rr_type node_type = rr_graph.node_type(id); + if (!is_chanxy(node_type) && !is_chanz(node_type)) { + continue; + } RRIndexedDataId cost_index = rr_graph.node_cost_index(id); diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index 1d6b30cc455..00ff027512e 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -1299,8 +1299,8 @@ struct t_router_opts { enum e_route_type route_type; int fixed_channel_width; int min_channel_width_hint; /// alloc_and_load_rr_graph(RRGraphBuilder const RRGraphView& rr_graph, const int num_seg_types, const int num_seg_types_x, + const int num_seg_types_y, const t_unified_to_parallel_seg_index& seg_index_map, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, @@ -1321,7 +1322,7 @@ static void build_rr_graph(e_graph_type graph_type, auto update_chan_width = alloc_and_load_rr_graph( device_ctx.rr_graph_builder, device_ctx.rr_graph_builder.rr_nodes(), device_ctx.rr_graph, segment_inf.size(), - segment_inf_x.size(), + segment_inf_x.size(), segment_inf_y.size(), segment_index_map, chan_details_x, chan_details_y, track_to_pin_lookup_x, track_to_pin_lookup_y, @@ -1951,6 +1952,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder const RRGraphView& rr_graph, const int num_seg_types, const int num_seg_types_x, + const int num_seg_types_y, const t_unified_to_parallel_seg_index& seg_index_map, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, @@ -2089,7 +2091,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder // since these die-crossing connections have more delays. if (grid.get_num_layers() > 1) { build_inter_die_3d_rr_chan(rr_graph_builder, i, j, interdie_3d_links[i][j], - CHANX_COST_INDEX_START, chan_width, chan_details_x); + CHANX_COST_INDEX_START + num_seg_types_x + num_seg_types_y, chan_width, chan_details_x); } for (int layer = 0; layer < (int)grid.get_num_layers(); ++layer) { @@ -3176,8 +3178,6 @@ static void build_inter_die_3d_rr_chan(RRGraphBuilder& rr_graph_builder, // 3) xhigh=xlow, yhigh=ylow // 4) directionality: NONE (neither incremental nor decremental in 2D space) - const int start_track = nodes_per_chan.max; - // Go through allocated nodes until no nodes are found within the RRGraph builder for (int track_num = 0; /*no condition*/; track_num++) { // Try to find a node with the current track_num @@ -3199,7 +3199,7 @@ static void build_inter_die_3d_rr_chan(RRGraphBuilder& rr_graph_builder, rr_graph_builder.set_node_coordinates(node, x_coord, y_coord, x_coord, y_coord); // TODO: the index doesn't make any sense. We need to an RRIndexedDataId for CHANZ nodes - rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(const_index_offset + seg_details[start_track - 1].index())); + rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(const_index_offset)); rr_graph_builder.set_node_capacity(node, 1); // GLOBAL routing handled elsewhere float R = 0; float C = 0; From 8866821604029efc983c74cc31f87c7ef95cda20 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Tue, 16 Sep 2025 12:08:30 -0400 Subject: [PATCH 36/58] make e_switch_block_type enum class and move it to switchblock_types.h --- libs/libarchfpga/src/echo_arch.cpp | 8 +++---- libs/libarchfpga/src/physical_types.h | 22 ------------------- .../src/read_fpga_interchange_arch.cpp | 2 +- libs/libarchfpga/src/read_xml_arch_file.cpp | 18 +++++++-------- libs/libarchfpga/src/switchblock_types.h | 22 +++++++++++++++++++ .../route/rr_graph_generation/rr_graph.cpp | 11 ++++------ .../route/rr_graph_generation/rr_graph2.cpp | 10 ++++----- .../rr_graph_generation/rr_graph_sbox.cpp | 8 +++---- .../tileable_rr_graph_gsb.cpp | 6 ++--- 9 files changed, 51 insertions(+), 56 deletions(-) diff --git a/libs/libarchfpga/src/echo_arch.cpp b/libs/libarchfpga/src/echo_arch.cpp index 0878a7adfd0..6f71dbac818 100644 --- a/libs/libarchfpga/src/echo_arch.cpp +++ b/libs/libarchfpga/src/echo_arch.cpp @@ -185,13 +185,13 @@ void PrintArchInfo(FILE* Echo, const t_arch* arch) { } switch (arch->sb_type) { - case (WILTON): + case e_switch_block_type::WILTON: fprintf(Echo, "\tSwitch Block: type wilton fs %d\n", arch->Fs); break; - case (UNIVERSAL): + case (e_switch_block_type::UNIVERSAL): fprintf(Echo, "\tSwitch Block: type universal fs %d\n", arch->Fs); break; - case (SUBSET): + case e_switch_block_type::SUBSET: fprintf(Echo, "\tSwitch Block: type subset fs %d\n", arch->Fs); break; default: @@ -201,7 +201,7 @@ void PrintArchInfo(FILE* Echo, const t_arch* arch) { fprintf(Echo, "\tInput Connect Block Switch Name Within a Same Die: %s\n", arch->ipin_cblock_switch_name[ipin_cblock_switch_index_within_die].c_str()); //if there is more than one layer available, print the connection block switch name that is used for connection between two dice - for (const auto& layout : arch->grid_layouts) { + for (const t_grid_def& layout : arch->grid_layouts) { int num_layers = (int)layout.layers.size(); if (num_layers > 1) { fprintf(Echo, "\tInput Connect Block Switch Name Between Two Dice: %s\n", arch->ipin_cblock_switch_name[ipin_cblock_switch_index_between_dice].c_str()); diff --git a/libs/libarchfpga/src/physical_types.h b/libs/libarchfpga/src/physical_types.h index 7e7c1c3de60..4f1df3fda3b 100644 --- a/libs/libarchfpga/src/physical_types.h +++ b/libs/libarchfpga/src/physical_types.h @@ -1685,28 +1685,6 @@ enum class SegResType { /// String versions of segment resource types constexpr std::array(SegResType::NUM_RES_TYPES)> RES_TYPE_STRING{"GCLK", "GENERAL"}; -/// Defines the type of switch block used in FPGA routing. -enum e_switch_block_type { - /// If the type is SUBSET, I use a Xilinx-like switch block where track i in one channel always - /// connects to track i in other channels. - SUBSET, - - /// If type is WILTON, I use a switch block where track i - /// does not always connect to track i in other channels. - /// See Steve Wilton, PhD Thesis, University of Toronto, 1996. - WILTON, - - /// The UNIVERSAL switch block is from Y. W. Chang et al, TODAES, Jan. 1996, pp. 80 - 101. - UNIVERSAL, - - /// The FULL switch block type allows for complete connectivity between tracks. - FULL, - - /// A CUSTOM switch block has also been added which allows a user to describe custom permutation functions and connection patterns. - /// See comment at top of SRC/route/build_switchblocks.c - CUSTOM -}; - enum e_Fc_type { ABSOLUTE, FRACTIONAL diff --git a/libs/libarchfpga/src/read_fpga_interchange_arch.cpp b/libs/libarchfpga/src/read_fpga_interchange_arch.cpp index d9ad5853570..984dddec11a 100644 --- a/libs/libarchfpga/src/read_fpga_interchange_arch.cpp +++ b/libs/libarchfpga/src/read_fpga_interchange_arch.cpp @@ -2328,7 +2328,7 @@ struct ArchReader { arch_->Chans.chan_y_dist.xpeak = 0; arch_->Chans.chan_y_dist.dc = 0; arch_->ipin_cblock_switch_name.push_back(std::string("generic")); - arch_->sb_type = WILTON; + arch_->sb_type = e_switch_block_type::WILTON; arch_->Fs = 3; default_fc_.specified = true; default_fc_.in_value_type = e_fc_value_type::FRACTIONAL; diff --git a/libs/libarchfpga/src/read_xml_arch_file.cpp b/libs/libarchfpga/src/read_xml_arch_file.cpp index 9864d76da59..4e06f4061da 100644 --- a/libs/libarchfpga/src/read_xml_arch_file.cpp +++ b/libs/libarchfpga/src/read_xml_arch_file.cpp @@ -458,8 +458,8 @@ void xml_read_arch(const char* ArchFile, Next = get_single_child(architecture, "switchlist", loc_data); arch->switches = process_switches(Next, timing_enabled, loc_data); - /* Process switchblocks. This depends on switches */ - bool switchblocklist_required = (arch->sb_type == CUSTOM); //require this section only if custom switchblocks are used + // Process switchblocks. This depends on switches + bool switchblocklist_required = (arch->sb_type == e_switch_block_type::CUSTOM); // require this section only if custom switchblocks are used SWITCHBLOCKLIST_REQD = BoolToReqOpt(switchblocklist_required); /* Process segments. This depends on switches */ @@ -2932,13 +2932,13 @@ static void process_device(pugi::xml_node Node, t_arch* arch, t_default_fc_spec& Prop = get_attribute(Cur, "type", loc_data).value(); // Parse attribute 'type', representing the major connectivity pattern for switch blocks if (strcmp(Prop, "wilton") == 0) { - arch->sb_type = WILTON; + arch->sb_type = e_switch_block_type::WILTON; } else if (strcmp(Prop, "universal") == 0) { - arch->sb_type = UNIVERSAL; + arch->sb_type = e_switch_block_type::UNIVERSAL; } else if (strcmp(Prop, "subset") == 0) { - arch->sb_type = SUBSET; + arch->sb_type = e_switch_block_type::SUBSET; } else if (strcmp(Prop, "custom") == 0) { - arch->sb_type = CUSTOM; + arch->sb_type = e_switch_block_type::CUSTOM; custom_switch_block = true; } else { archfpga_throw(loc_data.filename_c_str(), loc_data.line(Cur), @@ -2971,11 +2971,11 @@ static void process_tileable_device_parameters(t_arch* arch, const pugiutil::loc std::string sub_type_str = get_attribute(cur, "sub_type", loc_data, BoolToReqOpt(false)).as_string(""); if (!sub_type_str.empty()) { if (sub_type_str == "wilton") { - arch->sb_sub_type = WILTON; + arch->sb_sub_type = e_switch_block_type::WILTON; } else if (sub_type_str == "universal") { - arch->sb_sub_type = UNIVERSAL; + arch->sb_sub_type = e_switch_block_type::UNIVERSAL; } else if (sub_type_str == "subset") { - arch->sb_sub_type = SUBSET; + arch->sb_sub_type = e_switch_block_type::SUBSET; } else { archfpga_throw(loc_data.filename_c_str(), loc_data.line(cur), "Unknown property %s for switch block subtype x\n", sub_type_str.c_str()); diff --git a/libs/libarchfpga/src/switchblock_types.h b/libs/libarchfpga/src/switchblock_types.h index cda89219f20..4d8a99d900d 100644 --- a/libs/libarchfpga/src/switchblock_types.h +++ b/libs/libarchfpga/src/switchblock_types.h @@ -15,6 +15,28 @@ enum e_directionality { BI_DIRECTIONAL }; +/// Defines the type of switch block used in FPGA routing. +enum class e_switch_block_type { + /// If the type is SUBSET, I use a Xilinx-like switch block where track i in one channel always + /// connects to track i in other channels. + SUBSET, + + /// If type is WILTON, I use a switch block where track i + /// does not always connect to track i in other channels. + /// See Steve Wilton, PhD Thesis, University of Toronto, 1996. + WILTON, + + /// The UNIVERSAL switch block is from Y. W. Chang et al, TODAES, Jan. 1996, pp. 80 - 101. + UNIVERSAL, + + /// The FULL switch block type allows for complete connectivity between tracks. + FULL, + + /// A CUSTOM switch block has also been added which allows a user to describe custom permutation functions and connection patterns. + /// See comment at top of SRC/route/build_switchblocks.c + CUSTOM +}; + /** * @brief At the intersection of routing channels, left, right, top and bottom specify the x- and y-directed channels * while above and under specify the switch block wires one a layer above or below the current one. above and below diff --git a/vpr/src/route/rr_graph_generation/rr_graph.cpp b/vpr/src/route/rr_graph_generation/rr_graph.cpp index cbfe5147788..6e87b705094 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph.cpp +++ b/vpr/src/route/rr_graph_generation/rr_graph.cpp @@ -917,7 +917,7 @@ std::set get_layers_of_physical_types(const t_physical_tile_type_ptr type) } std::set get_layers_pin_is_connected_to(const t_physical_tile_type_ptr type, int from_layer, int pin_index) { - const auto& device_ctx = g_vpr_ctx.device(); + const DeviceContext& device_ctx = g_vpr_ctx.device(); std::set layer_pin_index_is_connected_to; for (int layer = 0; layer < (int)device_ctx.grid.get_num_layers(); layer++) { if (is_pin_conencted_to_layer(type, pin_index, from_layer, layer, device_ctx.grid.get_num_layers())) { @@ -1191,9 +1191,9 @@ static void build_rr_graph(e_graph_type graph_type, 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); + switch_block_conn = alloc_and_load_switch_block_conn(&nodes_per_chan, e_switch_block_type::SUBSET, /*Fs=*/3); } else { - if (sb_type == CUSTOM) { + if (sb_type == e_switch_block_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, @@ -4029,10 +4029,7 @@ static void build_unidir_rr_opins(RRGraphBuilder& rr_graph_builder, const std::vector& clb_to_clb_directs, const int num_seg_types, int& rr_edge_count) { - /* - * This routine adds the edges from opins to channels at the specified - * grid location (i,j) and grid tile side - */ + // This routine adds the edges from opins to channels at the specified grid location (i,j) and grid tile side *Fc_clipped = false; t_physical_tile_type_ptr type = grid.get_physical_type({i, j, layer}); diff --git a/vpr/src/route/rr_graph_generation/rr_graph2.cpp b/vpr/src/route/rr_graph_generation/rr_graph2.cpp index 544ca0df1d4..bd1c348d3f1 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph2.cpp +++ b/vpr/src/route/rr_graph_generation/rr_graph2.cpp @@ -771,14 +771,12 @@ int get_unidir_opin_connections(RRGraphBuilder& rr_graph_builder, } bool is_cblock(const int chan, const int seg, const int track, const t_chan_seg_details* seg_details) { - int length, ofs, start_seg; + int length = seg_details[track].length(); - length = seg_details[track].length(); - - /* Make sure they gave us correct start */ - start_seg = get_seg_start(seg_details, track, chan, seg); + // Make sure they gave us correct start + int start_seg = get_seg_start(seg_details, track, chan, seg); - ofs = seg - start_seg; + int ofs = seg - start_seg; VTR_ASSERT(ofs >= 0); VTR_ASSERT(ofs < length); diff --git a/vpr/src/route/rr_graph_generation/rr_graph_sbox.cpp b/vpr/src/route/rr_graph_generation/rr_graph_sbox.cpp index 3ddb41e0eda..37a729a0368 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph_sbox.cpp +++ b/vpr/src/route/rr_graph_generation/rr_graph_sbox.cpp @@ -94,13 +94,13 @@ int get_simple_switch_block_track(const enum e_side from_side, int to_track = -1; // Can check to see if it's not set later. - if (switch_block_type == SUBSET) { /* NB: Global routing uses SUBSET too */ + if (switch_block_type == e_switch_block_type::SUBSET) { /* NB: Global routing uses SUBSET too */ to_track = from_track; } /* See S. Wilton Phd thesis, U of T, 1996 p. 103 for details on following. */ - else if (switch_block_type == WILTON) { + else if (switch_block_type == e_switch_block_type::WILTON) { if (from_side == LEFT) { if (to_side == RIGHT) { /* CHANX to CHANX */ to_track = from_track; @@ -147,7 +147,7 @@ int get_simple_switch_block_track(const enum e_side from_side, } } /* End switch_block_type == WILTON case. */ - else if (switch_block_type == UNIVERSAL) { + else if (switch_block_type == e_switch_block_type::UNIVERSAL) { if (from_side == LEFT) { if (to_side == RIGHT) { /* CHANX to CHANX */ to_track = from_track; @@ -191,7 +191,7 @@ int get_simple_switch_block_track(const enum e_side from_side, /* End switch_block_type == UNIVERSAL case. */ /* UDSD Modification by WMF Begin */ - if (switch_block_type == FULL) { /* Just a placeholder. No meaning in reality */ + if (switch_block_type == e_switch_block_type::FULL) { /* Just a placeholder. No meaning in reality */ to_track = from_track; } /* UDSD Modification by WMF End */ diff --git a/vpr/src/route/rr_graph_generation/tileable_rr_graph/tileable_rr_graph_gsb.cpp b/vpr/src/route/rr_graph_generation/tileable_rr_graph/tileable_rr_graph_gsb.cpp index 541a0b76b72..5fbcfbdfaff 100644 --- a/vpr/src/route/rr_graph_generation/tileable_rr_graph/tileable_rr_graph_gsb.cpp +++ b/vpr/src/route/rr_graph_generation/tileable_rr_graph/tileable_rr_graph_gsb.cpp @@ -220,11 +220,11 @@ static std::vector get_switch_block_to_track_id(const e_switch_block_typ size_t actual_from_track = from_track % num_to_tracks; switch (switch_block_type) { - case SUBSET: /* NB: Global routing uses SUBSET too */ + case e_switch_block_type::SUBSET: /* NB: Global routing uses SUBSET too */ to_tracks = get_to_track_list(Fs, actual_from_track, num_to_tracks); /* Finish, we return */ return to_tracks; - case UNIVERSAL: + case e_switch_block_type::UNIVERSAL: if ((from_side == LEFT) || (from_side == RIGHT)) { /* For the prev_side, to_track is from_track @@ -257,7 +257,7 @@ static std::vector get_switch_block_to_track_id(const e_switch_block_typ /* Finish, we return */ return to_tracks; /* End switch_block_type == UNIVERSAL case. */ - case WILTON: + case e_switch_block_type::WILTON: /* See S. Wilton Phd thesis, U of T, 1996 p. 103 for details on following. */ if (from_side == LEFT) { if (to_side == RIGHT) { /* CHANX to CHANX */ From 55e93a39170390a6dd2032fe4678c96cc3e83fb4 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Wed, 17 Sep 2025 12:04:31 -0400 Subject: [PATCH 37/58] update 3d_sb SIV architecture file to add scatter-gather patterns for chanz nodes --- libs/libarchfpga/src/logic_types.h | 1 + libs/libarchfpga/src/read_xml_arch_file.cpp | 2 +- libs/librrgraph/src/base/rr_graph_type.h | 4 ++-- vpr/src/route/rr_graph_generation/rr_graph.cpp | 4 ++-- vpr/src/route/rr_graph_generation/rr_graph.h | 2 +- .../3d_SB_inter_die_stratixiv_arch.timing.xml | 13 ++++++++++--- 6 files changed, 17 insertions(+), 9 deletions(-) diff --git a/libs/libarchfpga/src/logic_types.h b/libs/libarchfpga/src/logic_types.h index 5453d5394c6..55c0ea39f0d 100644 --- a/libs/libarchfpga/src/logic_types.h +++ b/libs/libarchfpga/src/logic_types.h @@ -32,6 +32,7 @@ enum class e_parallel_axis { Y_AXIS, /** BOTH_AXIS: Data that can be applied to both x-directed and y-directed wire segment */ BOTH_AXIS, + /** Z_AXIS: Data that describes an z-directed wire segment (CHANZ) */ Z_AXIS }; diff --git a/libs/libarchfpga/src/read_xml_arch_file.cpp b/libs/libarchfpga/src/read_xml_arch_file.cpp index 4e06f4061da..629446c706f 100644 --- a/libs/libarchfpga/src/read_xml_arch_file.cpp +++ b/libs/libarchfpga/src/read_xml_arch_file.cpp @@ -2070,7 +2070,7 @@ static void process_fc(pugi::xml_node Node, //Apply any matching overrides bool default_overriden = false; - for (const auto& fc_override : fc_overrides) { + for (const t_fc_override& fc_override : fc_overrides) { bool apply_override = false; if (!fc_override.port_name.empty() && !fc_override.seg_name.empty()) { //Both port and seg names are specified require exact match on both diff --git a/libs/librrgraph/src/base/rr_graph_type.h b/libs/librrgraph/src/base/rr_graph_type.h index 4f419d29348..bcdb6c48f54 100644 --- a/libs/librrgraph/src/base/rr_graph_type.h +++ b/libs/librrgraph/src/base/rr_graph_type.h @@ -38,8 +38,8 @@ enum class e_graph_type { * * This map is used to translate indices from the unified segment vector * (`segment_inf` in the device context, which contains all segments regardless of axis) - * to axis-specific segment vectors (`segment_inf_x` or `segment_inf_y`), based on the - * segment's parallel axis. + * to axis-specific segment vectors (`segment_inf_x` or `segment_inf_y` or `segment_inf_z`), + * based on the segment's parallel axis. * * Each entry maps a unified segment index to a pair containing: * - The index in the corresponding axis-specific segment vector diff --git a/vpr/src/route/rr_graph_generation/rr_graph.cpp b/vpr/src/route/rr_graph_generation/rr_graph.cpp index 6e87b705094..ac315b0d4c0 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph.cpp +++ b/vpr/src/route/rr_graph_generation/rr_graph.cpp @@ -1838,7 +1838,7 @@ std::vector> alloc_and_load_actual_fc(const std::vector& sets_per_seg_type, const t_chan_width* nodes_per_chan, const e_fc_type fc_type, - const enum e_directionality directionality, + const e_directionality directionality, bool* Fc_clipped, bool is_flat) { // Initialize Fc of all blocks to zero @@ -4075,7 +4075,7 @@ static void build_unidir_rr_opins(RRGraphBuilder& rr_graph_builder, e_parallel_axis wanted_axis = chan_type == e_rr_type::CHANX ? e_parallel_axis::X_AXIS : e_parallel_axis::Y_AXIS; int seg_index = get_parallel_seg_index(iseg, seg_index_map, wanted_axis); - /*The segment at index iseg doesn't have the proper adjacency so skip building Fc_out conenctions for it*/ + // The segment at index iseg doesn't have the proper adjacency so skip building Fc_out connections for it. if (seg_index < 0) continue; diff --git a/vpr/src/route/rr_graph_generation/rr_graph.h b/vpr/src/route/rr_graph_generation/rr_graph.h index eb6d7204e66..452e058ddb8 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph.h +++ b/vpr/src/route/rr_graph_generation/rr_graph.h @@ -66,7 +66,7 @@ std::vector> alloc_and_load_actual_fc(const std::vector& sets_per_seg_type, const t_chan_width* nodes_per_chan, const e_fc_type fc_type, - const enum e_directionality directionality, + const e_directionality directionality, bool* Fc_clipped, bool is_flat); diff --git a/vtr_flow/arch/multi_die/stratixiv_3d/3d_SB_inter_die_stratixiv_arch.timing.xml b/vtr_flow/arch/multi_die/stratixiv_3d/3d_SB_inter_die_stratixiv_arch.timing.xml index 7a11f92487e..7a3ba51eca8 100644 --- a/vtr_flow/arch/multi_die/stratixiv_3d/3d_SB_inter_die_stratixiv_arch.timing.xml +++ b/vtr_flow/arch/multi_die/stratixiv_3d/3d_SB_inter_die_stratixiv_arch.timing.xml @@ -5072,6 +5072,8 @@ powerful. --> + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + + + @@ -48326,12 +48332,12 @@ - + - + @@ -48342,7 +48348,8 @@ - + + From 50b3569ad7b4e1eb428031129411f7febd991126 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Wed, 17 Sep 2025 12:15:30 -0400 Subject: [PATCH 38/58] remove above and under sides --- libs/libarchfpga/src/parse_switchblocks.cpp | 10 ++------ libs/libarchfpga/src/switchblock_types.h | 14 ++--------- libs/librrgraph/src/base/rr_spatial_lookup.h | 4 ++-- .../utils/alloc_and_load_rr_indexed_data.cpp | 2 +- .../build_switchblocks.cpp | 23 ++++++++----------- 5 files changed, 16 insertions(+), 37 deletions(-) diff --git a/libs/libarchfpga/src/parse_switchblocks.cpp b/libs/libarchfpga/src/parse_switchblocks.cpp index b1006ceb02b..a2636f2af19 100644 --- a/libs/libarchfpga/src/parse_switchblocks.cpp +++ b/libs/libarchfpga/src/parse_switchblocks.cpp @@ -328,7 +328,7 @@ static void parse_comma_separated_wire_points(const char* ch, std::vector CHAR_SIDE_MAP = { @@ -61,18 +58,11 @@ inline const std::unordered_map CHAR_SIDE_MAP = { {'B', BOTTOM}, {'b', BOTTOM}, {'L', LEFT}, - {'l', LEFT}, - {'A', ABOVE}, - {'a', ABOVE}, - {'U', UNDER}, - {'u', UNDER}}; + {'l', LEFT}}; 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 - /** * @brief Specifies what part of the FPGA a custom switchblock should be built in (i.e. perimeter, core, everywhere) * diff --git a/libs/librrgraph/src/base/rr_spatial_lookup.h b/libs/librrgraph/src/base/rr_spatial_lookup.h index 7f9f2414233..4fa2830be51 100644 --- a/libs/librrgraph/src/base/rr_spatial_lookup.h +++ b/libs/librrgraph/src/base/rr_spatial_lookup.h @@ -80,7 +80,7 @@ class RRSpatialLookup { * @param layer specifies which FPGA die the node is located at (e.g. multi-die(3D) FPGA) * @param (xlow, ylow) is the lower left corner of the grid location range to search within the FPGA * @param (xhigh, yhigh) is the top right corner of the grid location range to search within the FPGA - * @param rr_type specifies the type of resource, + * @param type specifies the type of resource, * @param ptc gives a unique number of resources of that type (e.g. CHANX) at that (layer,x,y). * * @return nodes A vector of unique nodes within the given bounds which meet the given parameters @@ -102,7 +102,7 @@ class RRSpatialLookup { * * @param layer specified which FPGA die the node is located at (e.g. multi-die(3D) FPGA) * @param (x, y) is the coordinate of the routing channel within the FPGA - * @param rr_type specifies the type of routing channel, either x-direction or y-direction + * @param type specifies the type of routing channel, either x-direction or y-direction * * @note * - Return an empty list if there are no routing channel at the given (layer,x,y) location diff --git a/libs/librrgraph/src/utils/alloc_and_load_rr_indexed_data.cpp b/libs/librrgraph/src/utils/alloc_and_load_rr_indexed_data.cpp index 2a70e845395..0510cca1177 100644 --- a/libs/librrgraph/src/utils/alloc_and_load_rr_indexed_data.cpp +++ b/libs/librrgraph/src/utils/alloc_and_load_rr_indexed_data.cpp @@ -88,7 +88,7 @@ void alloc_and_load_rr_indexed_data(const RRGraphView& rr_graph, e_base_cost_type base_cost_type, const bool echo_enabled, const char* echo_file_name) { - int total_num_segment = segment_inf_x.size() + segment_inf_y.size() + segment_inf_z.size(); + const size_t total_num_segment = segment_inf_x.size() + segment_inf_y.size() + segment_inf_z.size(); // CHAX & CHANY segment list sizes may differ, but if we're using uniform channels, they will have equal sizes int num_rr_indexed_data = CHANX_COST_INDEX_START + total_num_segment; diff --git a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp index 6496944451c..76d0a8c927f 100644 --- a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp +++ b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp @@ -251,8 +251,8 @@ t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_detail } // 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) { + for (e_side from_side : TOTAL_2D_SIDES) { + for (e_side to_side : TOTAL_2D_SIDES) { // Fill appropriate entry of the sb_conns map with vector specifying the wires the current wire will connect to compute_wire_connections(sb_loc, from_side, to_side, chan_details_x, chan_details_y, sb, @@ -449,18 +449,13 @@ static void compute_wireconn_connections(e_directionality directionality, 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 - 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(from_chan_details[from_loc.x][from_loc.y].data(), from_chan_type, from_loc.x, from_loc.y, from_side, + get_switchpoint_wires(from_chan_details[from_loc.x][from_loc.y].data(), from_chan_type, from_loc.x, from_loc.y, sb_conn.from_side, 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(to_chan_details[to_loc.x][to_loc.y].data(), to_chan_type, to_loc.x, to_loc.y, to_side, + get_switchpoint_wires(to_chan_details[to_loc.x][to_loc.y].data(), to_chan_type, to_loc.x, to_loc.y, sb_conn.to_side, wireconn.to_switchpoint_set, wire_type_sizes_to, /*is_dest=*/true, wireconn.to_switchpoint_order, rng, &scratchpad->potential_dest_wires, &scratchpad->scratch_wires); @@ -536,18 +531,18 @@ static void compute_wireconn_connections(e_directionality directionality, Direction from_wire_direction = from_chan_details[from_loc.x][from_loc.y][from_wire].direction(); if (from_wire_direction == Direction::INC) { - /* if this is a unidirectional wire headed in the increasing direction (relative to coordinate system) - * then switch block source side should be BOTTOM or LEFT */ + // If this is a unidirectional wire headed in the increasing direction (relative to coordinate system) + // then switch block source side should be BOTTOM or LEFT if (sb_conn.from_side == TOP || sb_conn.from_side == RIGHT) { continue; } - VTR_ASSERT(sb_conn.from_side == BOTTOM || sb_conn.from_side == LEFT || sb_conn.from_side == ABOVE || sb_conn.from_side == UNDER); + VTR_ASSERT(sb_conn.from_side == BOTTOM || sb_conn.from_side == LEFT); } else if (from_wire_direction == Direction::DEC) { - /* a wire heading in the decreasing direction can only connect from the TOP or RIGHT sides of a switch block */ + // A wire heading in the decreasing direction can only connect from the TOP or RIGHT sides of a switch block if (sb_conn.from_side == BOTTOM || sb_conn.from_side == LEFT) { continue; } - VTR_ASSERT(sb_conn.from_side == TOP || sb_conn.from_side == RIGHT || sb_conn.from_side == ABOVE || sb_conn.from_side == UNDER); + VTR_ASSERT(sb_conn.from_side == TOP || sb_conn.from_side == RIGHT); } else { VTR_ASSERT(from_wire_direction == Direction::BIDIR); } From c44189f5fb9b8fc0637134b4e3fd8a9721d71c70 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Wed, 17 Sep 2025 12:19:35 -0400 Subject: [PATCH 39/58] remove unused arguments of build_inter_die_3d_rr_chan() --- vpr/src/route/rr_graph_generation/rr_graph.cpp | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/vpr/src/route/rr_graph_generation/rr_graph.cpp b/vpr/src/route/rr_graph_generation/rr_graph.cpp index ac315b0d4c0..29cd632cf22 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph.cpp +++ b/vpr/src/route/rr_graph_generation/rr_graph.cpp @@ -478,20 +478,15 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, /** * @brief builds the extra length-0 CHANX nodes to handle 3D custom switchblocks edges in the RR graph. * @param rr_graph_builder RRGraphBuilder data structure which allows data modification on a routing resource graph - * @param layer switch block layer-coordinate * @param x_coord switch block x_coordinate * @param y_coord switch block y-coordinate * @param const_index_offset index to the correct node type for RR node cost initialization - * @param nodes_per_chan number of tracks per channel (x, y) - * @param chan_details_x channel-x details (length, start and end points, ...) */ static void build_inter_die_3d_rr_chan(RRGraphBuilder& rr_graph_builder, const int x_coord, const int y_coord, const std::vector& interdie_3d_links, - const int const_index_offset, - const t_chan_width& nodes_per_chan, - const t_chan_details& chan_details_x); + const int const_index_offset); static void add_inter_die_3d_edges(RRGraphBuilder& rr_graph_builder, int x_coord, @@ -2091,7 +2086,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder // since these die-crossing connections have more delays. if (grid.get_num_layers() > 1) { build_inter_die_3d_rr_chan(rr_graph_builder, i, j, interdie_3d_links[i][j], - CHANX_COST_INDEX_START + num_seg_types_x + num_seg_types_y, chan_width, chan_details_x); + CHANX_COST_INDEX_START + num_seg_types_x + num_seg_types_y); } for (int layer = 0; layer < (int)grid.get_num_layers(); ++layer) { @@ -3160,11 +3155,8 @@ static void build_inter_die_3d_rr_chan(RRGraphBuilder& rr_graph_builder, const int x_coord, const int y_coord, const std::vector& interdie_3d_links, - const int const_index_offset, - const t_chan_width& nodes_per_chan, - const t_chan_details& chan_details_x) { + const int const_index_offset) { auto& mutable_device_ctx = g_vpr_ctx.mutable_device(); - const t_chan_seg_details* seg_details = chan_details_x[x_coord][y_coord].data(); const size_t num_layers = g_vpr_ctx.device().grid.get_num_layers(); // 3D connections within the switch blocks use some CHANZ nodes to allow a single 3D connection to be driven From 0c4ca72c13553d6c17153a478467c47985655c78 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Wed, 17 Sep 2025 12:24:58 -0400 Subject: [PATCH 40/58] move Fc_xofs to alloc_and_load_rr_graph() --- .../route/rr_graph_generation/rr_graph.cpp | 38 ++++++++----------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/vpr/src/route/rr_graph_generation/rr_graph.cpp b/vpr/src/route/rr_graph_generation/rr_graph.cpp index 29cd632cf22..20b4b9162e2 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph.cpp +++ b/vpr/src/route/rr_graph_generation/rr_graph.cpp @@ -185,9 +185,9 @@ static int get_opin_direct_connections(RRGraphBuilder& rr_graph_builder, static std::function alloc_and_load_rr_graph(RRGraphBuilder& rr_graph_builder, t_rr_graph_storage& L_rr_node, const RRGraphView& rr_graph, - const int num_seg_types, - const int num_seg_types_x, - const int num_seg_types_y, + const size_t num_seg_types, + const size_t num_seg_types_x, + const size_t num_seg_types_y, const t_unified_to_parallel_seg_index& seg_index_map, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, @@ -201,8 +201,6 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder const int Fs, t_sblock_pattern& sblock_pattern, const std::vector>& Fc_out, - vtr::NdMatrix& Fc_xofs, - vtr::NdMatrix& Fc_yofs, const t_chan_width& chan_width, const int wire_to_ipin_switch, const int wire_to_pin_between_dice_switch, @@ -1159,18 +1157,6 @@ static void build_rr_graph(e_graph_type graph_type, } device_ctx.rr_graph_builder.resize_nodes(num_rr_nodes); - // These are data structures used by the unidir opin mapping. They are used - // to spread connections evenly for each segment type among the available - // wire start points - vtr::NdMatrix Fc_xofs({grid.height() - 1, - grid.width() - 1, - segment_inf_x.size()}, - 0); //[0..grid.height()-2][0..grid.width()-2][0..num_seg_types_x-1] - vtr::NdMatrix Fc_yofs({grid.width() - 1, - grid.height() - 1, - segment_inf_y.size()}, - 0); //[0..grid.width()-2][0..grid.height()-2][0..num_seg_types_y-1] - // START SB LOOKUP // Alloc and load the switch block lookup vtr::NdMatrix, 3> switch_block_conn; @@ -1324,7 +1310,7 @@ static void build_rr_graph(e_graph_type graph_type, opin_to_track_map, interdie_3d_links, switch_block_conn, sb_conn_map, grid, Fs, unidir_sb_pattern, - Fc_out, Fc_xofs, Fc_yofs, + Fc_out, nodes_per_chan, wire_to_arch_ipin_switch, wire_to_pin_between_dice_switch, @@ -1945,9 +1931,9 @@ std::vector> alloc_and_load_actual_fc(const std::vector alloc_and_load_rr_graph(RRGraphBuilder& rr_graph_builder, t_rr_graph_storage& L_rr_node, const RRGraphView& rr_graph, - const int num_seg_types, - const int num_seg_types_x, - const int num_seg_types_y, + const size_t num_seg_types, + const size_t num_seg_types_x, + const size_t num_seg_types_y, const t_unified_to_parallel_seg_index& seg_index_map, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, @@ -1961,8 +1947,6 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder const int Fs, t_sblock_pattern& sblock_pattern, const std::vector>& Fc_out, - vtr::NdMatrix& Fc_xofs, - vtr::NdMatrix& Fc_yofs, const t_chan_width& chan_width, const int wire_to_ipin_switch, const int wire_to_pin_between_dice_switch, @@ -2034,6 +2018,14 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder VTR_LOGV(route_verbosity > 1, "SOURCE->OPIN and IPIN->SINK edge count:%d\n", num_edges); num_edges = 0; + + // These are data structures used by the unidir opin mapping. They are used + // to spread connections evenly for each segment type among the available + // wire start points + // [0..grid.height()-2][0..grid.width()-2][0..num_seg_types_x/y-1] + vtr::NdMatrix Fc_xofs({grid.height() - 1, grid.width() - 1, num_seg_types_x}, 0); + vtr::NdMatrix Fc_yofs({grid.width() - 1, grid.height() - 1, num_seg_types_y}, 0); + // Build opins int rr_edges_before_directs = 0; for (size_t layer = 0; layer < grid.get_num_layers(); layer++) { From b118f0149352f5b6d5e6c6baf02cb1b134857bef Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Wed, 17 Sep 2025 12:38:53 -0400 Subject: [PATCH 41/58] use std::string_view instead of chan* and converting it to string --- libs/libarchfpga/src/parse_switchblocks.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/libs/libarchfpga/src/parse_switchblocks.cpp b/libs/libarchfpga/src/parse_switchblocks.cpp index a2636f2af19..64635723f36 100644 --- a/libs/libarchfpga/src/parse_switchblocks.cpp +++ b/libs/libarchfpga/src/parse_switchblocks.cpp @@ -35,7 +35,7 @@ using vtr::t_formula_data; /*---- Functions for Parsing Switchblocks from Architecture ----*/ //Process the desired order of a wireconn -static void parse_switchpoint_order(const char* order, e_switch_point_order& switchpoint_order); +static void parse_switchpoint_order(std::string_view order, e_switch_point_order& switchpoint_order); /** * @brief Parses an inline `` node using its attributes. @@ -86,7 +86,7 @@ static void parse_comma_separated_wire_points(const char* ch, std::vector& switches); @@ -282,12 +282,12 @@ static t_wire_switchpoints parse_wireconn_from_to_node(pugi::xml_node node, cons return wire_switchpoints; } -static void parse_switchpoint_order(const char* order, e_switch_point_order& switchpoint_order) { - if (order == std::string("")) { +static void parse_switchpoint_order(std::string_view order, e_switch_point_order& switchpoint_order) { + if (order == "") { switchpoint_order = e_switch_point_order::SHUFFLED; //Default - } else if (order == std::string("fixed")) { + } else if (order == "fixed") { switchpoint_order = e_switch_point_order::FIXED; - } else if (order == std::string("shuffled")) { + } else if (order == "shuffled") { switchpoint_order = e_switch_point_order::SHUFFLED; } else { archfpga_throw(__FILE__, __LINE__, "Unrecognized switchpoint order '%s'", order); @@ -332,15 +332,14 @@ static void parse_num_conns(std::string num_conns, t_wireconn_inf& wireconn) { wireconn.num_conns_formula = num_conns; } -//set sides for a specific conn for custom switch block pattern -static void set_switch_func_type(SBSideConnection& conn, const char* func_type) { +static void set_switch_func_type(SBSideConnection& conn, std::string_view func_type) { - if (std::string(func_type).length() != 2) { + if (func_type.length() != 2) { archfpga_throw(__FILE__, __LINE__, "Custom switchblock func type must be 2 characters long: %s\n", func_type); } // Only valid sides are right, top, left, bottom, above and under - if (std::string(func_type).find_first_not_of("rtlbRTLB") != std::string::npos) { + if (func_type.find_first_not_of("rtlbRTLB") != std::string::npos) { archfpga_throw(__FILE__, __LINE__, "Unknown direction specified: %s\n", func_type); } From 417f6a96513c65a22289d513ed3f565c0c7e9c21 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Wed, 17 Sep 2025 15:52:32 -0400 Subject: [PATCH 42/58] doxygen comments in build_scatter_gather.h and utils.h --- libs/librrgraph/src/base/rr_graph_builder.h | 3 +- libs/librrgraph/src/base/rr_graph_storage.h | 34 +++++----------- libs/librrgraph/src/base/rr_node.cpp | 2 +- .../build_scatter_gathers.h | 40 ++++++++++++++----- .../build_switchblocks.cpp | 1 - ...witchblock_scatter_gather_common_utils.cpp | 12 ++++++ .../switchblock_scatter_gather_common_utils.h | 6 +++ 7 files changed, 62 insertions(+), 36 deletions(-) diff --git a/libs/librrgraph/src/base/rr_graph_builder.h b/libs/librrgraph/src/base/rr_graph_builder.h index 34417b03120..5e386f19039 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.h +++ b/libs/librrgraph/src/base/rr_graph_builder.h @@ -238,11 +238,12 @@ class RRGraphBuilder { node_storage_.set_node_ptc_num(id, new_ptc_num); } - /** @brief set the layer number at which RRNodeId is located at */ + /// @brief Set the low layer coordinate where the given node is located at. inline void set_node_layer_low(RRNodeId id, int layer){ node_storage_.set_node_layer_low(id, layer); } + /// @brief Set the high layer coordinate where the given node is located at. inline void set_node_layer_high(RRNodeId id, int layer){ node_storage_.set_node_layer_high(id, layer); } diff --git a/libs/librrgraph/src/base/rr_graph_storage.h b/libs/librrgraph/src/base/rr_graph_storage.h index 08dd7f18608..1b427809740 100644 --- a/libs/librrgraph/src/base/rr_graph_storage.h +++ b/libs/librrgraph/src/base/rr_graph_storage.h @@ -241,17 +241,12 @@ class t_rr_graph_storage { return node_fan_in_[id]; } - /** @brief Find the layer number that RRNodeId is located at. - * It is zero if the FPGA only has one die. - * The layer number start from the base die (base die: 0, the die above it: 1, etc.) - */ - // short node_layer(RRNodeId id) const{ - // return node_layer_[id]; - // } + /// @brief Returns the lowest layer where the given node is located at. short node_layer_low(RRNodeId id) const { return node_layer_low_[id]; } + /// @brief Returns the highest layer where the given node is located at. short node_layer_high(RRNodeId id) const { return node_layer_high_[id]; } @@ -915,13 +910,14 @@ class t_rr_graph_storage { /** @brief Fan in counts for each RR node. */ vtr::vector node_fan_in_; - /** @brief - * Layer number that each RR node is located at - * Layer number refers to the die that the node belongs to. The layer number of base die is zero and die above it one, etc. - * This data is also considered as a hot data since it is used in inner loop of router, but since it didn't fit nicely into t_rr_node_data due to alignment issues, we had to store it - * in a separate vector. - */ + // Layer number refers to the die that the node belongs to. + // The layer number of base die is zero and die above it one, etc. + // This data is also considered as a hot data since it is used in inner loop of router, + // but since it didn't fit nicely into t_rr_node_data due to alignment issues, we had to store it in a separate vector. + + /// @brief The lowest layer number where a given node is located at. vtr::vector node_layer_low_; + /// @brief The highest layer number where a given node is located at. vtr::vector node_layer_high_; /** @@ -1107,20 +1103,12 @@ class t_rr_graph_view { return node_fan_in_[id]; } - /** - * @brief Retrieve the layer (die) number where the given RRNodeId is located. - * - * @param id The RRNodeId for which to retrieve the layer number. - * @return The layer number (die) where the RRNodeId is located. - */ - // short node_layer(RRNodeId id) const { - // return node_layer_[id]; - // } - + /// @brief Retrieve the lowest layer (die) number where the given RRNodeId is located. short node_layer_low(RRNodeId id) const { return node_layer_low_[id]; } + /// @brief Retrieve the highest layer (die) number where the given RRNodeId is located. short node_layer_high(RRNodeId id) const { return node_layer_high_[id]; } diff --git a/libs/librrgraph/src/base/rr_node.cpp b/libs/librrgraph/src/base/rr_node.cpp index c9abe98dabe..629647dfe2e 100644 --- a/libs/librrgraph/src/base/rr_node.cpp +++ b/libs/librrgraph/src/base/rr_node.cpp @@ -1,7 +1,7 @@ #include "rr_node.h" #include "rr_graph_storage.h" -//Returns the max 'length' over the x or y direction +//Returns the max 'length' over the x or y or z direction short t_rr_node::length() const { return std::max({storage_->node_yhigh(id_) - storage_->node_ylow(id_), storage_->node_xhigh(id_) - storage_->node_xlow(id_), diff --git a/vpr/src/route/rr_graph_generation/build_scatter_gathers.h b/vpr/src/route/rr_graph_generation/build_scatter_gathers.h index 33f3faa3482..34ff04d8507 100644 --- a/vpr/src/route/rr_graph_generation/build_scatter_gathers.h +++ b/vpr/src/route/rr_graph_generation/build_scatter_gathers.h @@ -7,25 +7,45 @@ #include +/// Identifies a specific channel location in the device grid. struct t_chan_loc { - t_physical_tile_loc location; - e_rr_type chan_type; - e_side side; + t_physical_tile_loc location; ///< Physical grid location of the channel + e_rr_type chan_type; ///< Type of routing channel (e.g., CHANX, CHANY) + e_side side; ///< Side of the reference switch block the channel lies on }; +/// Represents a wire candidate for scatter/gather connections. struct t_sg_candidate { - t_chan_loc chan_loc; - t_wire_switchpoint wire_switchpoint; + t_chan_loc chan_loc; ///< Channel location (coordinates, type, side) where the wire lies. + t_wire_switchpoint wire_switchpoint; ///< Wire index and its valid switchpoint }; +/// Represents a scatter/gather bottleneck connection between two locations. struct t_bottleneck_link { - t_physical_tile_loc gather_loc; - t_physical_tile_loc scatter_loc; - int arch_wire_switch; - std::vector gather_fanin_connections; - std::vector scatter_fanout_connections; + t_physical_tile_loc gather_loc; ///< Source switchblock location. + t_physical_tile_loc scatter_loc; ///< Destination switchblock location. + int arch_wire_switch; ///< The switch (mux) used to drive the bottleneck wire. + std::vector gather_fanin_connections; ///< Wires driving the bottleneck link at `gather_loc` + std::vector scatter_fanout_connections; ///< Wires driven by the bottleneck link at `scatter_loc` }; +/** + * @brief Builds scatter/gather bottleneck connections across the device grid. + * + * For each scatter/gather pattern, this routine finds candidate gather and scatter + * wires, evaluates connection limits from user-specified formulas, and creates + * bottleneck links between the corresponding locations. Both intra-die and inter-die + * (3D) connections are handled. + * + * @param scatter_gather_patterns List of scatter/gather connection patterns. + * @param inter_cluster_rr Flags indicating whether each layer has inter-cluster routing resources. + * @param segment_inf Wire segment type information. + * @param chan_details_x Channel details for horizontal routing channels. + * @param chan_details_y Channel details for vertical routing channels. + * @param nodes_per_chan Channel width data. + * @param interdie_3d_links Output: matrix storing inter-die (3D) bottleneck links. + * @return Vector of intra-die bottleneck links. + */ std::vector alloc_and_load_scatter_gather_connections(const std::vector& scatter_gather_patterns, const std::vector& inter_cluster_rr, const std::vector& segment_inf, diff --git a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp index 76d0a8c927f..ef4c78316ad 100644 --- a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp +++ b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp @@ -152,7 +152,6 @@ struct t_wireconn_scratchpad { std::vector scratch_wires; }; - /************ Function Declarations ************/ /* Compute the wire(s) that the wire at (x, y, from_side, to_side, from_wire) should connect to. diff --git a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp index 6f43a2392e4..69bd2006c20 100644 --- a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp +++ b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp @@ -7,6 +7,10 @@ #include "rr_types.h" #include "vtr_expr_eval.h" +// +// Static Function Declarations +// + /** * Returns wire segment length based on either: * 1) the wire length specified in the segment details variable for this wire (if this wire segment doesn't span entire FPGA) @@ -88,6 +92,10 @@ static bool is_core_sb(const DeviceGrid& grid, const t_physical_tile_loc& loc) { return is_core; } +// +// Static Function Definitions +// + static bool match_sb_xy(const DeviceGrid& grid, const t_physical_tile_loc& loc, const t_specified_loc& specified_loc) { @@ -243,6 +251,10 @@ static int get_wire_segment_length(e_rr_type chan_type, return wire_length; } +// +// Non-static Function Definitions +// + bool sb_not_here(const DeviceGrid& grid, const std::vector& inter_cluster_rr, const t_physical_tile_loc& loc, diff --git a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h index e8c9e654724..ecd05d18c89 100644 --- a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h +++ b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h @@ -96,6 +96,12 @@ int get_switchpoint_of_wire(e_rr_type chan_type, int seg_coord, e_side sb_side); +/** +* @brief Evaluates a connection formula for scatter/gather and custom switchblock patterns. +* +* Sets variables "from" and "to" to the given wire counts and evaluates +* the formula string using the provided parser +*/ int evaluate_num_conns_formula(vtr::FormulaParser& formula_parser, vtr::t_formula_data& formula_data, const std::string& num_conns_formula, From b79487294f78fe0b3261bdcc68d70531e6d8a3b2 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Wed, 17 Sep 2025 16:04:56 -0400 Subject: [PATCH 43/58] doxygen comments for static functions in build_scatter_gather.cpp --- .../build_scatter_gathers.cpp | 63 ++++++++++++++++--- 1 file changed, 54 insertions(+), 9 deletions(-) diff --git a/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp b/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp index 85e6b037291..bdb6eadd375 100644 --- a/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp +++ b/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp @@ -9,6 +9,49 @@ #include +// +// Static Function Declrations +// + +/** + * @brief Finds the routing channels corresponding to a given scatter or gather pattern and location. + * + * @param pattern Scatter/gather (SG) pattern to be processed. + * @param loc Physical switchblock location where the SG pattern is to be applied. + * @param chan_details_x Channel details for horizontal routing channels. + * @param chan_details_y Channel details for vertical routing channels. + * @param correct_channels Output: list of valid channel locations and types. + */ +static void index_to_correct_channels(const t_wireconn_inf& pattern, + const t_physical_tile_loc& loc, + const t_chan_details& chan_details_x, + const t_chan_details& chan_details_y, + std::vector& correct_channels); + +/** + * @brief Collects candidate wires from given channels that match specified switchpoints. + * + * @param channels List of channel locations to search for candiates. + * @param wire_switchpoints_vec Set of wire segments and valid switchpoints for matching. + * @param chan_details_x Channel details for horizontal routing channels. + * @param chan_details_y Channel details for vertical routing channels. + * @param is_dest True if searching for destination (scatter) wires, false for source (gather). + * @param wire_type_sizes_x Stores the number of wires of each wire segment type and their starting index for horizontal routing channels. + * @param wire_type_sizes_y Stores the number of wires of each wire segment type and their starting index for vertical routing channels. + * @return Vector of candidate wires that satisfy the switchpoint and direction constraints. + */ +static std::vector find_candidate_wires(const std::vector& channels, + const std::vector& wire_switchpoints_vec, + const t_chan_details& chan_details_x, + const t_chan_details& chan_details_y, + const t_wire_type_sizes& wire_type_sizes_x, + const t_wire_type_sizes& wire_type_sizes_y, + bool is_dest) ; + +// +// Static Function Definitions +// + static void index_to_correct_channels(const t_wireconn_inf& pattern, const t_physical_tile_loc& loc, const t_chan_details& chan_details_x, @@ -28,15 +71,13 @@ static void index_to_correct_channels(const t_wireconn_inf& pattern, } } -static -std::vector - find_candidate_wires(const std::vector& channels, - const std::vector& wire_switchpoints_vec, - const t_chan_details& chan_details_x, - const t_chan_details& chan_details_y, - const t_wire_type_sizes& wire_type_sizes_x, - const t_wire_type_sizes& wire_type_sizes_y, - bool is_dest) { +static std::vector find_candidate_wires(const std::vector& channels, + const std::vector& wire_switchpoints_vec, + const t_chan_details& chan_details_x, + const t_chan_details& chan_details_y, + const t_wire_type_sizes& wire_type_sizes_x, + const t_wire_type_sizes& wire_type_sizes_y, + bool is_dest) { // TODO: reuse std::vector candidates; @@ -100,6 +141,10 @@ std::vector return candidates; } +// +// Non-satatic Function Definitions +// + std::vector alloc_and_load_scatter_gather_connections(const std::vector& scatter_gather_patterns, const std::vector& inter_cluster_rr, const std::vector& segment_inf, From 019a8e5d14fc9dc26aafb496446dff756c441cec Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Wed, 17 Sep 2025 16:08:16 -0400 Subject: [PATCH 44/58] make format --- libs/libarchfpga/src/switchblock_types.h | 8 ++--- vpr/src/route/overuse_report.cpp | 4 +-- .../router_lookahead_extended_map.cpp | 4 +-- .../router_lookahead/router_lookahead_map.cpp | 36 ++++++++++++++----- .../router_lookahead/router_lookahead_map.h | 2 -- .../router_lookahead_map_utils.cpp | 2 +- .../build_scatter_gathers.cpp | 30 +++++++--------- .../build_scatter_gathers.h | 12 +++---- .../build_switchblocks.cpp | 3 +- .../route/rr_graph_generation/rr_graph.cpp | 6 +--- ...witchblock_scatter_gather_common_utils.cpp | 9 +++-- .../switchblock_scatter_gather_common_utils.h | 13 ++++--- vpr/src/util/vpr_utils.cpp | 12 +++---- 13 files changed, 73 insertions(+), 68 deletions(-) diff --git a/libs/libarchfpga/src/switchblock_types.h b/libs/libarchfpga/src/switchblock_types.h index 1a89e621c8b..dd58fda25fe 100644 --- a/libs/libarchfpga/src/switchblock_types.h +++ b/libs/libarchfpga/src/switchblock_types.h @@ -152,12 +152,12 @@ struct t_wire_switchpoints { * */ 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) + 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) e_switch_point_order from_switchpoint_order = e_switch_point_order::FIXED; ///< The desired from_switchpoint_set ordering e_switch_point_order to_switchpoint_order = e_switch_point_order::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) + 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. * diff --git a/vpr/src/route/overuse_report.cpp b/vpr/src/route/overuse_report.cpp index bd958ff79af..bdf470fa36b 100644 --- a/vpr/src/route/overuse_report.cpp +++ b/vpr/src/route/overuse_report.cpp @@ -155,7 +155,7 @@ void report_overused_nodes(const Netlist<>& net_list, report_sinks = true; break; - // TODO: handle CHANZ nodes + // TODO: handle CHANZ nodes default: break; @@ -248,7 +248,7 @@ static void report_overused_ipin_opin(std::ostream& os, os << "On Tile Pin" << "\n"; } else { - const char* pb_type_name = get_pb_graph_node_from_pin_physical_num(physical_type, rr_graph.node_ptc_num(node_id)) ->pb_type->name; + const char* pb_type_name = get_pb_graph_node_from_pin_physical_num(physical_type, rr_graph.node_ptc_num(node_id))->pb_type->name; const t_pb_graph_pin* pb_pin = get_pb_pin_from_pin_physical_num(physical_type, rr_graph.node_ptc_num(node_id)); os << "Intra-Tile Pin - Port : " << pb_pin->port->name << " - PB Type : " << std::string(pb_type_name) << "\n"; } diff --git a/vpr/src/route/router_lookahead/router_lookahead_extended_map.cpp b/vpr/src/route/router_lookahead/router_lookahead_extended_map.cpp index 270e950f1fc..02d4e4cc931 100644 --- a/vpr/src/route/router_lookahead/router_lookahead_extended_map.cpp +++ b/vpr/src/route/router_lookahead/router_lookahead_extended_map.cpp @@ -153,8 +153,8 @@ float ExtendedMapLookahead::get_chan_ipin_delays(RRNodeId to_node) const { VTR_ASSERT(to_type == e_rr_type::SINK || to_type == e_rr_type::IPIN); t_physical_tile_type_ptr to_tile_type = device_ctx.grid.get_physical_type({rr_graph.node_xlow(to_node), - rr_graph.node_ylow(to_node), - rr_graph.node_layer_low(to_node)}); + rr_graph.node_ylow(to_node), + rr_graph.node_layer_low(to_node)}); int to_tile_index = to_tile_type->index; int to_ptc = rr_graph.node_ptc_num(to_node); diff --git a/vpr/src/route/router_lookahead/router_lookahead_map.cpp b/vpr/src/route/router_lookahead/router_lookahead_map.cpp index 47342ff91d4..6bb3d36184f 100644 --- a/vpr/src/route/router_lookahead/router_lookahead_map.cpp +++ b/vpr/src/route/router_lookahead/router_lookahead_map.cpp @@ -505,9 +505,15 @@ static util::Cost_Entry get_wire_cost_entry(e_rr_type rr_type, int seg_index, in int chan_index; switch (rr_type) { - case e_rr_type::CHANX: chan_index = 0; break; - case e_rr_type::CHANY: chan_index = 1; break; - case e_rr_type::CHANZ: chan_index = 2; break; + case e_rr_type::CHANX: + chan_index = 0; + break; + case e_rr_type::CHANY: + chan_index = 1; + break; + case e_rr_type::CHANZ: + chan_index = 2; + break; default: VTR_ASSERT(false); } @@ -584,9 +590,15 @@ static void set_lookahead_map_costs(unsigned from_layer_num, util::t_routing_cost_map& routing_cost_map) { int chan_index; switch (chan_type) { - case e_rr_type::CHANX: chan_index = 0; break; - case e_rr_type::CHANY: chan_index = 1; break; - case e_rr_type::CHANZ: chan_index = 2; break; + case e_rr_type::CHANX: + chan_index = 0; + break; + case e_rr_type::CHANY: + chan_index = 1; + break; + case e_rr_type::CHANZ: + chan_index = 2; + break; default: VTR_ASSERT(false); } @@ -608,9 +620,15 @@ static void fill_in_missing_lookahead_entries(int segment_index, e_rr_type chan_ int chan_index; switch (chan_type) { - case e_rr_type::CHANX: chan_index = 0; break; - case e_rr_type::CHANY: chan_index = 1; break; - case e_rr_type::CHANZ: chan_index = 2; break; + case e_rr_type::CHANX: + chan_index = 0; + break; + case e_rr_type::CHANY: + chan_index = 1; + break; + case e_rr_type::CHANZ: + chan_index = 2; + break; default: VTR_ASSERT(false); } diff --git a/vpr/src/route/router_lookahead/router_lookahead_map.h b/vpr/src/route/router_lookahead/router_lookahead_map.h index dd2b980ba99..8f79abfe13b 100644 --- a/vpr/src/route/router_lookahead/router_lookahead_map.h +++ b/vpr/src/route/router_lookahead/router_lookahead_map.h @@ -63,7 +63,5 @@ class MapLookahead : public RouterLookahead { */ typedef vtr::NdMatrix t_wire_cost_map; - - void read_router_lookahead(const std::string& file); void write_router_lookahead(const std::string& file); diff --git a/vpr/src/route/router_lookahead/router_lookahead_map_utils.cpp b/vpr/src/route/router_lookahead/router_lookahead_map_utils.cpp index 3dbf1c5bd00..f476f2bb0cf 100644 --- a/vpr/src/route/router_lookahead/router_lookahead_map_utils.cpp +++ b/vpr/src/route/router_lookahead/router_lookahead_map_utils.cpp @@ -936,7 +936,7 @@ void dump_readable_router_lookahead_map(const std::string& file_name, const std: "delay_cost\n"; std::vector chan_types{e_rr_type::CHANX, e_rr_type::CHANY}; - if (num_layers > 1) { + if (num_layers > 1) { chan_types.push_back(e_rr_type::CHANZ); } diff --git a/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp b/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp index bdb6eadd375..62c64d11d61 100644 --- a/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp +++ b/vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp @@ -46,7 +46,7 @@ static std::vector find_candidate_wires(const std::vector find_candidate_wires(const std::vector alloc_and_load_scatter_gather_connections(const s VTR_ASSERT(sg_link_it != sg_pattern.sg_links.end()); const t_sg_link& sg_link = *sg_link_it; - auto seg_it = std::ranges::find_if(segment_inf, - [&](const t_segment_inf& seg) noexcept { - return seg.name == sg_link.seg_type; - }); + [&](const t_segment_inf& seg) noexcept { + return seg.name == sg_link.seg_type; + }); VTR_ASSERT(seg_it != segment_inf.end()); const t_segment_inf& wire_segment = *seg_it; @@ -209,16 +207,16 @@ std::vector alloc_and_load_scatter_gather_connections(const s } auto gather_wire_candidates = find_candidate_wires(gather_channels, - sg_pattern.gather_pattern.from_switchpoint_set, - chan_details_x, chan_details_y, - wire_type_sizes_x, wire_type_sizes_y, - /*is_dest=*/false); + sg_pattern.gather_pattern.from_switchpoint_set, + chan_details_x, chan_details_y, + wire_type_sizes_x, wire_type_sizes_y, + /*is_dest=*/false); auto scatter_wire_candidates = find_candidate_wires(scatter_channels, - sg_pattern.scatter_pattern.to_switchpoint_set, - chan_details_x, chan_details_y, - wire_type_sizes_x, wire_type_sizes_y, - /*is_dest=*/true); + sg_pattern.scatter_pattern.to_switchpoint_set, + chan_details_x, chan_details_y, + wire_type_sizes_x, wire_type_sizes_y, + /*is_dest=*/true); int bottleneck_fanin = evaluate_num_conns_formula(formula_parser, formula_data, @@ -279,9 +277,7 @@ std::vector alloc_and_load_scatter_gather_connections(const s } bottleneck_links.push_back(std::move(bottleneck_link)); } - } - } } } diff --git a/vpr/src/route/rr_graph_generation/build_scatter_gathers.h b/vpr/src/route/rr_graph_generation/build_scatter_gathers.h index 34ff04d8507..df5a569abb3 100644 --- a/vpr/src/route/rr_graph_generation/build_scatter_gathers.h +++ b/vpr/src/route/rr_graph_generation/build_scatter_gathers.h @@ -9,15 +9,15 @@ /// Identifies a specific channel location in the device grid. struct t_chan_loc { - t_physical_tile_loc location; ///< Physical grid location of the channel - e_rr_type chan_type; ///< Type of routing channel (e.g., CHANX, CHANY) - e_side side; ///< Side of the reference switch block the channel lies on + t_physical_tile_loc location; ///< Physical grid location of the channel + e_rr_type chan_type; ///< Type of routing channel (e.g., CHANX, CHANY) + e_side side; ///< Side of the reference switch block the channel lies on }; /// Represents a wire candidate for scatter/gather connections. struct t_sg_candidate { - t_chan_loc chan_loc; ///< Channel location (coordinates, type, side) where the wire lies. - t_wire_switchpoint wire_switchpoint; ///< Wire index and its valid switchpoint + t_chan_loc chan_loc; ///< Channel location (coordinates, type, side) where the wire lies. + t_wire_switchpoint wire_switchpoint; ///< Wire index and its valid switchpoint }; /// Represents a scatter/gather bottleneck connection between two locations. @@ -52,4 +52,4 @@ std::vector alloc_and_load_scatter_gather_connections(const s const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, const t_chan_width& nodes_per_chan, - vtr::NdMatrix, 2>& interdie_3d_links); \ No newline at end of file + vtr::NdMatrix, 2>& interdie_3d_links); diff --git a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp index ef4c78316ad..0064787e456 100644 --- a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp +++ b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp @@ -379,7 +379,6 @@ static void compute_wire_connections(const t_physical_tile_loc& sb_loc, e_rr_type from_chan_type, to_chan_type; // the type of channel - i.e. CHANX or CHANY t_physical_tile_loc from_loc, to_loc; - // For indexing into this switchblock's permutation funcs SBSideConnection side_conn(from_side, to_side); // For indexing into FPGA's switchblock map @@ -454,7 +453,7 @@ static void compute_wireconn_connections(e_directionality directionality, &scratchpad->potential_src_wires, &scratchpad->scratch_wires); - get_switchpoint_wires(to_chan_details[to_loc.x][to_loc.y].data(), to_chan_type, to_loc.x, to_loc.y, sb_conn.to_side, + get_switchpoint_wires(to_chan_details[to_loc.x][to_loc.y].data(), to_chan_type, to_loc.x, to_loc.y, sb_conn.to_side, wireconn.to_switchpoint_set, wire_type_sizes_to, /*is_dest=*/true, wireconn.to_switchpoint_order, rng, &scratchpad->potential_dest_wires, &scratchpad->scratch_wires); diff --git a/vpr/src/route/rr_graph_generation/rr_graph.cpp b/vpr/src/route/rr_graph_generation/rr_graph.cpp index 20b4b9162e2..cdf038804a5 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph.cpp +++ b/vpr/src/route/rr_graph_generation/rr_graph.cpp @@ -2078,7 +2078,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder // since these die-crossing connections have more delays. if (grid.get_num_layers() > 1) { build_inter_die_3d_rr_chan(rr_graph_builder, i, j, interdie_3d_links[i][j], - CHANX_COST_INDEX_START + num_seg_types_x + num_seg_types_y); + CHANX_COST_INDEX_START + num_seg_types_x + num_seg_types_y); } for (int layer = 0; layer < (int)grid.get_num_layers(); ++layer) { @@ -2137,12 +2137,9 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder num_edges += interdie_3d_rr_edges_to_create.size(); interdie_3d_rr_edges_to_create.clear(); } - } } - - VTR_LOGV(route_verbosity > 1, "CHAN->CHAN type edge count:%d\n", num_edges); num_edges = 0; @@ -3197,7 +3194,6 @@ static void build_inter_die_3d_rr_chan(RRGraphBuilder& rr_graph_builder, VTR_ASSERT_SAFE(interdie_3d_links[track_num].scatter_loc.layer_num < interdie_3d_links[track_num].gather_loc.layer_num); rr_graph_builder.set_node_direction(node, Direction::DEC); } - } } diff --git a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp index 69bd2006c20..3a244d9baf6 100644 --- a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp +++ b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.cpp @@ -68,14 +68,13 @@ static bool is_core_sb(const DeviceGrid& grid, const t_physical_tile_loc& loc); */ static bool match_sb_xy(const DeviceGrid& grid, const t_physical_tile_loc& loc, const t_specified_loc& sb); - static bool is_corner_sb(const DeviceGrid& grid, const t_physical_tile_loc& loc) { bool is_corner = false; if ((loc.x == 0 && loc.y == 0) || (loc.x == 0 && loc.y == int(grid.height()) - 2) || //-2 for no perim channels (loc.x == int(grid.width()) - 2 && loc.y == 0) || //-2 for no perim channels (loc.x == int(grid.width()) - 2 && loc.y == int(grid.height()) - 2)) { //-2 for no perim channels - is_corner = true; - } + is_corner = true; + } return is_corner; } @@ -259,7 +258,7 @@ bool sb_not_here(const DeviceGrid& grid, const std::vector& inter_cluster_rr, const t_physical_tile_loc& loc, e_sb_location sb_location, - const t_specified_loc& specified_loc/*=t_specified_loc()*/) { + const t_specified_loc& specified_loc /*=t_specified_loc()*/) { if (!inter_cluster_rr[loc.layer_num]) { return true; } @@ -470,4 +469,4 @@ int evaluate_num_conns_formula(vtr::FormulaParser& formula_parser, formula_data.set_var_value("to", to_wire_count); return formula_parser.parse_formula(num_conns_formula, formula_data); -} \ No newline at end of file +} diff --git a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h index ecd05d18c89..33bbbc14eac 100644 --- a/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h +++ b/vpr/src/route/rr_graph_generation/switchblock_scatter_gather_common_utils.h @@ -8,7 +8,6 @@ #include - /** Contains info about a wire segment type */ struct t_wire_info { int length; ///< the length of this type of wire segment in tiles @@ -97,13 +96,13 @@ int get_switchpoint_of_wire(e_rr_type chan_type, e_side sb_side); /** -* @brief Evaluates a connection formula for scatter/gather and custom switchblock patterns. -* -* Sets variables "from" and "to" to the given wire counts and evaluates -* the formula string using the provided parser -*/ + * @brief Evaluates a connection formula for scatter/gather and custom switchblock patterns. + * + * Sets variables "from" and "to" to the given wire counts and evaluates + * the formula string using the provided parser + */ int evaluate_num_conns_formula(vtr::FormulaParser& formula_parser, vtr::t_formula_data& formula_data, const std::string& num_conns_formula, size_t from_wire_count, - size_t to_wire_count); \ No newline at end of file + size_t to_wire_count); diff --git a/vpr/src/util/vpr_utils.cpp b/vpr/src/util/vpr_utils.cpp index 56121dfa4bf..b786697df1c 100644 --- a/vpr/src/util/vpr_utils.cpp +++ b/vpr/src/util/vpr_utils.cpp @@ -63,14 +63,14 @@ std::string rr_node_arch_name(RRNodeId inode, bool is_flat) { if (rr_graph.node_type(inode) == e_rr_type::OPIN || rr_graph.node_type(inode) == e_rr_type::IPIN) { //Pin names t_physical_tile_type_ptr type = device_ctx.grid.get_physical_type({rr_graph.node_xlow(rr_node), - rr_graph.node_ylow(rr_node), - rr_graph.node_layer_low(rr_node)}); + rr_graph.node_ylow(rr_node), + rr_graph.node_layer_low(rr_node)}); rr_node_arch_name += block_type_pin_index_to_name(type, rr_graph.node_pin_num(rr_node), is_flat); } else if (rr_graph.node_type(inode) == e_rr_type::SOURCE || rr_graph.node_type(inode) == e_rr_type::SINK) { //Set of pins associated with SOURCE/SINK t_physical_tile_type_ptr type = device_ctx.grid.get_physical_type({rr_graph.node_xlow(rr_node), - rr_graph.node_ylow(rr_node), - rr_graph.node_layer_low(rr_node)}); + rr_graph.node_ylow(rr_node), + rr_graph.node_layer_low(rr_node)}); auto pin_names = block_type_class_index_to_pin_names(type, rr_graph.node_class_num(rr_node), is_flat); if (pin_names.size() > 1) { rr_node_arch_name += rr_graph.node_type_string(inode); @@ -1657,8 +1657,8 @@ int get_rr_node_max_ptc(const RRGraphView& rr_graph_view, const DeviceContext& device_ctx = g_vpr_ctx.device(); t_physical_tile_type_ptr physical_type = device_ctx.grid.get_physical_type({rr_graph_view.node_xlow(node_id), - rr_graph_view.node_ylow(node_id), - rr_graph_view.node_layer_low(node_id)}); + rr_graph_view.node_ylow(node_id), + rr_graph_view.node_layer_low(node_id)}); if (node_type == e_rr_type::SINK || node_type == e_rr_type::SOURCE) { return get_tile_class_max_ptc(physical_type, is_flat); From c35a77f6bbacc90bf137739b5b23d596c81f2607 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Thu, 18 Sep 2025 12:24:35 -0400 Subject: [PATCH 45/58] remove layer member vars from t_switchblock_edge --- .../build_switchblocks.cpp | 10 ++---- .../rr_graph_generation/build_switchblocks.h | 13 +------- .../route/rr_graph_generation/rr_graph2.cpp | 33 ++++++++----------- .../rr_graph_generation/rr_node_indices.h | 3 +- 4 files changed, 18 insertions(+), 41 deletions(-) diff --git a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp index 0064787e456..01d1f6ab9b6 100644 --- a/vpr/src/route/rr_graph_generation/build_switchblocks.cpp +++ b/vpr/src/route/rr_graph_generation/build_switchblocks.cpp @@ -567,24 +567,18 @@ static void compute_wireconn_connections(e_directionality directionality, int to_wire = potential_dest_wires[dest_wire_ind].wire; //Index in channel - /* create the struct containing information about the target wire segment which will be added to the - * sb connections map */ + // Initialize information about the target wire segment which will be added to the sb connections map t_switchblock_edge sb_edge; sb_edge.from_wire = from_wire; sb_edge.to_wire = to_wire; - sb_edge.from_wire_layer = from_loc.layer_num; - sb_edge.to_wire_layer = to_loc.layer_num; // if the switch override has been set, use that, Otherwise use default if (wireconn.switch_override_indx != DEFAULT_SWITCH) { sb_edge.switch_ind = wireconn.switch_override_indx; } else if (from_loc.layer_num == to_loc.layer_num) { sb_edge.switch_ind = to_chan_details[to_loc.x][to_loc.y][to_wire].arch_wire_switch(); - sb_edge.switch_ind_between_layers = -1; //the connection does not cross any layers } else { - VTR_ASSERT(from_loc.layer_num != to_loc.layer_num); - sb_edge.switch_ind = to_chan_details[to_loc.x][to_loc.y][to_wire].arch_wire_switch(); - sb_edge.switch_ind_between_layers = to_chan_details[to_loc.x][to_loc.y][to_wire].arch_inter_die_switch(); + VTR_ASSERT(false); } VTR_LOGV(verbose, " make_conn: %d -> %d switch=%d\n", sb_edge.from_wire, sb_edge.to_wire, sb_edge.switch_ind); diff --git a/vpr/src/route/rr_graph_generation/build_switchblocks.h b/vpr/src/route/rr_graph_generation/build_switchblocks.h index 08fd2fc7b76..7ec587f632b 100644 --- a/vpr/src/route/rr_graph_generation/build_switchblocks.h +++ b/vpr/src/route/rr_graph_generation/build_switchblocks.h @@ -77,9 +77,7 @@ struct t_hash_Switchblock_Lookup { } }; -/** - * @brief Contains the required information to build an RR graph edge for a switch block connection - */ +/// @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; @@ -89,15 +87,6 @@ struct t_switchblock_edge { /// 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; }; /** diff --git a/vpr/src/route/rr_graph_generation/rr_graph2.cpp b/vpr/src/route/rr_graph_generation/rr_graph2.cpp index bd1c348d3f1..22d3bd4140f 100644 --- a/vpr/src/route/rr_graph_generation/rr_graph2.cpp +++ b/vpr/src/route/rr_graph_generation/rr_graph2.cpp @@ -1408,32 +1408,27 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, 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; - 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); + RRNodeId to_node = rr_graph_builder.node_lookup().find_node(layer, to_x, to_y, to_chan_type, to_wire); - if (!to_node) { - continue; - } + if (!to_node) { + continue; + } - // Apply any switch overrides - if (should_apply_switch_override(switch_override)) { - src_switch = switch_override; - } + // Apply any switch overrides + if (should_apply_switch_override(switch_override)) { + src_switch = switch_override; + } - rr_edges_to_create.emplace_back(from_rr_node, to_node, src_switch, false); - ++edge_count; + rr_edges_to_create.emplace_back(from_rr_node, to_node, src_switch, false); + ++edge_count; - if (device_ctx.arch_switch_inf[src_switch].directionality() == 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 - VTR_ASSERT(false); + if (device_ctx.arch_switch_inf[src_switch].directionality() == BI_DIRECTIONAL) { + // Add reverse edge since bidirectional + rr_edges_to_create.emplace_back(to_node, from_rr_node, src_switch, false); + ++edge_count; } } } diff --git a/vpr/src/route/rr_graph_generation/rr_node_indices.h b/vpr/src/route/rr_graph_generation/rr_node_indices.h index 051eac0b395..ef2b34ef1be 100644 --- a/vpr/src/route/rr_graph_generation/rr_node_indices.h +++ b/vpr/src/route/rr_graph_generation/rr_node_indices.h @@ -34,8 +34,7 @@ void alloc_and_load_rr_node_indices(RRGraphBuilder& rr_graph_builder, * @brief Allocates extra nodes within the RR graph to support 3D custom switch blocks for multi-die FPGAs * * @param rr_graph_builder RRGraphBuilder data structure which allows data modification on a routing resource graph - * @param extra_nodes_per_switchblock keeps how many extra length-0 CHANX node is required for each unique (x,y) location within the grid. - * Number of these extra nodes are exactly the same for all layers. Hence, we only keep it for one layer. ([0..grid.width-1][0..grid.height-1) + * @param interdie_3d_links Specifies the 3-d inter-die wires that are to be added at each switch-block location. * @param index Pointer to the global RR node index counter; incremented as new RR nodes are assigned. */ void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, From 25185f329e15c71c74b3b81af179472af1abb8e9 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Thu, 18 Sep 2025 12:27:41 -0400 Subject: [PATCH 46/58] fix compilation error in test_fasm --- utils/fasm/test/test_fasm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/fasm/test/test_fasm.cpp b/utils/fasm/test/test_fasm.cpp index 63767ccc1d1..ed125b30e5f 100644 --- a/utils/fasm/test/test_fasm.cpp +++ b/utils/fasm/test/test_fasm.cpp @@ -192,7 +192,7 @@ static std::string get_pin_feature (size_t inode) { // Get tile physical tile and the pin number int ilow = rr_graph.node_xlow(RRNodeId(inode)); int jlow = rr_graph.node_ylow(RRNodeId(inode)); - int layer_num = rr_graph.node_layer(RRNodeId(inode)); + int layer_num = rr_graph.node_layer_low(RRNodeId(inode)); auto physical_tile = device_ctx.grid.get_physical_type({ilow, jlow, layer_num}); int pin_num = rr_graph.node_pin_num(RRNodeId(inode)); From 6833d1c0054a072e5b427ff137687db8235b6f09 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Thu, 18 Sep 2025 12:52:44 -0400 Subject: [PATCH 47/58] clean some doxygen comments --- libs/libarchfpga/src/switchblock_types.h | 8 +------- libs/librrgraph/src/base/rr_graph_view.h | 15 ++++++--------- .../rr_graph_generation/build_switchblocks.h | 2 +- 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/libs/libarchfpga/src/switchblock_types.h b/libs/libarchfpga/src/switchblock_types.h index 02c46344a05..0e1255d5311 100644 --- a/libs/libarchfpga/src/switchblock_types.h +++ b/libs/libarchfpga/src/switchblock_types.h @@ -64,10 +64,7 @@ inline const std::unordered_map CHAR_SIDE_MAP = { 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 -/** - * @brief Specifies what part of the FPGA a custom switchblock should be built in (i.e. perimeter, core, everywhere) - * - */ +/// @brief 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, @@ -96,7 +93,6 @@ struct t_sb_loc_spec { /** * @brief represents a connection between two sides of a switchblock - * */ class SBSideConnection { public: @@ -141,7 +137,6 @@ enum class e_switch_point_order { /** * @brief A collection of switchpoints associated with a segment - * */ struct t_wire_switchpoints { std::string segment_name; ///< The type of segment @@ -150,7 +145,6 @@ struct t_wire_switchpoints { /** * @brief 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) diff --git a/libs/librrgraph/src/base/rr_graph_view.h b/libs/librrgraph/src/base/rr_graph_view.h index 9dd99189217..c8ec99adae3 100644 --- a/libs/librrgraph/src/base/rr_graph_view.h +++ b/libs/librrgraph/src/base/rr_graph_view.h @@ -25,7 +25,10 @@ * 5. A short (metal connection). * * - * @note Despite the RRGraph containing millions of edges, there are only a few switch types. Therefore, all switch details, including R and C, are stored using a flyweight pattern (rr_switch_inf) rather than being directly embedded in the edge-related data of the RRGraph. Each edge stores the ID of its associated switch for easy lookup. + * @note Despite the RRGraph containing millions of edges, there are only a few switch types. + * Therefore, all switch details, including R and C, are stored using a flyweight pattern (rr_switch_inf) + * rather than being directly embedded in the edge-related data of the RRGraph. + * Each edge stores the ID of its associated switch for easy lookup. * * * \internal @@ -225,21 +228,15 @@ class RRGraphView { return node_storage_.node_yhigh(node); } - /** @brief Return the layer num of a specified node. - */ - // inline short node_layer(RRNodeId node) const { - // return node_storage_.node_layer(node); - // } - + /// @brief Returns the highest layer where a node is located at. inline short node_layer_high(RRNodeId node) const { return node_storage_.node_layer_high(node); } + /// @brief Returns the lowest layer where a node is located at. inline short node_layer_low(RRNodeId node) const { return node_storage_.node_layer_low(node); } - - /** * @brief Return the bend start of a specified node. diff --git a/vpr/src/route/rr_graph_generation/build_switchblocks.h b/vpr/src/route/rr_graph_generation/build_switchblocks.h index 7ec587f632b..c4a9d5cc37b 100644 --- a/vpr/src/route/rr_graph_generation/build_switchblocks.h +++ b/vpr/src/route/rr_graph_generation/build_switchblocks.h @@ -85,7 +85,7 @@ struct t_switchblock_edge { /// 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 + /// RR graph switch index that connects the source wire to the destination wire that connect two tracks short switch_ind; }; From 1ca2ea2b2d2bee180c7eca7be2f58b93e52bcca4 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Thu, 18 Sep 2025 17:44:16 -0400 Subject: [PATCH 48/58] remove strong scatter gather test --- .../strong_scatter_gather/config/config.txt | 27 ------------------- .../config/golden_results.txt | 2 -- 2 files changed, 29 deletions(-) delete mode 100644 vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_scatter_gather/config/config.txt delete mode 100644 vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_scatter_gather/config/golden_results.txt diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_scatter_gather/config/config.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_scatter_gather/config/config.txt deleted file mode 100644 index 76a3a6293fe..00000000000 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_scatter_gather/config/config.txt +++ /dev/null @@ -1,27 +0,0 @@ -############################################## -# Configuration file for running experiments -############################################## - -# Path to directory of circuits to use -circuits_dir=benchmarks/verilog - -# Path to directory of architectures to use -archs_dir=arch/scatter-gather - -# Add circuits to list to sweep -circuit_list_add=ch_intrinsics.v - -# Add architectures to list to sweep -arch_list_add=k6_frac_N10_frac_chain_mem32K_40nm_sg.xml - -# Parse info and how to parse -parse_file=vpr_standard.txt - -# How to parse QoR info -qor_parse_file=qor_standard.txt - -# Pass requirements -pass_requirements_file=pass_requirements.txt - -# Script parameters -script_params_common = -track_memory_usage diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_scatter_gather/config/golden_results.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_scatter_gather/config/golden_results.txt deleted file mode 100644 index ecae57d76d6..00000000000 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_scatter_gather/config/golden_results.txt +++ /dev/null @@ -1,2 +0,0 @@ -arch circuit script_params vtr_flow_elapsed_time vtr_max_mem_stage vtr_max_mem error odin_synth_time max_odin_mem parmys_synth_time max_parmys_mem abc_depth abc_synth_time abc_cec_time abc_sec_time max_abc_mem ace_time max_ace_mem num_clb num_io num_memories num_mult vpr_status vpr_revision vpr_build_info vpr_compiler vpr_compiled hostname rundir max_vpr_mem num_primary_inputs num_primary_outputs num_pre_packed_nets num_pre_packed_blocks num_netlist_clocks num_post_packed_nets num_post_packed_blocks device_width device_height device_grid_tiles device_limiting_resources device_name pack_mem pack_time initial_placed_wirelength_est placed_wirelength_est total_swap accepted_swap rejected_swap aborted_swap place_mem place_time place_quench_time initial_placed_CPD_est placed_CPD_est placed_setup_TNS_est placed_setup_WNS_est placed_geomean_nonvirtual_intradomain_critical_path_delay_est place_delay_matrix_lookup_time place_quench_timing_analysis_time place_quench_sta_time place_total_timing_analysis_time place_total_sta_time ap_mem ap_time ap_full_legalizer_mem ap_full_legalizer_time min_chan_width routed_wirelength min_chan_width_route_success_iteration logic_block_area_total logic_block_area_used min_chan_width_routing_area_total min_chan_width_routing_area_per_tile min_chan_width_route_time min_chan_width_total_timing_analysis_time min_chan_width_total_sta_time crit_path_num_rr_graph_nodes crit_path_num_rr_graph_edges crit_path_collapsed_nodes crit_path_routed_wirelength crit_path_route_success_iteration crit_path_total_nets_routed crit_path_total_connections_routed crit_path_total_heap_pushes crit_path_total_heap_pops critical_path_delay geomean_nonvirtual_intradomain_critical_path_delay setup_TNS setup_WNS hold_TNS hold_WNS crit_path_routing_area_total crit_path_routing_area_per_tile router_lookahead_computation_time crit_path_route_time crit_path_create_rr_graph_time crit_path_create_intra_cluster_rr_graph_time crit_path_tile_lookahead_computation_time crit_path_router_lookahead_computation_time crit_path_total_timing_analysis_time crit_path_total_sta_time -k6_frac_N10_frac_chain_mem32K_40nm_sg.xml ch_intrinsics.v common 2.49 vpr 71.47 MiB -1 -1 0.16 30900 3 0.07 -1 -1 37084 -1 -1 68 99 1 0 success v8.0.0-13673-g028e6044f-dirty release VTR_ASSERT_LEVEL=2 GNU 15.1.1 on Linux-6.14.9-300.fc42.x86_64 x86_64 2025-08-25T13:13:32 betzgrp-pcamir.eecg /home/amirpoolad/Dev/vtr-verilog-to-routing 73184 99 130 344 474 1 227 298 12 12 144 clb auto 32.5 MiB 0.15 1668.56 665 69948 18708 40810 10430 71.5 MiB 0.19 0.00 2.40104 1.86413 -122.75 -1.86413 1.86413 0.12 0.000537934 0.000489526 0.0618774 0.0565413 -1 -1 -1 -1 44 1308 13 5.66058e+06 4.21279e+06 360780. 2505.42 0.92 0.280685 0.252587 13374 71755 -1 1113 9 385 601 24354 7746 1.97022 1.97022 -144.54 -1.97022 0 0 470760. 3269.17 0.01 0.03 0.05 -1 -1 0.01 0.0184111 0.0172572 From 6da700b08ecd2ca2931f114db5f3a0ddc5f7f728 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Thu, 18 Sep 2025 17:45:43 -0400 Subject: [PATCH 49/58] remove scatter gather test from task list --- vtr_flow/tasks/regression_tests/vtr_reg_strong/task_list.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/task_list.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/task_list.txt index 9c25c849c96..f94619b0bcd 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/task_list.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/task_list.txt @@ -119,4 +119,3 @@ regression_tests/vtr_reg_strong/strong_3d/3d_cb regression_tests/vtr_reg_strong/strong_3d/3d_sb regression_tests/vtr_reg_strong/strong_xilinx_simple regression_tests/vtr_reg_strong/strong_xilinx_flagship -regression_tests/vtr_reg_strong/strong_scatter_gather From 3336f289bfb400ce3b9381970abcaacb416108e9 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Thu, 18 Sep 2025 17:56:37 -0400 Subject: [PATCH 50/58] add a chanz wire and mux to SIV cb 3d arch file --- .../3d_full_OPIN_inter_die_stratixiv_arch.timing.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/vtr_flow/arch/multi_die/stratixiv_3d/3d_full_OPIN_inter_die_stratixiv_arch.timing.xml b/vtr_flow/arch/multi_die/stratixiv_3d/3d_full_OPIN_inter_die_stratixiv_arch.timing.xml index 206a64dd7eb..e673d3eb837 100644 --- a/vtr_flow/arch/multi_die/stratixiv_3d/3d_full_OPIN_inter_die_stratixiv_arch.timing.xml +++ b/vtr_flow/arch/multi_die/stratixiv_3d/3d_full_OPIN_inter_die_stratixiv_arch.timing.xml @@ -5116,6 +5116,8 @@ --> + + @@ -5235,6 +5237,10 @@ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + + + From e70ce875d8cccd451f31f00b07b6f2eee0964f07 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Thu, 18 Sep 2025 17:57:14 -0400 Subject: [PATCH 51/58] remove k6_sg arch file --- .../k6_frac_N10_frac_chain_mem32K_40nm_sg.xml | 1606 ----------------- 1 file changed, 1606 deletions(-) delete mode 100644 vtr_flow/arch/scatter-gather/k6_frac_N10_frac_chain_mem32K_40nm_sg.xml diff --git a/vtr_flow/arch/scatter-gather/k6_frac_N10_frac_chain_mem32K_40nm_sg.xml b/vtr_flow/arch/scatter-gather/k6_frac_N10_frac_chain_mem32K_40nm_sg.xml deleted file mode 100644 index dd06c897395..00000000000 --- a/vtr_flow/arch/scatter-gather/k6_frac_N10_frac_chain_mem32K_40nm_sg.xml +++ /dev/null @@ -1,1606 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - io.outpad io.inpad io.clock - io.outpad io.inpad io.clock - io.outpad io.inpad io.clock - io.outpad io.inpad io.clock - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 1 1 1 1 - 1 1 1 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 235e-12 - 235e-12 - 235e-12 - 235e-12 - 235e-12 - - - 174e-12 - 174e-12 - 174e-12 - 174e-12 - 174e-12 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 195e-12 - 195e-12 - 195e-12 - 195e-12 - - - 144e-12 - 144e-12 - 144e-12 - 144e-12 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 261e-12 - 261e-12 - 261e-12 - 261e-12 - 261e-12 - 261e-12 - - - 174e-12 - 174e-12 - 174e-12 - 174e-12 - 174e-12 - 174e-12 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From c187d716719c350586489e58b6382dc7767d7986 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Thu, 18 Sep 2025 18:02:51 -0400 Subject: [PATCH 52/58] add chanz segment and switch to 3d_k4_N4_90nm.xml --- vtr_flow/arch/multi_die/simple_arch/3d_k4_N4_90nm.xml | 4 ++++ .../3d_full_OPIN_inter_die_stratixiv_arch.timing.xml | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/vtr_flow/arch/multi_die/simple_arch/3d_k4_N4_90nm.xml b/vtr_flow/arch/multi_die/simple_arch/3d_k4_N4_90nm.xml index 0f525323384..500df33875f 100644 --- a/vtr_flow/arch/multi_die/simple_arch/3d_k4_N4_90nm.xml +++ b/vtr_flow/arch/multi_die/simple_arch/3d_k4_N4_90nm.xml @@ -96,6 +96,7 @@ + @@ -104,6 +105,9 @@ 1 1 1 + + + diff --git a/vtr_flow/arch/multi_die/stratixiv_3d/3d_full_OPIN_inter_die_stratixiv_arch.timing.xml b/vtr_flow/arch/multi_die/stratixiv_3d/3d_full_OPIN_inter_die_stratixiv_arch.timing.xml index e673d3eb837..141e357fe06 100644 --- a/vtr_flow/arch/multi_die/stratixiv_3d/3d_full_OPIN_inter_die_stratixiv_arch.timing.xml +++ b/vtr_flow/arch/multi_die/stratixiv_3d/3d_full_OPIN_inter_die_stratixiv_arch.timing.xml @@ -5237,7 +5237,6 @@ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 - From 8ebd707269d249ef7f0f79d3f39914f84205b445 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Fri, 19 Sep 2025 13:01:52 -0400 Subject: [PATCH 53/58] remove above and under directions from a comment in parse_switchblocks.cpp --- libs/libarchfpga/src/parse_switchblocks.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/libarchfpga/src/parse_switchblocks.cpp b/libs/libarchfpga/src/parse_switchblocks.cpp index 64635723f36..7209314371b 100644 --- a/libs/libarchfpga/src/parse_switchblocks.cpp +++ b/libs/libarchfpga/src/parse_switchblocks.cpp @@ -338,7 +338,7 @@ static void set_switch_func_type(SBSideConnection& conn, std::string_view func_t archfpga_throw(__FILE__, __LINE__, "Custom switchblock func type must be 2 characters long: %s\n", func_type); } - // Only valid sides are right, top, left, bottom, above and under + // Only valid sides are right, top, left, bottom if (func_type.find_first_not_of("rtlbRTLB") != std::string::npos) { archfpga_throw(__FILE__, __LINE__, "Unknown direction specified: %s\n", func_type); } From 20dbfe6db5ae44dad3057d1bc04e870d82269010 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Fri, 19 Sep 2025 13:09:16 -0400 Subject: [PATCH 54/58] add chan_type_to_index() --- .../router_lookahead/router_lookahead_map.cpp | 46 ++----------------- .../router_lookahead_map_utils.h | 22 +++++++++ 2 files changed, 25 insertions(+), 43 deletions(-) diff --git a/vpr/src/route/router_lookahead/router_lookahead_map.cpp b/vpr/src/route/router_lookahead/router_lookahead_map.cpp index 6bb3d36184f..cef970e0d7c 100644 --- a/vpr/src/route/router_lookahead/router_lookahead_map.cpp +++ b/vpr/src/route/router_lookahead/router_lookahead_map.cpp @@ -503,21 +503,7 @@ static util::Cost_Entry get_wire_cost_entry(e_rr_type rr_type, int seg_index, in VTR_ASSERT_SAFE(delta_x < static_cast(f_wire_cost_map.dim_size(4))); VTR_ASSERT_SAFE(delta_y < static_cast(f_wire_cost_map.dim_size(5))); - int chan_index; - switch (rr_type) { - case e_rr_type::CHANX: - chan_index = 0; - break; - case e_rr_type::CHANY: - chan_index = 1; - break; - case e_rr_type::CHANZ: - chan_index = 2; - break; - default: - VTR_ASSERT(false); - } - + const int chan_index = util::chan_type_to_index(rr_type); return f_wire_cost_map[from_layer_num][to_layer_num][chan_index][seg_index][delta_x][delta_y]; } @@ -588,20 +574,7 @@ static void set_lookahead_map_costs(unsigned from_layer_num, int segment_index, e_rr_type chan_type, util::t_routing_cost_map& routing_cost_map) { - int chan_index; - switch (chan_type) { - case e_rr_type::CHANX: - chan_index = 0; - break; - case e_rr_type::CHANY: - chan_index = 1; - break; - case e_rr_type::CHANZ: - chan_index = 2; - break; - default: - VTR_ASSERT(false); - } + const int chan_index = util::chan_type_to_index(chan_type); // set the lookahead cost map entries with a representative cost entry from routing_cost_map for (unsigned to_layer = 0; to_layer < routing_cost_map.dim_size(0); to_layer++) { @@ -618,20 +591,7 @@ static void set_lookahead_map_costs(unsigned from_layer_num, static void fill_in_missing_lookahead_entries(int segment_index, e_rr_type chan_type) { const DeviceContext& device_ctx = g_vpr_ctx.device(); - int chan_index; - switch (chan_type) { - case e_rr_type::CHANX: - chan_index = 0; - break; - case e_rr_type::CHANY: - chan_index = 1; - break; - case e_rr_type::CHANZ: - chan_index = 2; - break; - default: - VTR_ASSERT(false); - } + const int chan_index = util::chan_type_to_index(chan_type); const int num_layers = device_ctx.grid.get_num_layers(); const int grid_width = device_ctx.grid.width(); diff --git a/vpr/src/route/router_lookahead/router_lookahead_map_utils.h b/vpr/src/route/router_lookahead/router_lookahead_map_utils.h index 3d23058dbb6..325db7aa59d 100644 --- a/vpr/src/route/router_lookahead/router_lookahead_map_utils.h +++ b/vpr/src/route/router_lookahead/router_lookahead_map_utils.h @@ -358,4 +358,26 @@ std::pair get_cost_from_src_opin(const std::map& dim_sizes, WireCostCallBackFunction wire_cost_func); + + /// @brief Converts a routing channel type (CHANX/CHANY/CHANZ) to an index + /// to access the channel type dimension of the router lookahead table. +inline int chan_type_to_index(e_rr_type chan_type) { + int chan_index; + switch (chan_type) { + case e_rr_type::CHANX: + chan_index = 0; + break; + case e_rr_type::CHANY: + chan_index = 1; + break; + case e_rr_type::CHANZ: + chan_index = 2; + break; + default: + VTR_ASSERT(false); + } + + return chan_index; +} + } // namespace util From 7e2a68ff871e72328dd19cebd5187f6328b712cb Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Fri, 19 Sep 2025 13:10:37 -0400 Subject: [PATCH 55/58] write rr_index_info only when echo is enabled --- libs/librrgraph/src/utils/alloc_and_load_rr_indexed_data.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/librrgraph/src/utils/alloc_and_load_rr_indexed_data.cpp b/libs/librrgraph/src/utils/alloc_and_load_rr_indexed_data.cpp index 0510cca1177..f63e453dc14 100644 --- a/libs/librrgraph/src/utils/alloc_and_load_rr_indexed_data.cpp +++ b/libs/librrgraph/src/utils/alloc_and_load_rr_indexed_data.cpp @@ -164,9 +164,9 @@ void alloc_and_load_rr_indexed_data(const RRGraphView& rr_graph, load_rr_indexed_data_base_costs(rr_graph, rr_indexed_data, base_cost_type, echo_enabled, echo_file_name); - if (true) { + if (echo_enabled) { print_rr_index_info(rr_indexed_data, - "indexed_data.txt", + echo_file_name, segment_inf, segment_inf_x.size(), segment_inf_x.size() + segment_inf_y.size()); From 15dfee5c7ea2ac26d9008ee8cf9fc023d67b4cf2 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Fri, 19 Sep 2025 13:20:05 -0400 Subject: [PATCH 56/58] short --> char for layer getter methods --- libs/librrgraph/src/base/rr_graph_storage.h | 4 ++-- libs/librrgraph/src/base/rr_graph_view.h | 4 ++-- libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h | 7 +++++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/libs/librrgraph/src/base/rr_graph_storage.h b/libs/librrgraph/src/base/rr_graph_storage.h index c64c9558556..b3ba964de80 100644 --- a/libs/librrgraph/src/base/rr_graph_storage.h +++ b/libs/librrgraph/src/base/rr_graph_storage.h @@ -1107,12 +1107,12 @@ class t_rr_graph_view { } /// @brief Retrieve the lowest layer (die) number where the given RRNodeId is located. - short node_layer_low(RRNodeId id) const { + char node_layer_low(RRNodeId id) const { return node_layer_low_[id]; } /// @brief Retrieve the highest layer (die) number where the given RRNodeId is located. - short node_layer_high(RRNodeId id) const { + char node_layer_high(RRNodeId id) const { return node_layer_high_[id]; } diff --git a/libs/librrgraph/src/base/rr_graph_view.h b/libs/librrgraph/src/base/rr_graph_view.h index c8ec99adae3..e49bd6268ae 100644 --- a/libs/librrgraph/src/base/rr_graph_view.h +++ b/libs/librrgraph/src/base/rr_graph_view.h @@ -229,12 +229,12 @@ class RRGraphView { } /// @brief Returns the highest layer where a node is located at. - inline short node_layer_high(RRNodeId node) const { + inline char node_layer_high(RRNodeId node) const { return node_storage_.node_layer_high(node); } /// @brief Returns the lowest layer where a node is located at. - inline short node_layer_low(RRNodeId node) const { + inline char node_layer_low(RRNodeId node) const { return node_storage_.node_layer_low(node); } diff --git a/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h b/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h index 5a7d8d3e636..284c01ab0d5 100644 --- a/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h +++ b/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h @@ -744,7 +744,8 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { auto node = (*rr_nodes_)[inode]; RRNodeId node_id = node.id(); - VTR_ASSERT(layer_num >= 0); + // Currently, we only support two layers + VTR_ASSERT(layer_num >= 0 && layer_num <= 1); rr_graph_builder_->set_node_layer_low(node_id, layer_num); } @@ -752,7 +753,9 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { auto node = (*rr_nodes_)[inode]; RRNodeId node_id = node.id(); - VTR_ASSERT(layer_num >= 0); + // Currently, we only support two layers + VTR_ASSERT(layer_num >= 0 && layer_num <= 1); + VTR_ASSERT(layer_num >= 0 && layer_num <= 1); rr_graph_builder_->set_node_layer_high(node_id, layer_num); } From 61c8885a978ee0b97c8ec0f0805296468d8352e4 Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Fri, 19 Sep 2025 16:24:50 -0400 Subject: [PATCH 57/58] snake case --- libs/libarchfpga/src/read_xml_arch_file.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libs/libarchfpga/src/read_xml_arch_file.cpp b/libs/libarchfpga/src/read_xml_arch_file.cpp index 629446c706f..b6158ef4c35 100644 --- a/libs/libarchfpga/src/read_xml_arch_file.cpp +++ b/libs/libarchfpga/src/read_xml_arch_file.cpp @@ -3818,11 +3818,11 @@ static std::vector process_segments(pugi::xml_node Parent, pugi::xml_node Node; // Count the number of segs and check they are in fact of segment elements. - int NumSegs = count_children(Parent, "segment", loc_data); + int num_segs = count_children(Parent, "segment", loc_data); // Alloc segment list - if (NumSegs > 0) { - Segs.resize(NumSegs); + if (num_segs > 0) { + Segs.resize(num_segs); } // Load the segments. @@ -3832,7 +3832,7 @@ static std::vector process_segments(pugi::xml_node Parent, bool y_axis_seg_found = false; // Flags to see if we have any y-directed segment type specified bool z_axis_seg_found = false; // Flags to see if we have any z-directed segment type specified - for (int i = 0; i < NumSegs; ++i) { + for (int i = 0; i < num_segs; ++i) { /* Get segment name */ tmp = get_attribute(Node, "name", loc_data, ReqOpt::OPTIONAL).as_string(nullptr); if (tmp) { @@ -4174,7 +4174,7 @@ static void process_bend(pugi::xml_node Node, t_segment_inf& segment, const int part_len.push_back(list.size() + 1 - sum_len); } -static void calculate_custom_SB_locations(const pugiutil::loc_data& loc_data, +static void calculate_custom_sb_locations(const pugiutil::loc_data& loc_data, const pugi::xml_node& SubElem, const int grid_width, const int grid_height, @@ -4299,7 +4299,7 @@ static void process_switch_blocks(pugi::xml_node Parent, t_arch* arch, const pug // we have to parse the region specification and apply the SB pattern to all the locations fall into the specified // region based on device width and height. if (sb.specified_loc.x == ARCH_FPGA_UNDEFINED_VAL && sb.specified_loc.y == ARCH_FPGA_UNDEFINED_VAL) { - calculate_custom_SB_locations(loc_data, SubElem, grid_width, grid_height, sb); + calculate_custom_sb_locations(loc_data, SubElem, grid_width, grid_height, sb); } } From b4f3e757bebf41b80d846d135cc8f889926bf98c Mon Sep 17 00:00:00 2001 From: Soheil Shahrouz Date: Fri, 19 Sep 2025 17:20:16 -0400 Subject: [PATCH 58/58] address remaining PR comments on auto and commenting --- libs/libarchfpga/src/read_xml_arch_file.cpp | 10 +++++----- libs/librrgraph/src/base/check_rr_graph.cpp | 2 +- libs/librrgraph/src/base/get_parallel_segs.cpp | 4 ++++ libs/librrgraph/src/base/get_parallel_segs.h | 8 ++++---- libs/librrgraph/src/base/rr_graph_utils.cpp | 7 ++----- libs/librrgraph/src/base/rr_graph_view.h | 2 +- libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h | 8 ++++---- 7 files changed, 21 insertions(+), 20 deletions(-) diff --git a/libs/libarchfpga/src/read_xml_arch_file.cpp b/libs/libarchfpga/src/read_xml_arch_file.cpp index b6158ef4c35..187f1b4b01b 100644 --- a/libs/libarchfpga/src/read_xml_arch_file.cpp +++ b/libs/libarchfpga/src/read_xml_arch_file.cpp @@ -345,7 +345,7 @@ static void process_clock_routing(pugi::xml_node parent, const std::vector& switches, pugiutil::loc_data& loc_data); -static std::vector process_segments(pugi::xml_node Parent, +static std::vector process_segments(pugi::xml_node parent, const std::vector& switches, int num_layers, const bool timing_enabled, @@ -3804,7 +3804,7 @@ static void process_complex_blocks(pugi::xml_node Node, } } -static std::vector process_segments(pugi::xml_node Parent, +static std::vector process_segments(pugi::xml_node parent, const std::vector& switches, int num_layers, const bool timing_enabled, @@ -3817,8 +3817,8 @@ static std::vector process_segments(pugi::xml_node Parent, pugi::xml_node SubElem; pugi::xml_node Node; - // Count the number of segs and check they are in fact of segment elements. - int num_segs = count_children(Parent, "segment", loc_data); + // Count the number of segs specified in the architecture file. + int num_segs = count_children(parent, "segment", loc_data); // Alloc segment list if (num_segs > 0) { @@ -3826,7 +3826,7 @@ static std::vector process_segments(pugi::xml_node Parent, } // Load the segments. - Node = get_first_child(Parent, "segment", loc_data); + Node = get_first_child(parent, "segment", loc_data); bool x_axis_seg_found = false; // Flags to see if we have any x-directed segment type specified bool y_axis_seg_found = false; // Flags to see if we have any y-directed segment type specified diff --git a/libs/librrgraph/src/base/check_rr_graph.cpp b/libs/librrgraph/src/base/check_rr_graph.cpp index 267c3676510..f3646c98ccb 100644 --- a/libs/librrgraph/src/base/check_rr_graph.cpp +++ b/libs/librrgraph/src/base/check_rr_graph.cpp @@ -348,7 +348,7 @@ void check_rr_node(const RRGraphView& rr_graph, int ylow = rr_graph.node_ylow(rr_node); int yhigh = rr_graph.node_yhigh(rr_node); int layer_low = rr_graph.node_layer_low(rr_node); - int layer_high = rr_graph.node_layer_low(rr_node); + int layer_high = rr_graph.node_layer_high(rr_node); int ptc_num = rr_graph.node_ptc_num(rr_node); int capacity = rr_graph.node_capacity(rr_node); RRIndexedDataId cost_index = rr_graph.node_cost_index(rr_node); diff --git a/libs/librrgraph/src/base/get_parallel_segs.cpp b/libs/librrgraph/src/base/get_parallel_segs.cpp index 4719e073fe0..9f3738d8959 100644 --- a/libs/librrgraph/src/base/get_parallel_segs.cpp +++ b/libs/librrgraph/src/base/get_parallel_segs.cpp @@ -7,6 +7,10 @@ std::vector get_parallel_segs(const std::vector& s std::vector result; for (size_t i = 0; i < segment_inf.size(); ++i) { e_parallel_axis seg_axis = segment_inf[i].parallel_axis; + + // Keep this segment if: + // 1. Its axis exactly matches the requested parallel_axis, OR + // 2. The requested axis is X or Y (not Z), and the segment is marked BOTH_AXIS. if (seg_axis == parallel_axis || (parallel_axis != e_parallel_axis::Z_AXIS && seg_axis == e_parallel_axis::BOTH_AXIS)) { result.push_back(segment_inf[i]); diff --git a/libs/librrgraph/src/base/get_parallel_segs.h b/libs/librrgraph/src/base/get_parallel_segs.h index 47e64a575e2..19fc84be1c7 100644 --- a/libs/librrgraph/src/base/get_parallel_segs.h +++ b/libs/librrgraph/src/base/get_parallel_segs.h @@ -4,11 +4,11 @@ #include "physical_types.h" /** - * @brief Returns segments aligned with a given axis, including BOTH_AXIS segments. + * @brief Filters segments aligned with a given axis and records index mappings. * - * Filters the unified segment list (`segment_inf`) to include only segments matching - * the specified `parallel_axis` or marked as `BOTH_AXIS`. Also populates `seg_index_map` - * to map unified indices to axis-specific ones. + * Iterates through the unified segment list (`segment_inf`) and selects segments + * whose `parallel_axis` matches the requested `parallel_axis`. If the requested + * axis is not `Z_AXIS`, segments marked as `BOTH_AXIS` are also included. * * @param segment_inf Unified list of all segments. * @param seg_index_map Map from unified to axis-specific segment indices. diff --git a/libs/librrgraph/src/base/rr_graph_utils.cpp b/libs/librrgraph/src/base/rr_graph_utils.cpp index b721c34de35..dcafc96fc55 100644 --- a/libs/librrgraph/src/base/rr_graph_utils.cpp +++ b/libs/librrgraph/src/base/rr_graph_utils.cpp @@ -154,7 +154,7 @@ void rr_set_sink_locs(const RRGraphView& rr_graph, RRGraphBuilder& rr_graph_buil for (size_t node = 0; node < rr_graph.num_nodes(); ++node) { auto node_id = RRNodeId(node); - if (rr_graph.node_type((RRNodeId)node_id) != e_rr_type::SINK) { + if (rr_graph.node_type(node_id) != e_rr_type::SINK) { continue; } @@ -170,10 +170,7 @@ void rr_set_sink_locs(const RRGraphView& rr_graph, RRGraphBuilder& rr_graph_buil } const int node_layer = rr_graph.node_layer_low(node_id); - // Only CHANZ nodes spand across multiple layers. We're processing SINK nodes - if (node_layer != rr_graph.node_layer_high(node_id)) { - continue; - } + VTR_ASSERT(node_layer == rr_graph.node_layer_high(node_id)); int node_ptc = rr_graph.node_ptc_num(node_id); diff --git a/libs/librrgraph/src/base/rr_graph_view.h b/libs/librrgraph/src/base/rr_graph_view.h index e49bd6268ae..ca825d15642 100644 --- a/libs/librrgraph/src/base/rr_graph_view.h +++ b/libs/librrgraph/src/base/rr_graph_view.h @@ -416,7 +416,7 @@ class RRGraphView { else { // signal travels in increasing direction, stays at same point, or can travel both directions start_x = " (" + std::to_string(node_xlow(node)) + ","; //start coordinates have smaller value start_y = std::to_string(node_ylow(node)) + ","; - start_layer_str = std::to_string(node_layer_high(node)) + ")"; + start_layer_str = std::to_string(node_layer_low(node)) + ")"; end_x = " (" + std::to_string(node_xhigh(node)) + ","; //end coordinates have larger value end_y = std::to_string(node_yhigh(node)) + ","; end_layer_str = std::to_string(node_layer_high(node)) + ")"; //layer number diff --git a/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h b/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h index 284c01ab0d5..f8a4f36fda0 100644 --- a/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h +++ b/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h @@ -431,8 +431,8 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { segment_inf_vec_ptr = &segment_inf_z_; } - for(std::vector::size_type i=0; i < segment_inf_vec_ptr->size(); i++){ - if((*segment_inf_vec_ptr)[i].seg_index == segment_id) + for (size_t i = 0; i < segment_inf_vec_ptr->size(); i++){ + if ((*segment_inf_vec_ptr)[i].seg_index == segment_id) return static_cast(i); } @@ -741,7 +741,7 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { } inline void set_node_loc_layer_low(int layer_num, int& inode) final { - auto node = (*rr_nodes_)[inode]; + const t_rr_node& node = (*rr_nodes_)[inode]; RRNodeId node_id = node.id(); // Currently, we only support two layers @@ -750,7 +750,7 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { } inline void set_node_loc_layer_high(int layer_num, int& inode) final { - auto node = (*rr_nodes_)[inode]; + const t_rr_node& node = (*rr_nodes_)[inode]; RRNodeId node_id = node.id(); // Currently, we only support two layers