From 4af1381068ea2c68ffed05e6047ce9fb3c8f5726 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Thu, 3 Aug 2023 19:21:06 -0400 Subject: [PATCH 01/83] extended e_side structure to contain above layer and below layer to get switchblock pattern custom work for 3d --- libs/libarchfpga/src/parse_switchblocks.cpp | 97 +++++++++++++------ libs/libarchfpga/src/physical_types.h | 9 +- .../arch/multi_die/stratixiv_arch.timing.xml | 1 + 3 files changed, 78 insertions(+), 29 deletions(-) diff --git a/libs/libarchfpga/src/parse_switchblocks.cpp b/libs/libarchfpga/src/parse_switchblocks.cpp index 182d194c5d7..deed2db5936 100644 --- a/libs/libarchfpga/src/parse_switchblocks.cpp +++ b/libs/libarchfpga/src/parse_switchblocks.cpp @@ -65,6 +65,9 @@ static void parse_comma_separated_wire_points(const char* ch, std::vector */ void read_sb_switchfuncs(pugi::xml_node Node, t_switchblock_inf* sb, const pugiutil::loc_data& loc_data) { @@ -300,34 +367,8 @@ void read_sb_switchfuncs(pugi::xml_node Node, t_switchblock_inf* sb, const pugiu func_formula = get_attribute(SubElem, "formula", loc_data).as_string(nullptr); /* go through all the possible cases of func_type */ - if (0 == strcmp(func_type, "lt")) { - conn.set_sides(LEFT, TOP); - } else if (0 == strcmp(func_type, "lr")) { - conn.set_sides(LEFT, RIGHT); - } else if (0 == strcmp(func_type, "lb")) { - conn.set_sides(LEFT, BOTTOM); - } else if (0 == strcmp(func_type, "tl")) { - conn.set_sides(TOP, LEFT); - } else if (0 == strcmp(func_type, "tb")) { - conn.set_sides(TOP, BOTTOM); - } else if (0 == strcmp(func_type, "tr")) { - conn.set_sides(TOP, RIGHT); - } else if (0 == strcmp(func_type, "rt")) { - conn.set_sides(RIGHT, TOP); - } else if (0 == strcmp(func_type, "rl")) { - conn.set_sides(RIGHT, LEFT); - } else if (0 == strcmp(func_type, "rb")) { - conn.set_sides(RIGHT, BOTTOM); - } else if (0 == strcmp(func_type, "bl")) { - conn.set_sides(BOTTOM, LEFT); - } else if (0 == strcmp(func_type, "bt")) { - conn.set_sides(BOTTOM, TOP); - } else if (0 == strcmp(func_type, "br")) { - conn.set_sides(BOTTOM, RIGHT); - } else { - /* unknown permutation function */ - archfpga_throw(__FILE__, __LINE__, "Unknown permutation function specified: %s\n", func_type); - } + set_switch_func_type(conn,func_type); + func_ptr = &(sb->permutation_map[conn]); /* Here we load the specified switch function(s) */ diff --git a/libs/libarchfpga/src/physical_types.h b/libs/libarchfpga/src/physical_types.h index c00d65bfb41..6b6f721239f 100644 --- a/libs/libarchfpga/src/physical_types.h +++ b/libs/libarchfpga/src/physical_types.h @@ -175,11 +175,18 @@ enum e_side : unsigned char { RIGHT = 1, BOTTOM = 2, LEFT = 3, - NUM_SIDES + NUM_SIDES = 4, + ABOVE = 5, + UNDER = 6, + NUM_OF_TOTAL_SIDES, }; + constexpr std::array SIDES = {{TOP, RIGHT, BOTTOM, LEFT}}; //Set of all side orientations constexpr std::array SIDE_STRING = {{"TOP", "RIGHT", "BOTTOM", "LEFT"}}; //String versions of side orientations +constexpr std::array TOTAL_SIDES = {{TOP, RIGHT, BOTTOM, LEFT, ABOVE, UNDER}}; //Set of all side orientations including different layers +constexpr std::array TOTAL_SIDE_STRING = {{"TOP", "RIGHT", "BOTTOM", "LEFT", "ABOVE", "UNDER"}}; //String versions of side orientations including different layers + /* pin location distributions */ enum e_pin_location_distr { E_SPREAD_PIN_DISTR, diff --git a/vtr_flow/arch/multi_die/stratixiv_arch.timing.xml b/vtr_flow/arch/multi_die/stratixiv_arch.timing.xml index b1377f7f7c2..a3008d854df 100644 --- a/vtr_flow/arch/multi_die/stratixiv_arch.timing.xml +++ b/vtr_flow/arch/multi_die/stratixiv_arch.timing.xml @@ -48158,6 +48158,7 @@ + From a3393e99cef3ce63bf5a0d8e47619e396565b251 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Thu, 3 Aug 2023 19:28:59 -0400 Subject: [PATCH 02/83] refactor for loops with e_side as iterator to always use SIDES array --- libs/libarchfpga/src/parse_switchblocks.cpp | 4 ++-- libs/libarchfpga/src/read_fpga_interchange_arch.cpp | 2 +- libs/libarchfpga/src/read_xml_arch_file.cpp | 12 ++++++------ vpr/src/pack/post_routing_pb_pin_fixup.cpp | 2 +- vpr/src/route/build_switchblocks.cpp | 4 ++-- vpr/src/route/rr_graph2.cpp | 6 +++--- vpr/src/route/rr_graph_sbox.cpp | 4 ++-- vtr_flow/arch/multi_die/stratixiv_arch.timing.xml | 1 - 8 files changed, 17 insertions(+), 18 deletions(-) diff --git a/libs/libarchfpga/src/parse_switchblocks.cpp b/libs/libarchfpga/src/parse_switchblocks.cpp index deed2db5936..2d4fbe632eb 100644 --- a/libs/libarchfpga/src/parse_switchblocks.cpp +++ b/libs/libarchfpga/src/parse_switchblocks.cpp @@ -445,8 +445,8 @@ static void check_bidir_switchblock(const t_permutation_map* permutation_map) { SB_Side_Connection conn; /* iterate over all combinations of from_side -> to side */ - for (e_side from_side : {TOP, RIGHT, BOTTOM, LEFT}) { - for (e_side to_side : {TOP, RIGHT, BOTTOM, LEFT}) { + for (e_side from_side : SIDES) { + for (e_side to_side : SIDES) { /* can't connect a switchblock side to itself */ if (from_side == to_side) { continue; diff --git a/libs/libarchfpga/src/read_fpga_interchange_arch.cpp b/libs/libarchfpga/src/read_fpga_interchange_arch.cpp index 02dfe536746..3842e729539 100644 --- a/libs/libarchfpga/src/read_fpga_interchange_arch.cpp +++ b/libs/libarchfpga/src/read_fpga_interchange_arch.cpp @@ -475,7 +475,7 @@ struct ArchReader { type.pin_height_offset.resize(type.num_pins, 0); type.pinloc.resize({1, 1, 4}, std::vector(type.num_pins, false)); - for (e_side side : {TOP, RIGHT, BOTTOM, LEFT}) { + for (e_side side : SIDES) { for (int pin = 0; pin < type.num_pins; pin++) { type.pinloc[0][0][side][pin] = true; type.pin_width_offset[pin] = 0; diff --git a/libs/libarchfpga/src/read_xml_arch_file.cpp b/libs/libarchfpga/src/read_xml_arch_file.cpp index fa605911698..61b5963b30c 100644 --- a/libs/libarchfpga/src/read_xml_arch_file.cpp +++ b/libs/libarchfpga/src/read_xml_arch_file.cpp @@ -501,7 +501,7 @@ static void LoadPinLoc(pugi::xml_node Locations, int num_sides = 4 * (type->width * type->height); int side_index = 0; int count = 0; - for (e_side side : {TOP, RIGHT, BOTTOM, LEFT}) { + for (e_side side : SIDES) { for (int width = 0; width < type->width; ++width) { for (int height = 0; height < type->height; ++height) { for (int pin_offset = 0; pin_offset < (type->num_pins / num_sides) + 1; ++pin_offset) { @@ -526,7 +526,7 @@ static void LoadPinLoc(pugi::xml_node Locations, while (ipin < type->num_pins) { for (int width = 0; width < type->width; ++width) { for (int height = 0; height < type->height; ++height) { - for (e_side side : {TOP, RIGHT, BOTTOM, LEFT}) { + for (e_side side : SIDES) { if (((width == 0 && side == LEFT) || (height == type->height - 1 && side == TOP) || (width == type->width - 1 && side == RIGHT) @@ -567,7 +567,7 @@ static void LoadPinLoc(pugi::xml_node Locations, while (ipin < input_pins.size()) { for (int width = 0; width < type->width; ++width) { for (int height = 0; height < type->height; ++height) { - for (e_side side : {TOP, RIGHT, BOTTOM, LEFT}) { + for (e_side side : SIDES) { if (ipin < input_pins.size()) { //Pins still to allocate @@ -590,7 +590,7 @@ static void LoadPinLoc(pugi::xml_node Locations, while (ipin < output_pins.size()) { for (int width = 0; width < type->width; ++width) { for (int height = 0; height < type->height; ++height) { - for (e_side side : {TOP, RIGHT, BOTTOM, LEFT}) { + for (e_side side : SIDES) { if (((width == 0 && side == LEFT) || (height == type->height - 1 && side == TOP) || (width == type->width - 1 && side == RIGHT) @@ -621,7 +621,7 @@ static void LoadPinLoc(pugi::xml_node Locations, for (int layer = 0; layer < num_of_avail_layer; ++layer) { for (int width = 0; width < type->width; ++width) { for (int height = 0; height < type->height; ++height) { - for (e_side side : {TOP, RIGHT, BOTTOM, LEFT}) { + for (e_side side : SIDES) { for (auto token : pin_locs->assignments[sub_tile_index][width][height][layer][side]) { auto pin_range = ProcessPinString(Locations, &sub_tile, @@ -3398,7 +3398,7 @@ static void ProcessPinLocations(pugi::xml_node Locations, for (int l = 0; l < num_of_avail_layer; ++l) { for (int w = 0; w < PhysicalTileType->width; ++w) { for (int h = 0; h < PhysicalTileType->height; ++h) { - for (e_side side : {TOP, RIGHT, BOTTOM, LEFT}) { + for (e_side side : SIDES) { for (auto token : pin_locs->assignments[sub_tile_index][w][h][l][side]) { InstPort inst_port(token.c_str()); diff --git a/vpr/src/pack/post_routing_pb_pin_fixup.cpp b/vpr/src/pack/post_routing_pb_pin_fixup.cpp index ceb9263e12b..b1c8d21d829 100644 --- a/vpr/src/pack/post_routing_pb_pin_fixup.cpp +++ b/vpr/src/pack/post_routing_pb_pin_fixup.cpp @@ -107,7 +107,7 @@ static void update_cluster_pin_with_post_routing_results(const Netlist<>& net_li * Deposit all the sides */ if (wanted_sides.empty()) { - for (e_side side : {TOP, BOTTOM, LEFT, RIGHT}) { + for (e_side side : SIDES) { wanted_sides.push_back(side); } } diff --git a/vpr/src/route/build_switchblocks.cpp b/vpr/src/route/build_switchblocks.cpp index 3e9f8386312..66f6201c5aa 100644 --- a/vpr/src/route/build_switchblocks.cpp +++ b/vpr/src/route/build_switchblocks.cpp @@ -331,8 +331,8 @@ t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_detail continue; } /* now we iterate over all the potential side1->side2 connections */ - for (e_side from_side : {TOP, RIGHT, BOTTOM, LEFT}) { - for (e_side to_side : {TOP, RIGHT, BOTTOM, LEFT}) { + for (e_side from_side : SIDES) { + for (e_side to_side : 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, from_side, to_side, diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index 48cc553f44b..0c80697cc1b 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -1202,7 +1202,7 @@ static void load_block_rr_indices(RRGraphBuilder& rr_graph_builder, * Deposit all the sides */ if (wanted_sides.empty()) { - for (e_side side : {TOP, BOTTOM, LEFT, RIGHT}) { + for (e_side side : SIDES) { wanted_sides.push_back(side); } } @@ -2419,7 +2419,7 @@ void load_sblock_pattern_lookup(const int i, int num_wire_muxes[NUM_SIDES]; /* "Label" the wires around the switch block by connectivity. */ - for (e_side side : {TOP, RIGHT, BOTTOM, LEFT}) { + for (e_side side : SIDES) { /* Assume the channel segment doesn't exist. */ wire_mux_on_track[side].clear(); incoming_wire_label[side].clear(); @@ -2493,7 +2493,7 @@ void load_sblock_pattern_lookup(const int i, false, wire_mux_on_track[side], &num_wire_muxes[side], &dummy); } - for (e_side to_side : {TOP, RIGHT, BOTTOM, LEFT}) { + for (e_side to_side : SIDES) { /* Can't do anything if no muxes on this side. */ if (num_wire_muxes[to_side] == 0) continue; diff --git a/vpr/src/route/rr_graph_sbox.cpp b/vpr/src/route/rr_graph_sbox.cpp index 22a4db0c4be..cba5a04e4e0 100644 --- a/vpr/src/route/rr_graph_sbox.cpp +++ b/vpr/src/route/rr_graph_sbox.cpp @@ -40,8 +40,8 @@ vtr::NdMatrix, 3> alloc_and_load_switch_block_conn(t_chan_width vtr::NdMatrix, 3> switch_block_conn({4, 4, (size_t)nodes_per_chan->max}); - for (e_side from_side : {TOP, RIGHT, BOTTOM, LEFT}) { - for (e_side to_side : {TOP, RIGHT, BOTTOM, LEFT}) { + for (e_side from_side : SIDES) { + for (e_side to_side : SIDES) { int from_chan_width = (from_side == TOP || from_side == BOTTOM) ? nodes_per_chan->y_max : nodes_per_chan->x_max; int to_chan_width = (to_side == TOP || to_side == BOTTOM) ? nodes_per_chan->y_max : nodes_per_chan->x_max; for (int from_track = 0; from_track < from_chan_width; from_track++) { diff --git a/vtr_flow/arch/multi_die/stratixiv_arch.timing.xml b/vtr_flow/arch/multi_die/stratixiv_arch.timing.xml index a3008d854df..b1377f7f7c2 100644 --- a/vtr_flow/arch/multi_die/stratixiv_arch.timing.xml +++ b/vtr_flow/arch/multi_die/stratixiv_arch.timing.xml @@ -48158,7 +48158,6 @@ - From 76f741925f518fb3809d9866e58dfcc5c85260d7 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Tue, 8 Aug 2023 10:20:27 -0400 Subject: [PATCH 03/83] refactor index_into_correct_chan for custom switchblocks --- vpr/src/route/build_switchblocks.cpp | 78 +++++++++++++++++----------- 1 file changed, 47 insertions(+), 31 deletions(-) diff --git a/vpr/src/route/build_switchblocks.cpp b/vpr/src/route/build_switchblocks.cpp index 66f6201c5aa..b67b5247cdf 100644 --- a/vpr/src/route/build_switchblocks.cpp +++ b/vpr/src/route/build_switchblocks.cpp @@ -253,10 +253,10 @@ static void get_switchpoint_wires( std::vector* output_wires, std::vector* scratch_wires); -static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, enum e_side side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int* chan_x, int* chan_y, t_rr_type* chan_type); +static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, int tile_layer, enum e_side side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int& chan_x, int& chan_y, int& chan_layer, t_rr_type& chan_type); /* checks whether the specified coordinates are out of bounds */ -static bool coords_out_of_bounds(const DeviceGrid& grid, int x_coord, int y_coord, e_rr_type chan_type); +static bool coords_out_of_bounds(const DeviceGrid& grid, int x_coord, int y_coord, e_rr_type chan_type, int layer_coord = 0); /* 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); @@ -331,8 +331,8 @@ t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_detail continue; } /* now we iterate over all the potential side1->side2 connections */ - for (e_side from_side : SIDES) { - for (e_side to_side : SIDES) { + for (e_side from_side : TOTAL_SIDES) { + for (e_side to_side : TOTAL_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, from_side, to_side, @@ -554,10 +554,12 @@ static void get_switchpoint_wires( /* Compute the wire(s) that the wire at (x, y, from_side, to_side) should connect to. * sb_conns is updated with the result */ static void compute_wire_connections(int x_coord, int y_coord, enum e_side from_side, enum e_side to_side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, t_switchblock_inf* sb, const DeviceGrid& grid, const t_wire_type_sizes* wire_type_sizes_x, const t_wire_type_sizes* wire_type_sizes_y, e_directionality directionality, t_sb_connection_map* sb_conns, vtr::RandState& rand_state, t_wireconn_scratchpad* scratchpad) { - int from_x, from_y; /* index into source channel */ - int to_x, to_y; /* index into destination channel */ + int from_x, from_y, from_layer; /* index into source channel */ + int to_x, to_y, to_layer; /* index into destination channel */ t_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 = UNDEFINED; + from_x = from_y = to_x = to_y = from_layer = to_layer = UNDEFINED; + //TODO: SM: this should be function argument coming from the callee + int layer_coord = 0; SB_Side_Connection side_conn(from_side, to_side); /* for indexing into this switchblock's permutation funcs */ Switchblock_Lookup sb_conn(x_coord, y_coord, from_side, to_side); /* for indexing into FPGA's switchblock map */ @@ -576,15 +578,15 @@ static void compute_wire_connections(int x_coord, int y_coord, enum e_side from_ * destination channels. also return the channel type (ie chanx/chany) into which we are * indexing */ /* details for source channel */ - const t_chan_details& from_chan_details = index_into_correct_chan(x_coord, y_coord, from_side, chan_details_x, chan_details_y, - &from_x, &from_y, &from_chan_type); + const t_chan_details& from_chan_details = index_into_correct_chan(x_coord, y_coord, layer_coord, from_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, to_side, chan_details_x, chan_details_y, - &to_x, &to_y, &to_chan_type); + const t_chan_details& to_chan_details = index_into_correct_chan(x_coord, y_coord, layer_coord, to_side, chan_details_x, chan_details_y, + to_x, to_y, to_layer, to_chan_type); /* make sure from_x/y and to_x/y aren't out of bounds */ - if (coords_out_of_bounds(grid, to_x, to_y, to_chan_type) || coords_out_of_bounds(grid, from_x, from_y, from_chan_type)) { + if (coords_out_of_bounds(grid, to_x, to_y, to_chan_type, to_layer) || coords_out_of_bounds(grid, from_x, from_y, from_chan_type, from_layer)) { return; } @@ -797,40 +799,48 @@ static int evaluate_num_conns_formula(t_wireconn_scratchpad* scratchpad, std::st /* Here we find the correct channel (x or y), and the coordinates to index into it based on the * specified tile coordinates and the switchblock side. Also returns the type of channel * that we are indexing into (ie, CHANX or CHANY */ -static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, enum e_side side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int* set_x, int* set_y, t_rr_type* chan_type) { - *chan_type = CHANX; +static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, int tile_layer, enum e_side side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int& chan_x, int& chan_y, int& chan_layer, t_rr_type& chan_type){ + chan_type = CHANX; + //TODO: SM: must figure out how each track is connected to next layer + chan_layer = tile_layer; /* here we use the VPR convention that a tile 'owns' the channels directly to the right * and above it */ switch (side) { case TOP: /* this is y-channel belonging to tile above */ - *set_x = tile_x; - *set_y = tile_y + 1; - *chan_type = CHANY; + chan_x = tile_x; + chan_y = tile_y + 1; + chan_type = CHANY; return chan_details_y; break; case RIGHT: /* this is x-channel belonging to tile to the right */ - *set_x = tile_x + 1; - *set_y = tile_y; - *chan_type = CHANX; + chan_x = tile_x + 1; + chan_y = tile_y; + chan_type = CHANX; return chan_details_x; break; case BOTTOM: /* this is y-channel on the right of the tile */ - *set_x = tile_x; - *set_y = tile_y; - *chan_type = CHANY; + chan_x = tile_x; + chan_y = tile_y; + chan_type = CHANY; return chan_details_y; break; case LEFT: /* this is x-channel on top of the tile */ - *set_x = tile_x; - *set_y = tile_y; - *chan_type = CHANX; + chan_x = tile_x; + chan_y = tile_y; + chan_type = CHANX; return chan_details_x; break; + case ABOVE: + VPR_FATAL_ERROR(VPR_ERROR_ARCH, "index_into_correct_chan: un-supported side specified: %d\n", side); + break; + case UNDER: + VPR_FATAL_ERROR(VPR_ERROR_ARCH, "index_into_correct_chan: un-supported side specified: %d\n", side); + break; default: VPR_FATAL_ERROR(VPR_ERROR_ARCH, "index_into_correct_chan: unknown side specified: %d\n", side); break; @@ -840,18 +850,24 @@ static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, enu } /* checks whether the specified coordinates are out of bounds */ -static bool coords_out_of_bounds(const DeviceGrid& grid, int x_coord, int y_coord, e_rr_type chan_type) { - bool result = true; +static bool coords_out_of_bounds(const DeviceGrid& grid, int x_coord, int y_coord, e_rr_type chan_type, int layer_coord) { + bool result = false; + + /* the layer that channel is located at must be legal regardless of chan_type*/ + if(layer_coord < 0 || layer_coord > grid.get_num_layers()){ + return result; + } if (CHANX == chan_type) { - if (x_coord <= 0 || x_coord >= int(grid.width()) - 1 || /* there is no x-channel at x=0 */ - y_coord < 0 || y_coord >= int(grid.height()) - 1) { + /* 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 (CHANY == chan_type) { - if (x_coord < 0 || x_coord >= int(grid.width()) - 1 || y_coord <= 0 || y_coord >= int(grid.height()) - 1) { /* there is no y-channel at y=0 */ + /* 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; From 4ff0ed627f4730a3338ca99746b9111fa2ed46ae Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Tue, 8 Aug 2023 10:23:17 -0400 Subject: [PATCH 04/83] make format --- libs/libarchfpga/src/parse_switchblocks.cpp | 30 ++++++++++----------- libs/libarchfpga/src/physical_types.h | 2 +- vpr/src/route/build_switchblocks.cpp | 8 +++--- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/libs/libarchfpga/src/parse_switchblocks.cpp b/libs/libarchfpga/src/parse_switchblocks.cpp index 2d4fbe632eb..eacf7e98b76 100644 --- a/libs/libarchfpga/src/parse_switchblocks.cpp +++ b/libs/libarchfpga/src/parse_switchblocks.cpp @@ -66,7 +66,7 @@ static void parse_comma_separated_wire_points(const char* ch, std::vectorpermutation_map[conn]); diff --git a/libs/libarchfpga/src/physical_types.h b/libs/libarchfpga/src/physical_types.h index 6b6f721239f..a1d89cf0b57 100644 --- a/libs/libarchfpga/src/physical_types.h +++ b/libs/libarchfpga/src/physical_types.h @@ -184,7 +184,7 @@ enum e_side : unsigned char { constexpr std::array SIDES = {{TOP, RIGHT, BOTTOM, LEFT}}; //Set of all side orientations constexpr std::array SIDE_STRING = {{"TOP", "RIGHT", "BOTTOM", "LEFT"}}; //String versions of side orientations -constexpr std::array TOTAL_SIDES = {{TOP, RIGHT, BOTTOM, LEFT, ABOVE, UNDER}}; //Set of all side orientations including different layers +constexpr std::array TOTAL_SIDES = {{TOP, RIGHT, BOTTOM, LEFT, ABOVE, UNDER}}; //Set of all side orientations including different layers constexpr std::array TOTAL_SIDE_STRING = {{"TOP", "RIGHT", "BOTTOM", "LEFT", "ABOVE", "UNDER"}}; //String versions of side orientations including different layers /* pin location distributions */ diff --git a/vpr/src/route/build_switchblocks.cpp b/vpr/src/route/build_switchblocks.cpp index b67b5247cdf..66a271a7b6c 100644 --- a/vpr/src/route/build_switchblocks.cpp +++ b/vpr/src/route/build_switchblocks.cpp @@ -554,8 +554,8 @@ static void get_switchpoint_wires( /* Compute the wire(s) that the wire at (x, y, from_side, to_side) should connect to. * sb_conns is updated with the result */ static void compute_wire_connections(int x_coord, int y_coord, enum e_side from_side, enum e_side to_side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, t_switchblock_inf* sb, const DeviceGrid& grid, const t_wire_type_sizes* wire_type_sizes_x, const t_wire_type_sizes* wire_type_sizes_y, e_directionality directionality, t_sb_connection_map* sb_conns, vtr::RandState& rand_state, 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 */ + int from_x, from_y, from_layer; /* index into source channel */ + int to_x, to_y, to_layer; /* index into destination channel */ t_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; //TODO: SM: this should be function argument coming from the callee @@ -799,7 +799,7 @@ static int evaluate_num_conns_formula(t_wireconn_scratchpad* scratchpad, std::st /* Here we find the correct channel (x or y), and the coordinates to index into it based on the * specified tile coordinates and the switchblock side. Also returns the type of channel * that we are indexing into (ie, CHANX or CHANY */ -static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, int tile_layer, enum e_side side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int& chan_x, int& chan_y, int& chan_layer, t_rr_type& chan_type){ +static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, int tile_layer, enum e_side side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int& chan_x, int& chan_y, int& chan_layer, t_rr_type& chan_type) { chan_type = CHANX; //TODO: SM: must figure out how each track is connected to next layer chan_layer = tile_layer; @@ -854,7 +854,7 @@ static bool coords_out_of_bounds(const DeviceGrid& grid, int x_coord, int y_coor bool result = false; /* the layer that channel is located at must be legal regardless of chan_type*/ - if(layer_coord < 0 || layer_coord > grid.get_num_layers()){ + if (layer_coord < 0 || layer_coord > grid.get_num_layers()) { return result; } From 81155d5e6c7ba7f189178e43a91af693e8979dea Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Tue, 8 Aug 2023 11:11:44 -0400 Subject: [PATCH 05/83] removed the update that will change rr_graph for 2d cases --- vpr/src/route/build_switchblocks.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/vpr/src/route/build_switchblocks.cpp b/vpr/src/route/build_switchblocks.cpp index 66a271a7b6c..e07cac6be47 100644 --- a/vpr/src/route/build_switchblocks.cpp +++ b/vpr/src/route/build_switchblocks.cpp @@ -331,8 +331,9 @@ t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_detail continue; } /* now we iterate over all the potential side1->side2 connections */ - for (e_side from_side : TOTAL_SIDES) { - for (e_side to_side : TOTAL_SIDES) { + //TODO: SM: this must change to TOTAL_SIDES INSTEAD OF SIDES + for (e_side from_side : SIDES) { + for (e_side to_side : 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, from_side, to_side, From 2b93973540e8bf09ef3af2a4c359e326d5a637bc Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Tue, 8 Aug 2023 11:39:45 -0400 Subject: [PATCH 06/83] modified the functions to determine custom switch blocks locations based on layer number --- vpr/src/route/build_switchblocks.cpp | 81 ++++++++++++++++++---------- vpr/src/route/build_switchblocks.h | 2 +- vpr/src/route/rr_graph.cpp | 4 +- 3 files changed, 58 insertions(+), 29 deletions(-) diff --git a/vpr/src/route/build_switchblocks.cpp b/vpr/src/route/build_switchblocks.cpp index e07cac6be47..7e98d95638a 100644 --- a/vpr/src/route/build_switchblocks.cpp +++ b/vpr/src/route/build_switchblocks.cpp @@ -268,16 +268,19 @@ int get_wire_segment_length(const DeviceGrid& grid, e_rr_type chan_type, const t 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); /* returns true if the coordinates x/y do not correspond to the location specified by 'location' */ -static bool sb_not_here(const DeviceGrid& grid, int x, int y, e_sb_location location); +static bool sb_not_here(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer, e_sb_location location); /* checks if the specified coordinates represent a corner of the FPGA */ -static bool is_corner(const DeviceGrid& grid, int x, int y); +static bool is_corner(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer); /* checks if the specified coordinates correspond to one of the perimeter switchblocks */ -static bool is_perimeter(const DeviceGrid& grid, int x, int y); +static bool is_perimeter(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer); /* checks if the specified coordinates correspond to the core of the FPGA (i.e. not perimeter) */ -static bool is_core(const DeviceGrid& grid, int x, int y); +static bool is_core(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer); + +/* checks if the specified layer has programmable routing resources described in the architecture file */ +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); @@ -287,6 +290,7 @@ static int adjust_formula_result(int dest_wire, int src_W, int dest_W, int conne t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, const DeviceGrid& grid, + const std::vector& inter_cluster_rr, std::vector switchblocks, t_chan_width* nodes_per_chan, e_directionality directionality, @@ -325,20 +329,23 @@ 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 coordinates spanning the FPGA. */ - 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, x_coord, y_coord, sb.location)) { - continue; - } - /* now we iterate over all the potential side1->side2 connections */ - //TODO: SM: this must change to TOTAL_SIDES INSTEAD OF SIDES - for (e_side from_side : SIDES) { - for (e_side to_side : 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, from_side, to_side, - chan_details_x, chan_details_y, &sb, grid, - &wire_type_sizes_x, &wire_type_sizes_y, directionality, sb_conns, rand_state, &scratchpad); + 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.location)) { + continue; + } + /* now we iterate over all the potential side1->side2 connections */ + //TODO: SM: this must change to TOTAL_SIDES INSTEAD OF SIDES + for (e_side from_side: SIDES) { + for (e_side to_side: 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, from_side, to_side, + chan_details_x, chan_details_y, &sb, grid, + &wire_type_sizes_x, &wire_type_sizes_y, directionality, sb_conns, + rand_state, &scratchpad); + } } } } @@ -363,7 +370,7 @@ void free_switchblock_permutations(t_sb_connection_map* sb_conns) { } /* returns true if the coordinates x/y do not correspond to the location specified by 'location' */ -static bool sb_not_here(const DeviceGrid& grid, int x, int y, e_sb_location location) { +static bool sb_not_here(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer, e_sb_location location) { bool sb_not_here = true; switch (location) { @@ -371,22 +378,22 @@ static bool sb_not_here(const DeviceGrid& grid, int x, int y, e_sb_location loca sb_not_here = false; break; case E_PERIMETER: - if (is_perimeter(grid, x, y)) { + if (is_perimeter(grid, inter_cluster_rr, x, y, layer)) { sb_not_here = false; } break; case E_CORNER: - if (is_corner(grid, x, y)) { + if (is_corner(grid, inter_cluster_rr, x, y, layer)) { sb_not_here = false; } break; case E_CORE: - if (is_core(grid, x, y)) { + if (is_core(grid,inter_cluster_rr, x, y, layer)) { sb_not_here = false; } break; case E_FRINGE: - if (is_perimeter(grid, x, y) && !is_corner(grid, x, y)) { + if (is_perimeter(grid, inter_cluster_rr, x, y, layer) && !is_corner(grid, inter_cluster_rr, x, y, layer)) { sb_not_here = false; } break; @@ -398,7 +405,10 @@ static bool sb_not_here(const DeviceGrid& grid, int x, int y, e_sb_location loca } /* checks if the specified coordinates represent a corner of the FPGA */ -static bool is_corner(const DeviceGrid& grid, int x, int y) { +static bool is_corner(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 @@ -409,7 +419,10 @@ static bool is_corner(const DeviceGrid& grid, int x, int y) { } /* checks if the specified coordinates correspond to one of the perimeter switchblocks */ -static bool is_perimeter(const DeviceGrid& grid, int x, int y) { +static bool is_perimeter(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; @@ -418,11 +431,25 @@ static bool is_perimeter(const DeviceGrid& grid, int x, int y) { } /* checks if the specified coordinates correspond to the core of the FPGA (i.e. not perimeter) */ -static bool is_core(const DeviceGrid& grid, int x, int y) { - bool is_core = !is_perimeter(grid, x, y); +static bool is_core(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(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; +} + /* Counts the number of wires in each wire type in the specified channel */ static void count_wire_type_sizes(const t_chan_seg_details* channel, int nodes_per_chan, t_wire_type_sizes* wire_type_sizes) { vtr::string_view wire_type; diff --git a/vpr/src/route/build_switchblocks.h b/vpr/src/route/build_switchblocks.h index 68e60da3824..df8decc23c3 100644 --- a/vpr/src/route/build_switchblocks.h +++ b/vpr/src/route/build_switchblocks.h @@ -84,7 +84,7 @@ typedef std::unordered_map, /************ Functions ************/ /* allocate and build switch block permutation map */ -t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, const DeviceGrid& grid, std::vector switchblocks, t_chan_width* nodes_per_chan, enum e_directionality directionality, vtr::RandState& rand_state); +t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, const DeviceGrid& grid, const std::vector& inter_cluster_rr, std::vector switchblocks, t_chan_width* nodes_per_chan, enum e_directionality directionality, vtr::RandState& rand_state); /* deallocates switch block connections sparse array */ void free_switchblock_permutations(t_sb_connection_map* sb_conns); diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index a046361c926..37d941d4a1c 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -1200,13 +1200,14 @@ static void build_rr_graph(const t_graph_type graph_type, //is deterministic -- always producing the same RR graph. constexpr unsigned SWITCHPOINT_RNG_SEED = 1; vtr::RandState switchpoint_rand_state = SWITCHPOINT_RNG_SEED; + const auto 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); } else if (BI_DIRECTIONAL == directionality) { if (sb_type == CUSTOM) { sb_conn_map = alloc_and_load_switchblock_permutations(chan_details_x, chan_details_y, - grid, + grid, inter_cluster_prog_rr, switchblocks, &nodes_per_chan, directionality, switchpoint_rand_state); } else { @@ -1218,6 +1219,7 @@ static void build_rr_graph(const t_graph_type graph_type, if (sb_type == CUSTOM) { sb_conn_map = alloc_and_load_switchblock_permutations(chan_details_x, chan_details_y, grid, + inter_cluster_prog_rr, switchblocks, &nodes_per_chan, directionality, switchpoint_rand_state); } else { From 17beb305a075a11b085c6ac5e5cd342056ceb469 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Tue, 8 Aug 2023 16:39:12 -0400 Subject: [PATCH 07/83] modified index_into_correct_chan to consider layers to index to the correct chan --- vpr/src/route/build_switchblocks.cpp | 44 ++++++++++++++++++---------- vpr/src/route/build_switchblocks.h | 20 +++++++++---- 2 files changed, 43 insertions(+), 21 deletions(-) diff --git a/vpr/src/route/build_switchblocks.cpp b/vpr/src/route/build_switchblocks.cpp index 7e98d95638a..406d7a995cd 100644 --- a/vpr/src/route/build_switchblocks.cpp +++ b/vpr/src/route/build_switchblocks.cpp @@ -201,6 +201,7 @@ static void count_wire_type_sizes(const t_chan_seg_details* channel, int nodes_p static void compute_wire_connections( int x_coord, int y_coord, + int layer_coord, enum e_side from_side, enum e_side to_side, const t_chan_details& chan_details_x, @@ -223,8 +224,10 @@ static void compute_wireconn_connections( Switchblock_Lookup sb_conn, int from_x, int from_y, + int from_layer, int to_x, int to_y, + int to_layer, t_rr_type from_chan_type, t_rr_type to_chan_type, const t_wire_type_sizes* wire_type_sizes_x, @@ -341,7 +344,7 @@ t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_detail for (e_side to_side: 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, from_side, to_side, + 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, rand_state, &scratchpad); @@ -579,18 +582,16 @@ static void get_switchpoint_wires( } } -/* Compute the wire(s) that the wire at (x, y, from_side, to_side) should connect to. +/* Compute the wire(s) that the wire at (x, y, layer, from_side, to_side) should connect to. * sb_conns is updated with the result */ -static void compute_wire_connections(int x_coord, int y_coord, enum e_side from_side, enum e_side to_side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, t_switchblock_inf* sb, const DeviceGrid& grid, const t_wire_type_sizes* wire_type_sizes_x, const t_wire_type_sizes* wire_type_sizes_y, e_directionality directionality, t_sb_connection_map* sb_conns, vtr::RandState& rand_state, t_wireconn_scratchpad* scratchpad) { +static void compute_wire_connections(int x_coord, int y_coord, int layer_coord, enum e_side from_side, enum e_side to_side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, 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::RandState& rand_state, 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 */ t_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; - //TODO: SM: this should be function argument coming from the callee - int layer_coord = 0; SB_Side_Connection side_conn(from_side, to_side); /* for indexing into this switchblock's permutation funcs */ - Switchblock_Lookup sb_conn(x_coord, y_coord, from_side, to_side); /* for indexing into FPGA's switchblock map */ + Switchblock_Lookup sb_conn(x_coord, y_coord, layer_coord, from_side, to_side); /* for indexing into FPGA's switchblock map */ /* can't connect a switchblock side to itself */ if (from_side == to_side) { @@ -634,7 +635,7 @@ static void compute_wire_connections(int x_coord, int y_coord, enum e_side from_ /* compute the destination wire segments to which the source wire segment should connect based on the * current wireconn */ compute_wireconn_connections(grid, directionality, from_chan_details, to_chan_details, - sb_conn, from_x, from_y, to_x, to_y, from_chan_type, to_chan_type, wire_type_sizes_from, + sb_conn, from_x, from_y, from_layer, to_x, to_y, to_layer, from_chan_type, to_chan_type, wire_type_sizes_from, wire_type_sizes_to, sb, wireconn_ptr, sb_conns, rand_state, scratchpad); } @@ -653,8 +654,10 @@ static void compute_wireconn_connections( Switchblock_Lookup sb_conn, int from_x, int from_y, + int from_layer, int to_x, int to_y, + int to_layer, t_rr_type from_chan_type, t_rr_type to_chan_type, const t_wire_type_sizes* wire_type_sizes_from, @@ -788,7 +791,7 @@ static void compute_wireconn_connections( sb_edge.from_wire = from_wire; sb_edge.to_wire = to_wire; - // if the switch override has been set, use that. Otherwise use default + // if the switch override has been set, use that, Otherwise use default if (wireconn_ptr->switch_override_indx != DEFAULT_SWITCH) { sb_edge.switch_ind = wireconn_ptr->switch_override_indx; } else { @@ -805,9 +808,9 @@ static void compute_wireconn_connections( std::swap(sb_reverse_edge.from_wire, sb_reverse_edge.to_wire); //Since we are implementing the reverse connection we have swapped from and to. // - //Coverity flags this (false positive), so annotatate so coverity ignores it: + //Coverity flags this (false positive), so annotate coverity ignores it: // coverity[swapped_arguments : Intentional] - Switchblock_Lookup sb_conn_reverse(sb_conn.x_coord, sb_conn.y_coord, sb_conn.to_side, sb_conn.from_side); + Switchblock_Lookup sb_conn_reverse(sb_conn.x_coord, sb_conn.y_coord, sb_conn.layer_coord, sb_conn.to_side, sb_conn.from_side); (*sb_conns)[sb_conn_reverse].push_back(sb_reverse_edge); } } @@ -829,9 +832,6 @@ static int evaluate_num_conns_formula(t_wireconn_scratchpad* scratchpad, std::st * that we are indexing into (ie, CHANX or CHANY */ static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, int tile_layer, enum e_side side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int& chan_x, int& chan_y, int& chan_layer, t_rr_type& chan_type) { chan_type = CHANX; - //TODO: SM: must figure out how each track is connected to next layer - chan_layer = tile_layer; - /* here we use the VPR convention that a tile 'owns' the channels directly to the right * and above it */ switch (side) { @@ -839,6 +839,7 @@ static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, int /* this is y-channel belonging to tile above */ chan_x = tile_x; chan_y = tile_y + 1; + chan_layer = tile_layer; chan_type = CHANY; return chan_details_y; break; @@ -846,6 +847,7 @@ static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, int /* this is x-channel belonging to tile to the right */ chan_x = tile_x + 1; chan_y = tile_y; + chan_layer = tile_layer; chan_type = CHANX; return chan_details_x; break; @@ -854,6 +856,7 @@ static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, int chan_x = tile_x; chan_y = tile_y; chan_type = CHANY; + chan_layer = tile_layer; return chan_details_y; break; case LEFT: @@ -861,13 +864,24 @@ static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, int chan_x = tile_x; chan_y = tile_y; chan_type = CHANX; + chan_layer = tile_layer; return chan_details_x; break; case ABOVE: - VPR_FATAL_ERROR(VPR_ERROR_ARCH, "index_into_correct_chan: un-supported side specified: %d\n", side); + chan_x = tile_x; + chan_y = tile_y; + chan_layer = tile_layer + 1; + //TODO: SM : chanx or chany? + chan_type = CHANX; + return chan_details_x; break; case UNDER: - VPR_FATAL_ERROR(VPR_ERROR_ARCH, "index_into_correct_chan: un-supported side specified: %d\n", side); + chan_x = tile_x; + chan_y = tile_y; + chan_layer = tile_layer - 1; + //TODO: SM : chanx or chany? + chan_type = CHANX; + return chan_details_x; break; default: VPR_FATAL_ERROR(VPR_ERROR_ARCH, "index_into_correct_chan: unknown side specified: %d\n", side); diff --git a/vpr/src/route/build_switchblocks.h b/vpr/src/route/build_switchblocks.h index df8decc23c3..ac9b7680b1a 100644 --- a/vpr/src/route/build_switchblocks.h +++ b/vpr/src/route/build_switchblocks.h @@ -19,23 +19,30 @@ class Switchblock_Lookup { public: int x_coord; /* x coordinate of switchblock connection */ //TODO: redundant comment?? add range int y_coord; /* y coordinate of switchblock connection */ + int layer_coord; /* layer number of switchblock */ e_side from_side; /* source side of switchblock connection */ e_side to_side; /* destination side of switchblock connection */ /* Empty constructor initializes everything to 0 */ Switchblock_Lookup() { - x_coord = y_coord = -1; //TODO: use set function + x_coord = y_coord = layer_coord = -1; //TODO: use set function } /* Constructor for initializing member variables */ - Switchblock_Lookup(int set_x, int set_y, e_side set_from, e_side set_to) { - this->set_coords(set_x, set_y, set_from, set_to); //TODO: use set function + Switchblock_Lookup(int set_x, int set_y, int set_layer, e_side set_from, e_side set_to) { + this->set_coords(set_x, set_y, set_layer, set_from, set_to); //TODO: use set function + } + + /* Constructor for initializing member variables with default layer number (0), used for single die FPGA */ + Switchblock_Lookup(int set_x, int set_y, e_side set_from, e_side set_to){ + this->set_coords(set_x,set_y,0,set_from,set_to); } /* Function for setting the segment coordinates */ - void set_coords(int set_x, int set_y, e_side set_from, e_side set_to) { + void set_coords(int set_x, int set_y, int set_layer, e_side set_from, e_side set_to) { x_coord = set_x; y_coord = set_y; + layer_coord = set_layer; from_side = set_from; to_side = set_to; } @@ -44,7 +51,8 @@ class Switchblock_Lookup { bool operator==(const Switchblock_Lookup& obj) const { bool result; if (x_coord == obj.x_coord && y_coord == obj.y_coord - && from_side == obj.from_side && to_side == obj.to_side) { + && from_side == obj.from_side && to_side == obj.to_side + && layer_coord == obj.layer_coord) { result = true; } else { result = false; @@ -52,7 +60,7 @@ class Switchblock_Lookup { return result; } }; - +//TODO: SM: check if this require to include layer_coord struct t_hash_Switchblock_Lookup { size_t operator()(const Switchblock_Lookup& obj) const noexcept { //TODO: use vtr::hash_combine From 08cf7e9106ac35ca8d96200e12ce28db2b24bd79 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Thu, 10 Aug 2023 15:47:03 -0400 Subject: [PATCH 08/83] modified wireconnection parsing while using custom switchblocks with more than one layer --- vpr/src/route/build_switchblocks.cpp | 85 +++++++++++++++++++--------- vpr/src/route/build_switchblocks.h | 13 +++-- 2 files changed, 65 insertions(+), 33 deletions(-) diff --git a/vpr/src/route/build_switchblocks.cpp b/vpr/src/route/build_switchblocks.cpp index 406d7a995cd..ad13ab06931 100644 --- a/vpr/src/route/build_switchblocks.cpp +++ b/vpr/src/route/build_switchblocks.cpp @@ -283,7 +283,7 @@ static bool is_perimeter(const DeviceGrid& grid, const std::vector& inter_ static bool is_core(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer); /* checks if the specified layer has programmable routing resources described in the architecture file */ -static bool is_prog_routing_avail(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int layer); +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); @@ -331,8 +331,8 @@ t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_detail if (directionality != sb.directionality) { VPR_FATAL_ERROR(VPR_ERROR_ARCH, "alloc_and_load_switchblock_connections: Switchblock %s does not match directionality of architecture\n", sb.name.c_str()); } - /* Iterate over the x,y coordinates spanning the FPGA. */ - for(int layer_coord = 0; layer_coord < grid.get_num_layers(); layer_coord++) { + /* Iterate over the x,y, layer coordinates spanning the FPGA. */ + 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.location)) { @@ -340,8 +340,8 @@ t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_detail } /* now we iterate over all the potential side1->side2 connections */ //TODO: SM: this must change to TOTAL_SIDES INSTEAD OF SIDES - for (e_side from_side: SIDES) { - for (e_side to_side: SIDES) { + for (e_side from_side : TOTAL_SIDES) { + for (e_side to_side : TOTAL_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, @@ -391,7 +391,7 @@ static bool sb_not_here(const DeviceGrid& grid, const std::vector& inter_c } break; case E_CORE: - if (is_core(grid,inter_cluster_rr, x, y, layer)) { + if (is_core(grid, inter_cluster_rr, x, y, layer)) { sb_not_here = false; } break; @@ -409,7 +409,7 @@ static bool sb_not_here(const DeviceGrid& grid, const std::vector& inter_c /* checks if the specified coordinates represent a corner of the FPGA */ static bool is_corner(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)){ + if (!is_prog_routing_avail(grid, inter_cluster_rr, layer)) { return false; } bool is_corner = false; @@ -423,7 +423,7 @@ static bool is_corner(const DeviceGrid& grid, const std::vector& inter_clu /* checks if the specified coordinates correspond to one of the perimeter switchblocks */ static bool is_perimeter(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)){ + if (!is_prog_routing_avail(grid, inter_cluster_rr, layer)) { return false; } bool is_perimeter = false; @@ -435,19 +435,19 @@ static bool is_perimeter(const DeviceGrid& grid, const std::vector& inter_ /* checks if the specified coordinates correspond to the core of the FPGA (i.e. not perimeter) */ static bool is_core(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)){ + if (!is_prog_routing_avail(grid, inter_cluster_rr, layer)) { return false; } bool is_core = !is_perimeter(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){ +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)){ + if (!inter_cluster_rr.at(layer)) { is_prog_avail = false; } return is_prog_avail; @@ -590,7 +590,7 @@ static void compute_wire_connections(int x_coord, int y_coord, int layer_coord, t_rr_type from_chan_type, to_chan_type; /* the type of channel - i.e. CHANX or CHANY */ from_x = from_y = to_x = to_y = from_layer = to_layer = UNDEFINED; - SB_Side_Connection side_conn(from_side, to_side); /* for indexing into this switchblock's permutation funcs */ + SB_Side_Connection side_conn(from_side, to_side); /* for indexing into this switchblock's permutation funcs */ Switchblock_Lookup sb_conn(x_coord, y_coord, layer_coord, from_side, to_side); /* for indexing into FPGA's switchblock map */ /* can't connect a switchblock side to itself */ @@ -670,24 +670,45 @@ static void compute_wireconn_connections( constexpr bool verbose = false; /* 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, sb_conn.from_side, - wireconn_ptr->from_switchpoint_set, wire_type_sizes_from, false, wireconn_ptr->from_switchpoint_order, rand_state, - &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, sb_conn.to_side, - wireconn_ptr->to_switchpoint_set, wire_type_sizes_to, true, wireconn_ptr->to_switchpoint_order, rand_state, &scratchpad->potential_dest_wires, - &scratchpad->scratch_wires); + if (sb_conn.from_side == ABOVE || sb_conn.from_side == UNDER) { + for (e_side from_side : SIDES) { + get_switchpoint_wires(grid, + from_chan_details[from_x][from_y].data(), from_chan_type, from_x, from_y, from_side, + wireconn_ptr->from_switchpoint_set, wire_type_sizes_from, false, wireconn_ptr->from_switchpoint_order, rand_state, + &scratchpad->potential_src_wires, + &scratchpad->scratch_wires); + } + } else { + get_switchpoint_wires(grid, + from_chan_details[from_x][from_y].data(), from_chan_type, from_x, from_y, sb_conn.from_side, + wireconn_ptr->from_switchpoint_set, wire_type_sizes_from, false, wireconn_ptr->from_switchpoint_order, rand_state, + &scratchpad->potential_src_wires, + &scratchpad->scratch_wires); + } + if (sb_conn.to_side == ABOVE || sb_conn.to_side == UNDER) { + for (e_side to_side : SIDES) { + get_switchpoint_wires(grid, + to_chan_details[to_x][to_y].data(), to_chan_type, to_x, to_y, to_side, + wireconn_ptr->to_switchpoint_set, wire_type_sizes_to, true, + wireconn_ptr->to_switchpoint_order, rand_state, &scratchpad->potential_dest_wires, + &scratchpad->scratch_wires); + } + } else { + get_switchpoint_wires(grid, + to_chan_details[to_x][to_y].data(), to_chan_type, to_x, to_y, sb_conn.to_side, + wireconn_ptr->to_switchpoint_set, wire_type_sizes_to, true, + wireconn_ptr->to_switchpoint_order, rand_state, &scratchpad->potential_dest_wires, + &scratchpad->scratch_wires); + } const auto& potential_src_wires = scratchpad->potential_src_wires; const auto& potential_dest_wires = scratchpad->potential_dest_wires; +#if 0 VTR_LOGV(verbose, "SB_LOC: %d,%d %s->%s\n", sb_conn.x_coord, sb_conn.y_coord, SIDE_STRING[sb_conn.from_side], SIDE_STRING[sb_conn.to_side]); //Define to print out specific wire-switchpoints used in to/from sets, if verbose is set true -#if 0 + for (auto from_set : wireconn_ptr->from_switchpoint_set) { VTR_LOGV(verbose, " FROM_SET: %s @", from_set.segment_name.c_str()); for (int switchpoint : from_set.switchpoints) { @@ -752,13 +773,15 @@ static void compute_wireconn_connections( if (sb_conn.from_side == TOP || sb_conn.from_side == RIGHT) { continue; } - VTR_ASSERT(sb_conn.from_side == BOTTOM || sb_conn.from_side == LEFT); + //TODO: SM: should uncomment these + //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 */ if (sb_conn.from_side == BOTTOM || sb_conn.from_side == LEFT) { continue; } - VTR_ASSERT(sb_conn.from_side == TOP || sb_conn.from_side == RIGHT); + //TODO: SM: should uncomment these + //VTR_ASSERT(sb_conn.from_side == TOP || sb_conn.from_side == RIGHT); } else { VTR_ASSERT(from_wire_direction == Direction::BIDIR); } @@ -790,12 +813,18 @@ static void compute_wireconn_connections( 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; // if the switch override has been set, use that, Otherwise use default if (wireconn_ptr->switch_override_indx != DEFAULT_SWITCH) { sb_edge.switch_ind = wireconn_ptr->switch_override_indx; - } else { + } else if (from_layer == to_layer) { sb_edge.switch_ind = to_chan_details[to_x][to_y][to_wire].arch_wire_switch(); + } else { + VTR_ASSERT(from_layer != to_layer); + //TODO: SM: should figure out whether this is correct + sb_edge.switch_ind = to_chan_details[to_x][to_y][to_wire].arch_opin_between_dice_switch(); } VTR_LOGV(verbose, " make_conn: %d -> %d switch=%d\n", sb_edge.from_wire, sb_edge.to_wire, sb_edge.switch_ind); @@ -871,7 +900,7 @@ static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, int chan_x = tile_x; chan_y = tile_y; chan_layer = tile_layer + 1; - //TODO: SM : chanx or chany? + //TODO: SM : chanx or chany? should be both somehow chan_type = CHANX; return chan_details_x; break; @@ -879,7 +908,7 @@ static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, int chan_x = tile_x; chan_y = tile_y; chan_layer = tile_layer - 1; - //TODO: SM : chanx or chany? + //TODO: SM : chanx or chany? should be both somehow chan_type = CHANX; return chan_details_x; break; diff --git a/vpr/src/route/build_switchblocks.h b/vpr/src/route/build_switchblocks.h index ac9b7680b1a..5c91d7462be 100644 --- a/vpr/src/route/build_switchblocks.h +++ b/vpr/src/route/build_switchblocks.h @@ -34,8 +34,8 @@ class Switchblock_Lookup { } /* Constructor for initializing member variables with default layer number (0), used for single die FPGA */ - Switchblock_Lookup(int set_x, int set_y, e_side set_from, e_side set_to){ - this->set_coords(set_x,set_y,0,set_from,set_to); + Switchblock_Lookup(int set_x, int set_y, e_side set_from, e_side set_to) { + this->set_coords(set_x, set_y, 0, set_from, set_to); } /* Function for setting the segment coordinates */ @@ -60,15 +60,16 @@ class Switchblock_Lookup { return result; } }; -//TODO: SM: check if this require to include layer_coord + struct t_hash_Switchblock_Lookup { size_t operator()(const Switchblock_Lookup& obj) const noexcept { //TODO: use vtr::hash_combine size_t result; result = ((((std::hash()(obj.x_coord) ^ std::hash()(obj.y_coord) << 10) - ^ std::hash()((int)obj.from_side) << 20) - ^ std::hash()((int)obj.to_side) << 30)); + ^ std::hash()(obj.layer_coord << 20) + ^ std::hash()((int)obj.from_side) << 30) + ^ std::hash()((int)obj.to_side) << 40)); return result; } }; @@ -79,6 +80,8 @@ struct t_switchblock_edge { short from_wire; short to_wire; short switch_ind; + short from_wire_layer; + short to_wire_layer; }; /* Switchblock connections are made as [x][y][from_side][to_side][from_wire_ind]. From 92ebe0f1a2bc38f071d52c2f2e91402f0634a65d Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Tue, 15 Aug 2023 13:26:05 -0400 Subject: [PATCH 09/83] added edges to connect track to track in different layers, no additional nodes have been defined --- vpr/src/route/rr_graph2.cpp | 127 ++++++++++++++++++++++++++++++++++-- 1 file changed, 121 insertions(+), 6 deletions(-) diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index 0c80697cc1b..b16b09dc8b5 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -93,6 +93,23 @@ static int get_unidir_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, RRNodeId from_rr_node, t_rr_edge_info_set& rr_edges_to_create); +static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, + const int tile_x, + const int tile_y, + const int layer, + const e_side from_side, + const int from_wire, + RRNodeId from_rr_node, + const e_side to_side, + const int to_x, + const int to_y, + const t_rr_type to_chan_type, + const int switch_override, + t_sb_connection_map* sb_conn_map, + t_rr_edge_info_set& rr_edges_to_create, + int& edge_count); + + static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, const int layer, const int from_track, @@ -1713,7 +1730,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, int to_chan, to_sb; std::vector conn_tracks; bool from_is_sblock, is_behind, Fs_clipped; - enum e_side from_side_a, from_side_b, to_side; + enum e_side from_side_a, from_side_b, from_side_c, from_side_d, to_side; bool custom_switch_block; /* check whether a custom switch block will be used */ @@ -1752,7 +1769,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, //If source and destination segments both lie along the same channel //we clip the loop bounds to the switch blocks of interest and proceed //normally - if (to_type == from_type) { + if (to_type == from_type) { //TODO: SM: remove the comment (CHANX == CHANX OR CHANY == CHANY) start = to_seg - 1; end = to_seg; } @@ -2010,6 +2027,62 @@ static int get_bidir_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, return num_conn; } +static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, + const int tile_x, + const int tile_y, + const int layer, + const e_side from_side, + const int from_wire, + RRNodeId from_rr_node, + const e_side to_side, + const int to_x, + const int to_y, + const t_rr_type to_chan_type, + const int switch_override, + t_sb_connection_map* sb_conn_map, + t_rr_edge_info_set& rr_edges_to_create, + int& edge_count){ + + /* get coordinate to index into the SB map */ + Switchblock_Lookup sb_coord(tile_x, tile_y, layer, from_side, to_side); + if (sb_conn_map->count(sb_coord) > 0) { + /* get reference to the connections vector which lists all destination wires for a given source wire + * at a specific coordinate sb_coord */ + std::vector& conn_vector = (*sb_conn_map)[sb_coord]; + + /* go through the connections... */ + for (int iconn = 0; iconn < (int)conn_vector.size(); ++iconn) { + if (conn_vector.at(iconn).from_wire != from_wire) continue; + + int to_wire = conn_vector.at(iconn).to_wire; + RRNodeId to_node = rr_graph_builder.node_lookup().find_node(layer, to_x, to_y, to_chan_type, to_wire); + + if (!to_node) { + continue; + } + + /* Get the index of the switch connecting the two wires */ + int src_switch = conn_vector[iconn].switch_ind; + + //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; + + auto& device_ctx = g_vpr_ctx.device(); + + if (device_ctx.arch_switch_inf[src_switch].directionality() == BI_DIRECTIONAL) { + //Add reverse edge since bi-directional + rr_edges_to_create.emplace_back(to_node, from_rr_node, src_switch, false); + ++edge_count; + } + } + } +} + /* Figures out the edges that should connect the given wire segment to the given * channel segment, adds these edges to 'edge_list' and returns the number of * edges added . @@ -2047,8 +2120,9 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, } } - /* get coordinate to index into the SB map */ - Switchblock_Lookup sb_coord(tile_x, tile_y, from_side, to_side); +// get_switchblocks_edges(rr_graph_builder,tile_x,tile_y,layer,from_side,from_wire,from_rr_node,to_side,to_x,to_y,to_chan_type,switch_override,sb_conn_map,rr_edges_to_create,edge_count); + + Switchblock_Lookup sb_coord(tile_x, tile_y, layer, from_side, to_side); if (sb_conn_map->count(sb_coord) > 0) { /* get reference to the connections vector which lists all destination wires for a given source wire * at a specific coordinate sb_coord */ @@ -2084,9 +2158,50 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, ++edge_count; } } - } else { - /* specified sb_conn_map entry does not exist -- do nothing */ } + + //check sb_conn_map for connections between two layers + for(e_side to_another_die_side : {ABOVE,UNDER}){ + Switchblock_Lookup sb_coord_layer(tile_x, tile_y, layer, from_side, to_another_die_side); + if (sb_conn_map->count(sb_coord_layer) > 0) { + /* get reference to the connections vector which lists all destination wires for a given source wire + * at a specific coordinate sb_coord */ + std::vector& conn_vector = (*sb_conn_map)[sb_coord_layer]; + + /* go through the connections... */ + for (int iconn = 0; iconn < (int)conn_vector.size(); ++iconn) { + if (conn_vector.at(iconn).from_wire != from_wire) continue; + + int to_wire = conn_vector.at(iconn).to_wire; + int to_layer = conn_vector.at(iconn).to_wire_layer; + RRNodeId to_node = rr_graph_builder.node_lookup().find_node(to_layer, to_x, to_y, to_chan_type, to_wire); + + if (!to_node) { + continue; + } + + /* Get the index of the switch connecting the two wires */ + int src_switch = conn_vector[iconn].switch_ind; + + //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; + + auto& device_ctx = g_vpr_ctx.device(); + + if (device_ctx.arch_switch_inf[src_switch].directionality() == BI_DIRECTIONAL) { + //Add reverse edge since bi-directional + rr_edges_to_create.emplace_back(to_node, from_rr_node, src_switch, false); + ++edge_count; + } + } + } + } + return edge_count; } From f00977f17f3f0c94d775023e15c98ca15f98044a Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Tue, 15 Aug 2023 16:41:19 -0400 Subject: [PATCH 10/83] factor out the get_switchblocks_edges function and connect two layers for sb --- vpr/src/route/rr_graph2.cpp | 114 ++++++------------ .../arch/multi_die/stratixiv_arch.timing.xml | 1 + 2 files changed, 35 insertions(+), 80 deletions(-) diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index b16b09dc8b5..1256a50b77a 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -1730,7 +1730,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, int to_chan, to_sb; std::vector conn_tracks; bool from_is_sblock, is_behind, Fs_clipped; - enum e_side from_side_a, from_side_b, from_side_c, from_side_d, to_side; + enum e_side from_side_a, from_side_b, to_side; bool custom_switch_block; /* check whether a custom switch block will be used */ @@ -2055,7 +2055,9 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, if (conn_vector.at(iconn).from_wire != from_wire) continue; int to_wire = conn_vector.at(iconn).to_wire; - RRNodeId to_node = rr_graph_builder.node_lookup().find_node(layer, to_x, to_y, to_chan_type, to_wire); + int to_layer = conn_vector.at(iconn).to_wire_layer; + + RRNodeId to_node = rr_graph_builder.node_lookup().find_node(to_layer, to_x, to_y, to_chan_type, to_wire); if (!to_node) { continue; @@ -2120,88 +2122,40 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, } } -// get_switchblocks_edges(rr_graph_builder,tile_x,tile_y,layer,from_side,from_wire,from_rr_node,to_side,to_x,to_y,to_chan_type,switch_override,sb_conn_map,rr_edges_to_create,edge_count); - - Switchblock_Lookup sb_coord(tile_x, tile_y, layer, from_side, to_side); - if (sb_conn_map->count(sb_coord) > 0) { - /* get reference to the connections vector which lists all destination wires for a given source wire - * at a specific coordinate sb_coord */ - std::vector& conn_vector = (*sb_conn_map)[sb_coord]; - - /* go through the connections... */ - for (int iconn = 0; iconn < (int)conn_vector.size(); ++iconn) { - if (conn_vector.at(iconn).from_wire != from_wire) continue; - - int to_wire = conn_vector.at(iconn).to_wire; - RRNodeId to_node = rr_graph_builder.node_lookup().find_node(layer, to_x, to_y, to_chan_type, to_wire); - - if (!to_node) { - continue; - } - - /* Get the index of the switch connecting the two wires */ - int src_switch = conn_vector[iconn].switch_ind; - - //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; - - auto& device_ctx = g_vpr_ctx.device(); - - if (device_ctx.arch_switch_inf[src_switch].directionality() == BI_DIRECTIONAL) { - //Add reverse edge since bi-directional - rr_edges_to_create.emplace_back(to_node, from_rr_node, src_switch, false); - ++edge_count; - } - } - } + get_switchblocks_edges(rr_graph_builder, + tile_x, + tile_y, + layer, + from_side, + from_wire, + from_rr_node, + to_side, + to_x, + to_y, + to_chan_type, + switch_override, + sb_conn_map, + rr_edges_to_create, + edge_count); //check sb_conn_map for connections between two layers for(e_side to_another_die_side : {ABOVE,UNDER}){ - Switchblock_Lookup sb_coord_layer(tile_x, tile_y, layer, from_side, to_another_die_side); - if (sb_conn_map->count(sb_coord_layer) > 0) { - /* get reference to the connections vector which lists all destination wires for a given source wire - * at a specific coordinate sb_coord */ - std::vector& conn_vector = (*sb_conn_map)[sb_coord_layer]; - - /* go through the connections... */ - for (int iconn = 0; iconn < (int)conn_vector.size(); ++iconn) { - if (conn_vector.at(iconn).from_wire != from_wire) continue; - - int to_wire = conn_vector.at(iconn).to_wire; - int to_layer = conn_vector.at(iconn).to_wire_layer; - RRNodeId to_node = rr_graph_builder.node_lookup().find_node(to_layer, to_x, to_y, to_chan_type, to_wire); - - if (!to_node) { - continue; - } - - /* Get the index of the switch connecting the two wires */ - int src_switch = conn_vector[iconn].switch_ind; - - //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; - - auto& device_ctx = g_vpr_ctx.device(); - - if (device_ctx.arch_switch_inf[src_switch].directionality() == BI_DIRECTIONAL) { - //Add reverse edge since bi-directional - rr_edges_to_create.emplace_back(to_node, from_rr_node, src_switch, false); - ++edge_count; - } - } - } + 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, + sb_conn_map, + rr_edges_to_create, + edge_count); } - return edge_count; } diff --git a/vtr_flow/arch/multi_die/stratixiv_arch.timing.xml b/vtr_flow/arch/multi_die/stratixiv_arch.timing.xml index b1377f7f7c2..4241700bb4d 100644 --- a/vtr_flow/arch/multi_die/stratixiv_arch.timing.xml +++ b/vtr_flow/arch/multi_die/stratixiv_arch.timing.xml @@ -48159,6 +48159,7 @@ + From f31a5fa3f148c87c778b70390f733eacce49bb3a Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Tue, 15 Aug 2023 16:48:38 -0400 Subject: [PATCH 11/83] make format --- vpr/src/route/rr_graph2.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index 1256a50b77a..5f977a0d480 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -109,7 +109,6 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, t_rr_edge_info_set& rr_edges_to_create, int& edge_count); - static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, const int layer, const int from_track, @@ -2041,8 +2040,7 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, const int switch_override, t_sb_connection_map* sb_conn_map, t_rr_edge_info_set& rr_edges_to_create, - int& edge_count){ - + int& edge_count) { /* get coordinate to index into the SB map */ Switchblock_Lookup sb_coord(tile_x, tile_y, layer, from_side, to_side); if (sb_conn_map->count(sb_coord) > 0) { @@ -2139,7 +2137,7 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, edge_count); //check sb_conn_map for connections between two layers - for(e_side to_another_die_side : {ABOVE,UNDER}){ + for (e_side to_another_die_side : {ABOVE, UNDER}) { get_switchblocks_edges(rr_graph_builder, tile_x, tile_y, From 8cbfc30636d5f810e3a7c446a9b0e7bbd04d3540 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Thu, 17 Aug 2023 14:20:45 -0400 Subject: [PATCH 12/83] updated parsing custom switchblocks architecture syntax to connect both channel from one layer to another --- vpr/src/route/build_switchblocks.cpp | 128 +++++++++++++++------------ vpr/src/route/rr_graph2.cpp | 1 + 2 files changed, 73 insertions(+), 56 deletions(-) diff --git a/vpr/src/route/build_switchblocks.cpp b/vpr/src/route/build_switchblocks.cpp index ad13ab06931..f484c37c61e 100644 --- a/vpr/src/route/build_switchblocks.cpp +++ b/vpr/src/route/build_switchblocks.cpp @@ -256,7 +256,7 @@ static void get_switchpoint_wires( std::vector* output_wires, std::vector* scratch_wires); -static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, int tile_layer, enum e_side side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int& chan_x, int& chan_y, int& chan_layer, t_rr_type& chan_type); +static const std::vector index_into_correct_chan(int tile_x, int tile_y, int tile_layer, enum e_side side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int& chan_x, int& chan_y, int& chan_layer, std::vector& chan_type); /* checks whether the specified coordinates are out of bounds */ static bool coords_out_of_bounds(const DeviceGrid& grid, int x_coord, int y_coord, e_rr_type chan_type, int layer_coord = 0); @@ -587,7 +587,7 @@ static void get_switchpoint_wires( static void compute_wire_connections(int x_coord, int y_coord, int layer_coord, enum e_side from_side, enum e_side to_side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, t_switchblock_inf* sb, const DeviceGrid& grid, const t_wire_type_sizes* wire_type_sizes_x, const t_wire_type_sizes* wire_type_sizes_y, e_directionality directionality, t_sb_connection_map* sb_conns, vtr::RandState& rand_state, 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 */ - t_rr_type from_chan_type, to_chan_type; /* the type of channel - i.e. CHANX or CHANY */ + std::vector from_chan_type, to_chan_type; /* the type of channel - i.e. CHANX or CHANY */ from_x = from_y = to_x = to_y = from_layer = to_layer = UNDEFINED; SB_Side_Connection side_conn(from_side, to_side); /* for indexing into this switchblock's permutation funcs */ @@ -604,41 +604,49 @@ static void compute_wire_connections(int x_coord, int y_coord, int layer_coord, } /* find the correct channel, and the coordinates to index into it for both the source and - * destination channels. also return the channel type (ie chanx/chany) into which we are + * 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, chan_details_x, chan_details_y, + const std::vector from_chan_details = index_into_correct_chan(x_coord, y_coord, layer_coord, from_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, chan_details_x, chan_details_y, + const std::vector to_chan_details = index_into_correct_chan(x_coord, y_coord, layer_coord, to_side, chan_details_x, chan_details_y, to_x, to_y, to_layer, to_chan_type); - /* make sure from_x/y and to_x/y aren't out of bounds */ - if (coords_out_of_bounds(grid, to_x, to_y, to_chan_type, to_layer) || coords_out_of_bounds(grid, from_x, from_y, from_chan_type, from_layer)) { - return; - } + //check from/to_chan_details size matches the from/to_chan_type size + VTR_ASSERT(from_chan_details.size() == from_chan_type.size()); + VTR_ASSERT(to_chan_details.size() == to_chan_type.size()); - const t_wire_type_sizes* wire_type_sizes_from = wire_type_sizes_x; - const t_wire_type_sizes* wire_type_sizes_to = wire_type_sizes_x; - if (from_chan_type == CHANY) { - wire_type_sizes_from = wire_type_sizes_y; - } - if (to_chan_type == CHANY) { - wire_type_sizes_to = wire_type_sizes_y; - } - /* iterate over all the wire connections specified for this switch block */ - for (int iconn = 0; iconn < (int)sb->wireconns.size(); iconn++) { - /* pointer to a connection specification between wire types/subsegment_nums */ - t_wireconn_inf* wireconn_ptr = &sb->wireconns[iconn]; - - /* compute the destination wire segments to which the source wire segment should connect based on the - * current wireconn */ - compute_wireconn_connections(grid, directionality, from_chan_details, to_chan_details, - sb_conn, from_x, from_y, from_layer, to_x, to_y, to_layer, from_chan_type, to_chan_type, wire_type_sizes_from, - wire_type_sizes_to, sb, wireconn_ptr, sb_conns, rand_state, scratchpad); - } + for(size_t from_chan_index = 0; from_chan_index < from_chan_details.size(); from_chan_index++){ + for(size_t to_chan_index = 0; to_chan_index < to_chan_details.size(); to_chan_index++){ + /* 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_chan_type.at(to_chan_index), to_layer) || coords_out_of_bounds(grid, from_x, from_y, from_chan_type.at(from_chan_index), from_layer)) { + return; + } + const t_wire_type_sizes* wire_type_sizes_from = wire_type_sizes_x; + const t_wire_type_sizes* wire_type_sizes_to = wire_type_sizes_x; + if (from_chan_type.at(from_chan_index) == CHANY) { + wire_type_sizes_from = wire_type_sizes_y; + } + if (to_chan_type.at(to_chan_index) == CHANY) { + wire_type_sizes_to = wire_type_sizes_y; + } + + /* iterate over all the wire connections specified for this switch block */ + for (int iconn = 0; iconn < (int)sb->wireconns.size(); iconn++) { + /* pointer to a connection specification between wire types/subsegment_nums */ + t_wireconn_inf* wireconn_ptr = &sb->wireconns[iconn]; + + /* 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.at(from_chan_index), to_chan_details.at(to_chan_index), + sb_conn, from_x, from_y, from_layer, to_x, to_y, to_layer, from_chan_type.at(from_chan_index), to_chan_type.at(to_chan_index), wire_type_sizes_from, + wire_type_sizes_to, sb, wireconn_ptr, sb_conns, rand_state, scratchpad); + } + } + } return; } @@ -773,15 +781,13 @@ static void compute_wireconn_connections( if (sb_conn.from_side == TOP || sb_conn.from_side == RIGHT) { continue; } - //TODO: SM: should uncomment these - //VTR_ASSERT(sb_conn.from_side == BOTTOM || sb_conn.from_side == LEFT); + VTR_ASSERT(sb_conn.from_side == BOTTOM || sb_conn.from_side == LEFT || sb_conn.from_side == ABOVE || sb_conn.from_side == UNDER); } 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 */ if (sb_conn.from_side == BOTTOM || sb_conn.from_side == LEFT) { continue; } - //TODO: SM: should uncomment these - //VTR_ASSERT(sb_conn.from_side == TOP || sb_conn.from_side == RIGHT); + VTR_ASSERT(sb_conn.from_side == TOP || sb_conn.from_side == RIGHT || sb_conn.from_side == ABOVE || sb_conn.from_side == UNDER); } else { VTR_ASSERT(from_wire_direction == Direction::BIDIR); } @@ -856,68 +862,78 @@ static int evaluate_num_conns_formula(t_wireconn_scratchpad* scratchpad, std::st return scratchpad->formula_parser.parse_formula(num_conns_formula, vars); } -/* Here we find the correct channel (x or y), and the coordinates to index into it based on the - * specified tile coordinates and the switchblock side. Also returns the type of channel - * that we are indexing into (ie, CHANX or CHANY */ -static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, int tile_layer, enum e_side side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int& chan_x, int& chan_y, int& chan_layer, t_rr_type& chan_type) { - chan_type = CHANX; +/* Here we find the correct channel (x or y or both), and the coordinates to index into it based on the + * specified tile coordinates (x,y,layer) and the switchblock side. Also returns the type of channel + * that we are indexing into (ie, CHANX or CHANY) */ +static const std::vector index_into_correct_chan(int tile_x, int tile_y, int tile_layer, enum e_side side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int& chan_x, int& chan_y, int& chan_layer, std::vector& chan_type) { + std::vector chan_details; /* here we use the VPR convention that a tile 'owns' the channels directly to the right * and above it */ switch (side) { case TOP: - /* this is y-channel belonging to tile above */ + /* 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_type = CHANY; - return chan_details_y; + chan_type.push_back(CHANY); + chan_details.push_back(chan_details_y); + return chan_details; break; case RIGHT: - /* this is x-channel belonging to tile to the 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_type = CHANX; - return chan_details_x; + chan_type.push_back(CHANX); + chan_details.push_back(chan_details_x); + return chan_details; break; case BOTTOM: - /* this is y-channel on the right of the tile */ + /* this is y-channel on the right of the tile in the same layer */ chan_x = tile_x; chan_y = tile_y; - chan_type = CHANY; + chan_type.push_back(CHANY); chan_layer = tile_layer; - return chan_details_y; + chan_details.push_back(chan_details_y); + return chan_details; break; case LEFT: - /* this is x-channel on top of the tile */ + /* this is x-channel on top of the tile in the same layer*/ chan_x = tile_x; chan_y = tile_y; - chan_type = CHANX; + chan_type.push_back(CHANX); chan_layer = tile_layer; - return chan_details_x; + chan_details.push_back(chan_details_x); + return chan_details; 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; - //TODO: SM : chanx or chany? should be both somehow - chan_type = CHANX; - return chan_details_x; + chan_type.push_back(CHANX); + chan_type.push_back(CHANY); + chan_details.push_back(chan_details_x); + chan_details.push_back(chan_details_y); + return chan_details; 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; - //TODO: SM : chanx or chany? should be both somehow - chan_type = CHANX; - return chan_details_x; + chan_type.push_back(CHANX); + chan_type.push_back(CHANY); + chan_details.push_back(chan_details_x); + chan_details.push_back(chan_details_y); + return chan_details; break; default: VPR_FATAL_ERROR(VPR_ERROR_ARCH, "index_into_correct_chan: unknown side specified: %d\n", side); break; } VTR_ASSERT(false); - return chan_details_x; //Unreachable + return chan_details; //Unreachable, return empty vector } /* checks whether the specified coordinates are out of bounds */ diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index 5f977a0d480..dea7573d3f5 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -2041,6 +2041,7 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, t_sb_connection_map* sb_conn_map, t_rr_edge_info_set& rr_edges_to_create, int& edge_count) { + /* get coordinate to index into the SB map */ Switchblock_Lookup sb_coord(tile_x, tile_y, layer, from_side, to_side); if (sb_conn_map->count(sb_coord) > 0) { From 50fbfce14a13502f23d8819e7613bcb880669c0a Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Fri, 25 Aug 2023 17:37:59 -0400 Subject: [PATCH 13/83] add extra nodes (CHANX) in switchblocks with length = 0 --- libs/librrgraph/src/base/check_rr_graph.cpp | 3 +- libs/librrgraph/src/io/gen/rr_graph_uxsdcxx.h | 2 +- .../src/io/gen/rr_graph_uxsdcxx_interface.h | 2 +- .../src/io/rr_graph_uxsdcxx_serializer.h | 2 ++ .../librrgraph/src/utils/describe_rr_node.cpp | 1 - vpr/src/route/rr_graph.cpp | 30 +++++++++++++++++++ vpr/src/route/rr_graph2.cpp | 25 +++++++++++++++- vpr/src/route/rr_graph_timing_params.cpp | 2 +- 8 files changed, 61 insertions(+), 6 deletions(-) diff --git a/libs/librrgraph/src/base/check_rr_graph.cpp b/libs/librrgraph/src/base/check_rr_graph.cpp index 104e069af65..a0c1809b532 100644 --- a/libs/librrgraph/src/base/check_rr_graph.cpp +++ b/libs/librrgraph/src/base/check_rr_graph.cpp @@ -485,7 +485,8 @@ void check_rr_node(const RRGraphView& rr_graph, tracks_per_node = ((rr_type == CHANX) ? chan_width.x_list[ylow] : chan_width.y_list[xlow]); } - if (ptc_num >= nodes_per_chan) { + //todo: SM: we need to allow ptc_num equal to nodes_per_chan + if (ptc_num > nodes_per_chan) { VPR_ERROR(VPR_ERROR_ROUTE, "in check_rr_node: inode %d (type %d) has a ptc_num of %d.\n", inode, rr_type, ptc_num); } diff --git a/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx.h b/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx.h index 843aa582f12..ea4d65c51cb 100644 --- a/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx.h +++ b/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx.h @@ -1571,7 +1571,7 @@ template constexpr const char *lookup_switch_type[] = {"UXSD_INVALID", "mux", "tristate", "pass_gate", "short", "buffer"}; constexpr const char *lookup_pin_type[] = {"UXSD_INVALID", "OPEN", "OUTPUT", "INPUT"}; constexpr const char *lookup_node_type[] = {"UXSD_INVALID", "CHANX", "CHANY", "SOURCE", "SINK", "OPIN", "IPIN"}; -constexpr const char *lookup_node_direction[] = {"UXSD_INVALID", "INC_DIR", "DEC_DIR", "BI_DIR"}; +constexpr const char *lookup_node_direction[] = {"UXSD_INVALID", "INC_DIR", "DEC_DIR", "BI_DIR","NONE"}; constexpr const char *lookup_loc_side[] = {"UXSD_INVALID", "LEFT", "RIGHT", "TOP", "BOTTOM", "RIGHT_LEFT", "RIGHT_BOTTOM", "RIGHT_BOTTOM_LEFT", "TOP_RIGHT", "TOP_BOTTOM", "TOP_LEFT", "TOP_RIGHT_BOTTOM", "TOP_RIGHT_LEFT", "TOP_BOTTOM_LEFT", "TOP_RIGHT_BOTTOM_LEFT", "BOTTOM_LEFT"}; /* Lexers(string->token functions) for enums. */ 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 9a61c8cbe12..a998e483f8a 100644 --- a/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx_interface.h +++ b/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx_interface.h @@ -27,7 +27,7 @@ enum class enum_pin_type {UXSD_INVALID = 0, OPEN, OUTPUT, INPUT}; enum class enum_node_type {UXSD_INVALID = 0, CHANX, CHANY, SOURCE, SINK, OPIN, IPIN}; -enum class enum_node_direction {UXSD_INVALID = 0, INC_DIR, DEC_DIR, BI_DIR}; +enum class enum_node_direction {UXSD_INVALID = 0, INC_DIR, DEC_DIR, BI_DIR, NONE}; enum class enum_loc_side {UXSD_INVALID = 0, LEFT, RIGHT, TOP, BOTTOM, RIGHT_LEFT, RIGHT_BOTTOM, RIGHT_BOTTOM_LEFT, TOP_RIGHT, TOP_BOTTOM, TOP_LEFT, TOP_RIGHT_BOTTOM, TOP_RIGHT_LEFT, TOP_BOTTOM_LEFT, TOP_RIGHT_BOTTOM_LEFT, BOTTOM_LEFT}; diff --git a/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h b/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h index c0bfd38b7c6..604c84bb966 100644 --- a/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h +++ b/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h @@ -1837,6 +1837,8 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { return uxsd::enum_node_direction::DEC_DIR; case Direction::BIDIR: return uxsd::enum_node_direction::BI_DIR; + case Direction::NONE: + return uxsd::enum_node_direction::NONE; default: report_error( "Invalid direction %d", direction); diff --git a/libs/librrgraph/src/utils/describe_rr_node.cpp b/libs/librrgraph/src/utils/describe_rr_node.cpp index a4982cce8f7..6383e3489cc 100644 --- a/libs/librrgraph/src/utils/describe_rr_node.cpp +++ b/libs/librrgraph/src/utils/describe_rr_node.cpp @@ -11,7 +11,6 @@ std::string describe_rr_node(const RRGraphView& rr_graph, bool is_flat) { std::string msg = vtr::string_fmt("RR node: %d", inode); - if (rr_graph.node_type(inode) == CHANX || rr_graph.node_type(inode) == CHANY) { auto cost_index = rr_graph.node_cost_index(inode); diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index 37d941d4a1c..ddb5d46cd13 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -1068,6 +1068,14 @@ static void build_rr_graph(const t_graph_type graph_type, } /* END CHAN_DETAILS */ + /* START A SEG DETAIL WITH LENGTH 0 */ + //define a channel segment with length 0 to support 3d custom switchblocks + + t_chan_seg_details seg_detail_layer; + seg_detail_layer.set_length(0); + + /* END A SEG DETAILS WITH LENGTH 0 */ + /* START FC */ /* Determine the actual value of Fc */ std::vector> Fc_in; /* [0..device_ctx.num_block_types-1][0..num_pins-1][0..num_segments-1] */ @@ -3189,6 +3197,28 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, rr_graph_builder.set_node_track_num(node, track); rr_graph_builder.set_node_direction(node, seg_details[track].direction()); } + + //do everything else for newly added node + int track = tracks_per_chan; + RRNodeId node = rr_graph_builder.node_lookup().find_node(layer, x_coord, y_coord, CHANX, track); + if(node){ + rr_graph_builder.set_node_layer(node, layer); + rr_graph_builder.set_node_coordinates(node, x_coord, y_coord, x_coord, y_coord); + rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(cost_index_offset + seg_details[track-1].index())); + rr_graph_builder.set_node_capacity(node, 1); /* GLOBAL routing handled elsewhere */ +// int length = 0; +// float R = length * seg_details[track-1].Rmetal(); +// float C = length * seg_details[track-1].Cmetal(); + float R = 0; + float C = 0; + rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(R, C, mutable_device_ctx.rr_rc_data))); + + rr_graph_builder.set_node_type(node, CHANX); + rr_graph_builder.set_node_track_num(node, track); + rr_graph_builder.set_node_direction(node, Direction::NONE); + } + + } void uniquify_edges(t_rr_edge_info_set& rr_edges_to_create) { diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index dea7573d3f5..c7cc0550282 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -1103,8 +1103,18 @@ static void load_chan_rr_indices(const int max_chan_width, int y = (type == CHANX ? chan : seg); const t_chan_seg_details* seg_details = chan_details[x][y].data(); + /* + * Calculate how many nodes we need to reserve: + * In case of multi-die FPGAs, we add an extra node (can be either CHANX OR CHANY, used CHANX) to + * support inter-die communication from switch blocks (Meaning connection between two tracks in different layers) + * The extra node have the following attribute: + * 1) type = CHANX + * 2) length = 0 (xhigh = OPEN, yhigh = OPEN) + * 3) ptc = max_chanx_width + */ + int num_reserved_nodes = (grid.get_num_layers() > 1 && type == CHANX) ? max_chan_width +1 : max_chan_width; /* Reserve nodes in lookup to save memory */ - rr_graph_builder.node_lookup().reserve_nodes(layer, chan, seg, type, max_chan_width); + rr_graph_builder.node_lookup().reserve_nodes(layer, chan, seg, type, num_reserved_nodes); for (int track = 0; track < max_chan_width; ++track) { /* TODO: May let the length() == 0 case go through, to model muxes */ @@ -1132,11 +1142,23 @@ static void load_chan_rr_indices(const int max_chan_width, /* Assign inode of start of wire to current position */ rr_graph_builder.node_lookup().add_node(inode, layer, chan, seg, type, track); } + + if(type == CHANX) { + //add the extra node for multi-dice support + RRNodeId inode = rr_graph_builder.node_lookup().find_node(layer, y, x, CHANX, max_chan_width); + if (!inode) { + inode = RRNodeId(*index); + ++(*index); + rr_graph_builder.node_lookup().add_node(inode, layer, y, x, CHANX, max_chan_width); + } + } } } } } + + /* As the rr_indices builders modify a local copy of indices, use the local copy in the builder * TODO: these building functions should only talk to a RRGraphBuilder object */ @@ -1381,6 +1403,7 @@ void alloc_and_load_rr_node_indices(RRGraphBuilder& rr_graph_builder, CHANX, chan_details_x, rr_graph_builder, index); load_chan_rr_indices(nodes_per_chan->y_max, grid, grid.height(), grid.width(), CHANY, chan_details_y, rr_graph_builder, index); + } void alloc_and_load_intra_cluster_rr_node_indices(RRGraphBuilder& rr_graph_builder, diff --git a/vpr/src/route/rr_graph_timing_params.cpp b/vpr/src/route/rr_graph_timing_params.cpp index f89b8aba9a0..ae316cef2c7 100644 --- a/vpr/src/route/rr_graph_timing_params.cpp +++ b/vpr/src/route/rr_graph_timing_params.cpp @@ -58,7 +58,7 @@ void add_rr_graph_C_from_switches(float C_ipin_cblock) { from_rr_type = rr_graph.node_type(rr_id); - if (from_rr_type == CHANX || from_rr_type == CHANY) { + if ((from_rr_type == CHANX || from_rr_type == CHANY)) { for (t_edge_size iedge = 0; iedge < rr_graph.num_edges(rr_id); iedge++) { to_node = size_t(rr_graph.edge_sink_node(rr_id, iedge)); to_rr_type = rr_graph.node_type(RRNodeId(to_node)); From 4dac4a5b47bfd110fcf52a3177f272f8cc6611d3 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Fri, 25 Aug 2023 17:38:46 -0400 Subject: [PATCH 14/83] make format --- vpr/src/route/build_switchblocks.cpp | 12 ++++++------ vpr/src/route/rr_graph.cpp | 12 +++++------- vpr/src/route/rr_graph2.cpp | 8 ++------ 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/vpr/src/route/build_switchblocks.cpp b/vpr/src/route/build_switchblocks.cpp index f484c37c61e..7b1094f9c03 100644 --- a/vpr/src/route/build_switchblocks.cpp +++ b/vpr/src/route/build_switchblocks.cpp @@ -585,8 +585,8 @@ static void get_switchpoint_wires( /* Compute the wire(s) that the wire at (x, y, layer, from_side, to_side) should connect to. * sb_conns is updated with the result */ static void compute_wire_connections(int x_coord, int y_coord, int layer_coord, enum e_side from_side, enum e_side to_side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, t_switchblock_inf* sb, const DeviceGrid& grid, const t_wire_type_sizes* wire_type_sizes_x, const t_wire_type_sizes* wire_type_sizes_y, e_directionality directionality, t_sb_connection_map* sb_conns, vtr::RandState& rand_state, 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 */ + int from_x, from_y, from_layer; /* index into source channel */ + int to_x, to_y, to_layer; /* index into destination channel */ std::vector 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; @@ -608,18 +608,18 @@ static void compute_wire_connections(int x_coord, int y_coord, int layer_coord, * indexing */ /* details for source channel */ const std::vector from_chan_details = index_into_correct_chan(x_coord, y_coord, layer_coord, from_side, chan_details_x, chan_details_y, - from_x, from_y, from_layer, from_chan_type); + from_x, from_y, from_layer, from_chan_type); /* details for destination channel */ const std::vector to_chan_details = index_into_correct_chan(x_coord, y_coord, layer_coord, to_side, chan_details_x, chan_details_y, - to_x, to_y, to_layer, to_chan_type); + to_x, to_y, to_layer, to_chan_type); //check from/to_chan_details size matches the from/to_chan_type size VTR_ASSERT(from_chan_details.size() == from_chan_type.size()); VTR_ASSERT(to_chan_details.size() == to_chan_type.size()); - for(size_t from_chan_index = 0; from_chan_index < from_chan_details.size(); from_chan_index++){ - for(size_t to_chan_index = 0; to_chan_index < to_chan_details.size(); to_chan_index++){ + for (size_t from_chan_index = 0; from_chan_index < from_chan_details.size(); from_chan_index++) { + for (size_t to_chan_index = 0; to_chan_index < to_chan_details.size(); to_chan_index++) { /* 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_chan_type.at(to_chan_index), to_layer) || coords_out_of_bounds(grid, from_x, from_y, from_chan_type.at(from_chan_index), from_layer)) { return; diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index ddb5d46cd13..a68aa265653 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -3201,14 +3201,14 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, //do everything else for newly added node int track = tracks_per_chan; RRNodeId node = rr_graph_builder.node_lookup().find_node(layer, x_coord, y_coord, CHANX, track); - if(node){ + if (node) { rr_graph_builder.set_node_layer(node, layer); rr_graph_builder.set_node_coordinates(node, x_coord, y_coord, x_coord, y_coord); - rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(cost_index_offset + seg_details[track-1].index())); + rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(cost_index_offset + seg_details[track - 1].index())); rr_graph_builder.set_node_capacity(node, 1); /* GLOBAL routing handled elsewhere */ -// int length = 0; -// float R = length * seg_details[track-1].Rmetal(); -// float C = length * seg_details[track-1].Cmetal(); + // int length = 0; + // float R = length * seg_details[track-1].Rmetal(); + // float C = length * seg_details[track-1].Cmetal(); float R = 0; float C = 0; rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(R, C, mutable_device_ctx.rr_rc_data))); @@ -3217,8 +3217,6 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, rr_graph_builder.set_node_track_num(node, track); rr_graph_builder.set_node_direction(node, Direction::NONE); } - - } void uniquify_edges(t_rr_edge_info_set& rr_edges_to_create) { diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index c7cc0550282..1307668a372 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -1112,7 +1112,7 @@ static void load_chan_rr_indices(const int max_chan_width, * 2) length = 0 (xhigh = OPEN, yhigh = OPEN) * 3) ptc = max_chanx_width */ - int num_reserved_nodes = (grid.get_num_layers() > 1 && type == CHANX) ? max_chan_width +1 : max_chan_width; + int num_reserved_nodes = (grid.get_num_layers() > 1 && type == CHANX) ? max_chan_width + 1 : max_chan_width; /* Reserve nodes in lookup to save memory */ rr_graph_builder.node_lookup().reserve_nodes(layer, chan, seg, type, num_reserved_nodes); @@ -1143,7 +1143,7 @@ static void load_chan_rr_indices(const int max_chan_width, rr_graph_builder.node_lookup().add_node(inode, layer, chan, seg, type, track); } - if(type == CHANX) { + if (type == CHANX) { //add the extra node for multi-dice support RRNodeId inode = rr_graph_builder.node_lookup().find_node(layer, y, x, CHANX, max_chan_width); if (!inode) { @@ -1157,8 +1157,6 @@ static void load_chan_rr_indices(const int max_chan_width, } } - - /* As the rr_indices builders modify a local copy of indices, use the local copy in the builder * TODO: these building functions should only talk to a RRGraphBuilder object */ @@ -1403,7 +1401,6 @@ void alloc_and_load_rr_node_indices(RRGraphBuilder& rr_graph_builder, CHANX, chan_details_x, rr_graph_builder, index); load_chan_rr_indices(nodes_per_chan->y_max, grid, grid.height(), grid.width(), CHANY, chan_details_y, rr_graph_builder, index); - } void alloc_and_load_intra_cluster_rr_node_indices(RRGraphBuilder& rr_graph_builder, @@ -2064,7 +2061,6 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, t_sb_connection_map* sb_conn_map, t_rr_edge_info_set& rr_edges_to_create, int& edge_count) { - /* get coordinate to index into the SB map */ Switchblock_Lookup sb_coord(tile_x, tile_y, layer, from_side, to_side); if (sb_conn_map->count(sb_coord) > 0) { From 3939af13b1dae518031db041dc1987fb360dd8e4 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Thu, 31 Aug 2023 20:02:01 -0400 Subject: [PATCH 15/83] add extra nodes for track-to-track connections in rr graph --- vpr/src/route/rr_graph.cpp | 13 ++++--- vpr/src/route/rr_graph2.cpp | 68 ++++++++++++++++++++++++++++--------- vpr/src/route/rr_graph2.h | 6 ++++ 3 files changed, 67 insertions(+), 20 deletions(-) diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index a68aa265653..82b3d9b2722 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -1251,6 +1251,11 @@ static void build_rr_graph(const t_graph_type graph_type, } /* END SB LOOKUP */ + /* Add extra nodes to switch blocks for multi-layer FPGAs with custom switch blocks that define track-to_track connections */ + if(grid.get_num_layers() > 1 && sb_type == CUSTOM){ + alloc_and_load_inter_die_rr_node_indices(device_ctx.rr_graph_builder, &nodes_per_chan, grid, sb_conn_map, &num_rr_nodes); + } + /* START IPIN MAP */ /* Create ipin map lookups */ @@ -3204,11 +3209,11 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, if (node) { rr_graph_builder.set_node_layer(node, layer); rr_graph_builder.set_node_coordinates(node, x_coord, y_coord, x_coord, y_coord); - rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(cost_index_offset + seg_details[track - 1].index())); + rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(CHANX_COST_INDEX_START + seg_details[track - 1].index())); rr_graph_builder.set_node_capacity(node, 1); /* GLOBAL routing handled elsewhere */ - // int length = 0; - // float R = length * seg_details[track-1].Rmetal(); - // float C = length * seg_details[track-1].Cmetal(); + // int length = 0; + // float R = length * seg_details[track-1].Rmetal(); + // float C = length * seg_details[track-1].Cmetal(); float R = 0; float C = 0; rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(R, C, mutable_device_ctx.rr_rc_data))); diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index 1307668a372..5b9c9853cb3 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -1103,18 +1103,8 @@ static void load_chan_rr_indices(const int max_chan_width, int y = (type == CHANX ? chan : seg); const t_chan_seg_details* seg_details = chan_details[x][y].data(); - /* - * Calculate how many nodes we need to reserve: - * In case of multi-die FPGAs, we add an extra node (can be either CHANX OR CHANY, used CHANX) to - * support inter-die communication from switch blocks (Meaning connection between two tracks in different layers) - * The extra node have the following attribute: - * 1) type = CHANX - * 2) length = 0 (xhigh = OPEN, yhigh = OPEN) - * 3) ptc = max_chanx_width - */ - int num_reserved_nodes = (grid.get_num_layers() > 1 && type == CHANX) ? max_chan_width + 1 : max_chan_width; /* Reserve nodes in lookup to save memory */ - rr_graph_builder.node_lookup().reserve_nodes(layer, chan, seg, type, num_reserved_nodes); + rr_graph_builder.node_lookup().reserve_nodes(layer, chan, seg, type, max_chan_width); for (int track = 0; track < max_chan_width; ++track) { /* TODO: May let the length() == 0 case go through, to model muxes */ @@ -1142,14 +1132,60 @@ static void load_chan_rr_indices(const int max_chan_width, /* Assign inode of start of wire to current position */ rr_graph_builder.node_lookup().add_node(inode, layer, chan, seg, type, track); } + } + } + } +} - if (type == CHANX) { - //add the extra node for multi-dice support - RRNodeId inode = rr_graph_builder.node_lookup().find_node(layer, y, x, CHANX, max_chan_width); - if (!inode) { +void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, + const t_chan_width* nodes_per_chan, + const DeviceGrid& grid, + const t_sb_connection_map* sb_conn_map, + int* index){ + /* + * Calculate how many nodes we need to reserve: + * In case of multi-die FPGAs, we add extra nodes (can be either CHANX OR CHANY, used CHANX) to + * support inter-die communication from switch blocks (Meaning connection between two tracks in different layers) + * The extra nodes have the following attribute: + * 1) type = CHANX + * 2) length = 0 (xhigh = OPEN, yhigh = OPEN) + * 3) ptc = [max_chanx_width:max_chanx_width+number_of_connection] + */ + + auto& device_ctx = g_vpr_ctx.device(); + + for(int layer = 0; layer < grid.get_num_layers(); layer++){ + /* Skip the current die if architecture file specifies that it doesn't require global resource routing */ + if (!device_ctx.inter_cluster_prog_routing_resources.at(layer)) { + continue; + } + for (int y = 0; y < grid.height() - 1; ++y) { + for (int x = 1; x < grid.width() - 1; ++x) { + //count how many track-to-track connection go from current layer to other layers + int conn_count = 0; + for(auto from_side : TOTAL_SIDES){ + for(auto to_side : TOTAL_SIDES){ + if(int(from_side) < NUM_SIDES && int(to_side) < NUM_SIDES){ //this connection can not cross any layer + continue; + } + if(from_side == to_side){ //no connection + continue; + } + + Switchblock_Lookup sb_coord(x, y, layer, from_side, to_side); + if(sb_conn_map->count(sb_coord) > 0){ + conn_count += sb_conn_map->size(); + } + } + } + //reserve extra nodes for inter-die track-to-track connection + rr_graph_builder.node_lookup().reserve_nodes(layer,x,y,CHANX,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,y,x,CHANX,nodes_per_chan->max + rr_node_offset); + if(!inode){ inode = RRNodeId(*index); ++(*index); - rr_graph_builder.node_lookup().add_node(inode, layer, y, x, CHANX, max_chan_width); + rr_graph_builder.node_lookup().add_node(inode,layer,y,x,CHANX,nodes_per_chan->max + rr_node_offset); } } } diff --git a/vpr/src/route/rr_graph2.h b/vpr/src/route/rr_graph2.h index b1651f6ccda..7c299fe56ae 100644 --- a/vpr/src/route/rr_graph2.h +++ b/vpr/src/route/rr_graph2.h @@ -29,6 +29,12 @@ void alloc_and_load_rr_node_indices(RRGraphBuilder& rr_graph_builder, const t_chan_details& chan_details_y, bool is_flat); +void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, + const t_chan_width* nodes_per_chan, + const DeviceGrid& grid, + const t_sb_connection_map* sb_conn_map, + int* index); + void alloc_and_load_tile_rr_node_indices(RRGraphBuilder& rr_graph_builder, t_physical_tile_type_ptr physical_tile, int layer, From 15be4953b8f1ba159e2c325784105e6cbf6c368c Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Thu, 31 Aug 2023 20:32:55 -0400 Subject: [PATCH 16/83] set node attributes for custom extra nodes added to rrgraph to support custom switch blocks --- vpr/src/route/rr_graph.cpp | 75 +++++++++++++++++++++++++++---------- vpr/src/route/rr_graph2.cpp | 46 ++++++++++++++--------- vpr/src/route/rr_graph2.h | 7 ++++ 3 files changed, 90 insertions(+), 38 deletions(-) diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index 82b3d9b2722..0c103c7dcb0 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -463,8 +463,8 @@ static std::unordered_set get_chain_pins(std::vector chai static void build_rr_chan(RRGraphBuilder& rr_graph_builder, const int layer, - const int i, - const int j, + const int x_coord, + const int y_coord, const t_rr_type chan_type, const t_track_to_pin_lookup& track_to_pin_lookup, t_sb_connection_map* sb_conn_map, @@ -482,6 +482,16 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, const int wire_to_pin_between_dice_switch, const enum e_directionality directionality); +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 t_sb_connection_map* sb_conn_map, + const int const_index_offset, + const t_chan_width& nodes_per_chan, + const t_chan_details& chan_details_x, + const DeviceGrid& grid); + void uniquify_edges(t_rr_edge_info_set& rr_edges_to_create); void alloc_and_load_edges(RRGraphBuilder& rr_graph_builder, @@ -1252,7 +1262,7 @@ static void build_rr_graph(const t_graph_type graph_type, /* END SB LOOKUP */ /* Add extra nodes to switch blocks for multi-layer FPGAs with custom switch blocks that define track-to_track connections */ - if(grid.get_num_layers() > 1 && sb_type == CUSTOM){ + if(grid.get_num_layers() > 1 && sb_type == CUSTOM){ alloc_and_load_inter_die_rr_node_indices(device_ctx.rr_graph_builder, &nodes_per_chan, grid, sb_conn_map, &num_rr_nodes); } @@ -2148,6 +2158,14 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder rr_edges_to_create.clear(); } + + //In multi-die FPGAs with track-to-track connection between layers, we need to load newly added CHANX nodes + 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()); + build_inter_die_custom_sb_rr_chan(rr_graph_builder, layer, i, j, sb_conn_map, CHANX_COST_INDEX_START, chan_width, chan_details_x, grid); + } + } } } @@ -3202,25 +3220,42 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, rr_graph_builder.set_node_track_num(node, track); rr_graph_builder.set_node_direction(node, seg_details[track].direction()); } +} - //do everything else for newly added node - int track = tracks_per_chan; - RRNodeId node = rr_graph_builder.node_lookup().find_node(layer, x_coord, y_coord, CHANX, track); - if (node) { - rr_graph_builder.set_node_layer(node, layer); - rr_graph_builder.set_node_coordinates(node, x_coord, y_coord, x_coord, y_coord); - rr_graph_builder.set_node_cost_index(node, RRIndexedDataId(CHANX_COST_INDEX_START + seg_details[track - 1].index())); - rr_graph_builder.set_node_capacity(node, 1); /* GLOBAL routing handled elsewhere */ - // int length = 0; - // float R = length * seg_details[track-1].Rmetal(); - // float C = length * seg_details[track-1].Cmetal(); - float R = 0; - float C = 0; - rr_graph_builder.set_node_rc_index(node, NodeRCIndex(find_create_rr_rc_data(R, C, mutable_device_ctx.rr_rc_data))); +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 t_sb_connection_map* sb_conn_map, + const int const_index_offset, + const t_chan_width& nodes_per_chan, + const t_chan_details& chan_details_x, + const DeviceGrid& grid){ - rr_graph_builder.set_node_type(node, CHANX); - rr_graph_builder.set_node_track_num(node, track); - rr_graph_builder.set_node_direction(node, Direction::NONE); + auto& mutable_device_ctx = g_vpr_ctx.mutable_device(); + const t_chan_seg_details* seg_details = chan_details_x[x_coord][y_coord].data(); + + /* Loads up all the extra routing resource nodes required to support multi-die custom switch blocks */ + int start_track = nodes_per_chan.max; + int conn_count = get_number_track_to_track_conn_from_layer(layer,x_coord,y_coord,sb_conn_map); + + for(int offset = 0; offset < conn_count; offset++) { + RRNodeId node = rr_graph_builder.node_lookup().find_node(layer, x_coord, y_coord, CHANX, start_track + offset); + if (node) { + rr_graph_builder.set_node_layer(node, layer); + rr_graph_builder.set_node_coordinates(node, x_coord, y_coord, x_coord, y_coord); + rr_graph_builder.set_node_cost_index(node, RRIndexedDataId( + const_index_offset + seg_details[start_track - 1].index())); + rr_graph_builder.set_node_capacity(node, 1); /* GLOBAL routing handled elsewhere */ + float R = 0; + float C = 0; + rr_graph_builder.set_node_rc_index(node, NodeRCIndex( + find_create_rr_rc_data(R, C, mutable_device_ctx.rr_rc_data))); + + rr_graph_builder.set_node_type(node, CHANX); + rr_graph_builder.set_node_track_num(node, start_track + offset); + rr_graph_builder.set_node_direction(node, Direction::NONE); + } } } diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index 5b9c9853cb3..58260d24075 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -1137,18 +1137,42 @@ static void load_chan_rr_indices(const int max_chan_width, } } +int get_number_track_to_track_conn_from_layer(const int layer, + const int x, + const int y, + const t_sb_connection_map* sb_conn_map){ + int conn_count = 0; + for(auto from_side : TOTAL_SIDES){ + for(auto to_side : TOTAL_SIDES){ + if(int(from_side) < NUM_SIDES && int(to_side) < NUM_SIDES){ //this connection can not cross any layer + continue; + } + if(from_side == to_side){ //no connection + continue; + } + + Switchblock_Lookup sb_coord(x, y, layer, from_side, to_side); + if(sb_conn_map->count(sb_coord) > 0){ + conn_count += sb_conn_map->size(); + } + } + } + + return conn_count; +} + + void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, const t_chan_width* nodes_per_chan, const DeviceGrid& grid, const t_sb_connection_map* sb_conn_map, int* index){ /* - * Calculate how many nodes we need to reserve: * In case of multi-die FPGAs, we add extra nodes (can be either CHANX OR CHANY, used CHANX) to - * support inter-die communication from switch blocks (Meaning connection between two tracks in different layers) + * support inter-die communication coming from switch blocks (connection between two tracks in different layers) * The extra nodes have the following attribute: * 1) type = CHANX - * 2) length = 0 (xhigh = OPEN, yhigh = OPEN) + * 2) length = 0 (xhigh = xlow, yhigh = ylow) * 3) ptc = [max_chanx_width:max_chanx_width+number_of_connection] */ @@ -1162,22 +1186,8 @@ void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, for (int y = 0; y < grid.height() - 1; ++y) { for (int x = 1; x < grid.width() - 1; ++x) { //count how many track-to-track connection go from current layer to other layers - int conn_count = 0; - for(auto from_side : TOTAL_SIDES){ - for(auto to_side : TOTAL_SIDES){ - if(int(from_side) < NUM_SIDES && int(to_side) < NUM_SIDES){ //this connection can not cross any layer - continue; - } - if(from_side == to_side){ //no connection - continue; - } + int conn_count = get_number_track_to_track_conn_from_layer(layer, x, y, sb_conn_map); - Switchblock_Lookup sb_coord(x, y, layer, from_side, to_side); - if(sb_conn_map->count(sb_coord) > 0){ - conn_count += sb_conn_map->size(); - } - } - } //reserve extra nodes for inter-die track-to-track connection rr_graph_builder.node_lookup().reserve_nodes(layer,x,y,CHANX,conn_count); for(int rr_node_offset = 0; rr_node_offset < conn_count; rr_node_offset++){ diff --git a/vpr/src/route/rr_graph2.h b/vpr/src/route/rr_graph2.h index 7c299fe56ae..718b7a82867 100644 --- a/vpr/src/route/rr_graph2.h +++ b/vpr/src/route/rr_graph2.h @@ -69,6 +69,13 @@ int get_rr_node_index(const t_rr_node_indices& L_rr_node_indices, int ptc, e_side side = NUM_SIDES); +//Return how many connection inside switch blocks located at (layer,x,y) are going to a different layer +int get_number_track_to_track_conn_from_layer(const int layer, + const int x, + const int y, + const t_sb_connection_map* sb_conn_map); + + int find_average_rr_node_index(int device_width, int device_height, t_rr_type rr_type, From e71b4a572974706a74528d58e059af5182c015bb Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Thu, 31 Aug 2023 20:33:36 -0400 Subject: [PATCH 17/83] make format --- vpr/src/route/rr_graph.cpp | 16 +++++++--------- vpr/src/route/rr_graph2.cpp | 27 +++++++++++++-------------- vpr/src/route/rr_graph2.h | 1 - 3 files changed, 20 insertions(+), 24 deletions(-) diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index 0c103c7dcb0..e44bb0f82ea 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -1262,7 +1262,7 @@ static void build_rr_graph(const t_graph_type graph_type, /* END SB LOOKUP */ /* Add extra nodes to switch blocks for multi-layer FPGAs with custom switch blocks that define track-to_track connections */ - if(grid.get_num_layers() > 1 && sb_type == CUSTOM){ + if (grid.get_num_layers() > 1 && sb_type == CUSTOM) { alloc_and_load_inter_die_rr_node_indices(device_ctx.rr_graph_builder, &nodes_per_chan, grid, sb_conn_map, &num_rr_nodes); } @@ -2160,12 +2160,11 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder } //In multi-die FPGAs with track-to-track connection between layers, we need to load newly added CHANX nodes - if(grid.get_num_layers() > 1 && sb_conn_map != nullptr){ + 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()); build_inter_die_custom_sb_rr_chan(rr_graph_builder, layer, i, j, sb_conn_map, CHANX_COST_INDEX_START, chan_width, chan_details_x, grid); } - } } } @@ -3230,27 +3229,26 @@ static void build_inter_die_custom_sb_rr_chan(RRGraphBuilder& rr_graph_builder, const int const_index_offset, const t_chan_width& nodes_per_chan, const t_chan_details& chan_details_x, - const DeviceGrid& grid){ - + const DeviceGrid& grid) { auto& mutable_device_ctx = g_vpr_ctx.mutable_device(); const t_chan_seg_details* seg_details = chan_details_x[x_coord][y_coord].data(); /* Loads up all the extra routing resource nodes required to support multi-die custom switch blocks */ int start_track = nodes_per_chan.max; - int conn_count = get_number_track_to_track_conn_from_layer(layer,x_coord,y_coord,sb_conn_map); + int conn_count = get_number_track_to_track_conn_from_layer(layer, x_coord, y_coord, sb_conn_map); - for(int offset = 0; offset < conn_count; offset++) { + for (int offset = 0; offset < conn_count; offset++) { RRNodeId node = rr_graph_builder.node_lookup().find_node(layer, x_coord, y_coord, CHANX, start_track + offset); if (node) { rr_graph_builder.set_node_layer(node, layer); rr_graph_builder.set_node_coordinates(node, x_coord, y_coord, x_coord, y_coord); rr_graph_builder.set_node_cost_index(node, RRIndexedDataId( - const_index_offset + seg_details[start_track - 1].index())); + const_index_offset + seg_details[start_track - 1].index())); rr_graph_builder.set_node_capacity(node, 1); /* GLOBAL routing handled elsewhere */ float R = 0; float C = 0; rr_graph_builder.set_node_rc_index(node, NodeRCIndex( - find_create_rr_rc_data(R, C, mutable_device_ctx.rr_rc_data))); + find_create_rr_rc_data(R, C, mutable_device_ctx.rr_rc_data))); rr_graph_builder.set_node_type(node, CHANX); rr_graph_builder.set_node_track_num(node, start_track + offset); diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index 58260d24075..7a55c899d9c 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -1140,19 +1140,19 @@ static void load_chan_rr_indices(const int max_chan_width, int get_number_track_to_track_conn_from_layer(const int layer, const int x, const int y, - const t_sb_connection_map* sb_conn_map){ + const t_sb_connection_map* sb_conn_map) { int conn_count = 0; - for(auto from_side : TOTAL_SIDES){ - for(auto to_side : TOTAL_SIDES){ - if(int(from_side) < NUM_SIDES && int(to_side) < NUM_SIDES){ //this connection can not cross any layer + for (auto from_side : TOTAL_SIDES) { + for (auto to_side : TOTAL_SIDES) { + if (int(from_side) < NUM_SIDES && int(to_side) < NUM_SIDES) { //this connection can not cross any layer continue; } - if(from_side == to_side){ //no connection + if (from_side == to_side) { //no connection continue; } Switchblock_Lookup sb_coord(x, y, layer, from_side, to_side); - if(sb_conn_map->count(sb_coord) > 0){ + if (sb_conn_map->count(sb_coord) > 0) { conn_count += sb_conn_map->size(); } } @@ -1161,12 +1161,11 @@ int get_number_track_to_track_conn_from_layer(const int layer, return conn_count; } - void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, const t_chan_width* nodes_per_chan, const DeviceGrid& grid, const t_sb_connection_map* sb_conn_map, - int* index){ + int* index) { /* * In case of multi-die FPGAs, we add extra nodes (can be either CHANX OR CHANY, used CHANX) to * support inter-die communication coming from switch blocks (connection between two tracks in different layers) @@ -1178,7 +1177,7 @@ void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, auto& device_ctx = g_vpr_ctx.device(); - for(int layer = 0; layer < grid.get_num_layers(); layer++){ + for (int layer = 0; layer < grid.get_num_layers(); layer++) { /* Skip the current die if architecture file specifies that it doesn't require global resource routing */ if (!device_ctx.inter_cluster_prog_routing_resources.at(layer)) { continue; @@ -1189,13 +1188,13 @@ void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, int conn_count = get_number_track_to_track_conn_from_layer(layer, x, y, sb_conn_map); //reserve extra nodes for inter-die track-to-track connection - rr_graph_builder.node_lookup().reserve_nodes(layer,x,y,CHANX,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,y,x,CHANX,nodes_per_chan->max + rr_node_offset); - if(!inode){ + rr_graph_builder.node_lookup().reserve_nodes(layer, x, y, CHANX, 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, y, x, CHANX, nodes_per_chan->max + rr_node_offset); + if (!inode) { inode = RRNodeId(*index); ++(*index); - rr_graph_builder.node_lookup().add_node(inode,layer,y,x,CHANX,nodes_per_chan->max + rr_node_offset); + rr_graph_builder.node_lookup().add_node(inode, layer, y, x, CHANX, nodes_per_chan->max + rr_node_offset); } } } diff --git a/vpr/src/route/rr_graph2.h b/vpr/src/route/rr_graph2.h index 718b7a82867..650cdc6b254 100644 --- a/vpr/src/route/rr_graph2.h +++ b/vpr/src/route/rr_graph2.h @@ -75,7 +75,6 @@ int get_number_track_to_track_conn_from_layer(const int layer, const int y, const t_sb_connection_map* sb_conn_map); - int find_average_rr_node_index(int device_width, int device_height, t_rr_type rr_type, From 2fe5adfae41e18d2d79bec19d36d1a1aba2b90ca Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Thu, 31 Aug 2023 21:31:19 -0400 Subject: [PATCH 18/83] added track-to_track edges to correct node index in rr_graph --- vpr/src/route/rr_graph.cpp | 12 ++++-- vpr/src/route/rr_graph2.cpp | 82 ++++++++++++++++++++++++++++--------- vpr/src/route/rr_graph2.h | 1 + 3 files changed, 73 insertions(+), 22 deletions(-) diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index e44bb0f82ea..eb6f73b9fa5 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -3084,6 +3084,12 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, custom_switch_block = true; } + /* + *In case of multi-die FPGAs with custom switchblocks, we map each connection to a new CHANX node with length 0; + *To find track num of newly added nodes, we need to keep index of used nodes for each switch blocks. + */ + int* inter_die_track_offset = 0; + /* Loads up all the routing resource nodes in the current channel segment */ for (int track = 0; track < tracks_per_chan; ++track) { if (seg_details[track].length() == 0) @@ -3131,7 +3137,7 @@ 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, + opposite_chan_type, inter_die_track_offset, seg_dimension, max_opposite_chan_width, grid, Fs_per_side, sblock_pattern, node, rr_edges_to_create, from_seg_details, to_seg_details, opposite_chan_details, directionality, @@ -3151,7 +3157,7 @@ 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, + opposite_chan_type, inter_die_track_offset, seg_dimension, max_opposite_chan_width, grid, 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); @@ -3183,7 +3189,7 @@ 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, + chan_type, inter_die_track_offset, seg_dimension, max_chan_width, grid, Fs_per_side, sblock_pattern, node, rr_edges_to_create, from_seg_details, to_seg_details, from_chan_details, directionality, diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index 7a55c899d9c..1051bf89328 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -104,6 +104,7 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, const int to_x, const int to_y, const t_rr_type to_chan_type, + int* to_track_index, const int switch_override, t_sb_connection_map* sb_conn_map, t_rr_edge_info_set& rr_edges_to_create, @@ -117,6 +118,7 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, const t_rr_type to_chan_type, const e_side from_side, const e_side to_side, + int* to_track_index, const int swtich_override, t_sb_connection_map* sb_conn_map, RRNodeId from_rr_node, @@ -1144,7 +1146,7 @@ int get_number_track_to_track_conn_from_layer(const int layer, int conn_count = 0; for (auto from_side : TOTAL_SIDES) { for (auto to_side : TOTAL_SIDES) { - if (int(from_side) < NUM_SIDES && int(to_side) < NUM_SIDES) { //this connection can not cross any layer + if (int(from_side) < NUM_SIDES && int(to_side) < NUM_SIDES) { //this connection will not cross any layer continue; } if (from_side == to_side) { //no connection @@ -1778,6 +1780,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, const t_rr_type from_type, const int to_seg, const t_rr_type to_type, + int* to_track_index, const int chan_len, const int max_chan_width, const DeviceGrid& grid, @@ -1833,7 +1836,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, //If source and destination segments both lie along the same channel //we clip the loop bounds to the switch blocks of interest and proceed //normally - if (to_type == from_type) { //TODO: SM: remove the comment (CHANX == CHANX OR CHANY == CHANY) + if (to_type == from_type) { start = to_seg - 1; end = to_seg; } @@ -1919,7 +1922,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, if (custom_switch_block) { 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, + to_type, from_side_a, to_side, to_track_index, switch_override, sb_conn_map, from_rr_node, rr_edges_to_create); } @@ -1957,7 +1960,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, if (custom_switch_block) { 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, + to_type, from_side_b, to_side, to_track_index, switch_override, sb_conn_map, from_rr_node, rr_edges_to_create); } @@ -2102,6 +2105,7 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, const int to_x, const int to_y, const t_rr_type to_chan_type, + int* to_track_index, const int switch_override, t_sb_connection_map* sb_conn_map, t_rr_edge_info_set& rr_edges_to_create, @@ -2112,6 +2116,7 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, /* get reference to the connections vector which lists all destination wires for a given source wire * at a specific coordinate sb_coord */ std::vector& conn_vector = (*sb_conn_map)[sb_coord]; + bool has_inter_die_conn = false; /* go through the connections... */ for (int iconn = 0; iconn < (int)conn_vector.size(); ++iconn) { @@ -2119,32 +2124,68 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, int to_wire = conn_vector.at(iconn).to_wire; int to_layer = conn_vector.at(iconn).to_wire_layer; + /* Get the index of the switch connecting the two wires */ + int src_switch = conn_vector[iconn].switch_ind; - RRNodeId to_node = rr_graph_builder.node_lookup().find_node(to_layer, to_x, to_y, to_chan_type, to_wire); - if (!to_node) { - continue; - } + 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); - /* Get the index of the switch connecting the two wires */ - int src_switch = conn_vector[iconn].switch_ind; + 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; + + auto& device_ctx = g_vpr_ctx.device(); + + if (device_ctx.arch_switch_inf[src_switch].directionality() == BI_DIRECTIONAL) { + //Add reverse edge since bi-directional + rr_edges_to_create.emplace_back(to_node, from_rr_node, src_switch, false); + ++edge_count; + } } + else{ //track-to_track connection crossing layer + VTR_ASSERT(to_layer != layer); + int chan_width = g_vpr_ctx.device().chan_width.max; + /* + * In order to connect two tracks in different layers, we need to follow these three steps: + * 1) connect "from_track" to extra "chanx" node in the same switchblocks + * 2) connect extra "chanx" node located in from_layer to another extra "chanx" node located in to_layer + * 3) connect "chanx" node located in to_layer to "to_track" + * */ - rr_edges_to_create.emplace_back(from_rr_node, to_node, src_switch, false); - ++edge_count; + RRNodeId track_to_chanx_node = rr_graph_builder.node_lookup().find_node(layer, tile_x, tile_y, CHANX, chan_width+ (*to_track_index)); + RRNodeId diff_layer_chanx_node = rr_graph_builder.node_lookup().find_node(to_layer, tile_x, tile_y, CHANX, chan_width+ (*to_track_index)); + RRNodeId chanx_to_track_node = rr_graph_builder.node_lookup().find_node(to_layer, to_x, to_y, to_chan_type, to_wire); - auto& device_ctx = g_vpr_ctx.device(); + if(!track_to_chanx_node || !diff_layer_chanx_node || !chanx_to_track_node){ + continue; + } - if (device_ctx.arch_switch_inf[src_switch].directionality() == BI_DIRECTIONAL) { - //Add reverse edge since bi-directional - rr_edges_to_create.emplace_back(to_node, from_rr_node, src_switch, false); + //set the flag that we have used one chanx nodes in both switch blocks + has_inter_die_conn = true; + + //Apply any switch overrides + if (should_apply_switch_override(switch_override)) { + src_switch = switch_override; + } + + rr_edges_to_create.emplace_back(from_rr_node, track_to_chanx_node, src_switch, false); + ++edge_count; + rr_edges_to_create.emplace_back(track_to_chanx_node, diff_layer_chanx_node, src_switch, false); + ++edge_count; + rr_edges_to_create.emplace_back(diff_layer_chanx_node, chanx_to_track_node, src_switch, false); ++edge_count; } } + //incrementing the track index to avoid using same extra for the next iteration + ++(*to_track_index); } } @@ -2161,6 +2202,7 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, const t_rr_type to_chan_type, const e_side from_side, const e_side to_side, + int* to_track_index, const int switch_override, t_sb_connection_map* sb_conn_map, RRNodeId from_rr_node, @@ -2196,6 +2238,7 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, to_x, to_y, to_chan_type, + to_track_index, switch_override, sb_conn_map, rr_edges_to_create, @@ -2214,6 +2257,7 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, to_x, to_y, to_chan_type, + to_track_index, switch_override, sb_conn_map, rr_edges_to_create, diff --git a/vpr/src/route/rr_graph2.h b/vpr/src/route/rr_graph2.h index 650cdc6b254..072ae2246e6 100644 --- a/vpr/src/route/rr_graph2.h +++ b/vpr/src/route/rr_graph2.h @@ -189,6 +189,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, const t_rr_type from_type, const int to_seg, const t_rr_type to_type, + int* to_track_index, const int chan_len, const int max_chan_width, const DeviceGrid& grid, From 93d6b319c94a4eefee9dae9b8d8cbcc19564c909 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Fri, 1 Sep 2023 13:54:39 -0400 Subject: [PATCH 19/83] changed the hash function for sb_conn_map to use vtr::hash_combine --- vpr/src/route/build_switchblocks.h | 14 ++++++-------- vpr/src/route/rr_graph.cpp | 16 +++++++--------- vpr/src/route/rr_graph2.cpp | 8 +++++--- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/vpr/src/route/build_switchblocks.h b/vpr/src/route/build_switchblocks.h index 5c91d7462be..15f8318f681 100644 --- a/vpr/src/route/build_switchblocks.h +++ b/vpr/src/route/build_switchblocks.h @@ -63,14 +63,12 @@ class Switchblock_Lookup { struct t_hash_Switchblock_Lookup { size_t operator()(const Switchblock_Lookup& obj) const noexcept { - //TODO: use vtr::hash_combine - size_t result; - result = ((((std::hash()(obj.x_coord) - ^ std::hash()(obj.y_coord) << 10) - ^ std::hash()(obj.layer_coord << 20) - ^ std::hash()((int)obj.from_side) << 30) - ^ std::hash()((int)obj.to_side) << 40)); - return result; + std::size_t hash = std::hash{}(obj.x_coord); + vtr::hash_combine(hash, obj.y_coord); + vtr::hash_combine(hash, obj.layer_coord); + vtr::hash_combine(hash, obj.from_side); + vtr::hash_combine(hash, obj.to_side); + return hash; } }; diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index eb6f73b9fa5..edb9c367786 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -489,8 +489,7 @@ static void build_inter_die_custom_sb_rr_chan(RRGraphBuilder& rr_graph_builder, const t_sb_connection_map* sb_conn_map, const int const_index_offset, const t_chan_width& nodes_per_chan, - const t_chan_details& chan_details_x, - const DeviceGrid& grid); + const t_chan_details& chan_details_x); void uniquify_edges(t_rr_edge_info_set& rr_edges_to_create); @@ -2163,7 +2162,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder 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()); - build_inter_die_custom_sb_rr_chan(rr_graph_builder, layer, i, j, sb_conn_map, CHANX_COST_INDEX_START, chan_width, chan_details_x, grid); + build_inter_die_custom_sb_rr_chan(rr_graph_builder, layer, i, j, sb_conn_map, CHANX_COST_INDEX_START, chan_width, chan_details_x); } } } @@ -3088,7 +3087,7 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, *In case of multi-die FPGAs with custom switchblocks, we map each connection to a new CHANX node with length 0; *To find track num of newly added nodes, we need to keep index of used nodes for each switch blocks. */ - int* inter_die_track_offset = 0; + int inter_die_track_offset = 0; /* Loads up all the routing resource nodes in the current channel segment */ for (int track = 0; track < tracks_per_chan; ++track) { @@ -3137,7 +3136,7 @@ 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, inter_die_track_offset, seg_dimension, max_opposite_chan_width, grid, + opposite_chan_type, &inter_die_track_offset, seg_dimension, max_opposite_chan_width, grid, Fs_per_side, sblock_pattern, node, rr_edges_to_create, from_seg_details, to_seg_details, opposite_chan_details, directionality, @@ -3157,7 +3156,7 @@ 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, inter_die_track_offset, seg_dimension, max_opposite_chan_width, grid, + opposite_chan_type, &inter_die_track_offset, seg_dimension, max_opposite_chan_width, grid, 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); @@ -3189,7 +3188,7 @@ 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, inter_die_track_offset, seg_dimension, max_chan_width, grid, + chan_type, &inter_die_track_offset, seg_dimension, max_chan_width, grid, Fs_per_side, sblock_pattern, node, rr_edges_to_create, from_seg_details, to_seg_details, from_chan_details, directionality, @@ -3234,8 +3233,7 @@ static void build_inter_die_custom_sb_rr_chan(RRGraphBuilder& rr_graph_builder, const t_sb_connection_map* sb_conn_map, const int const_index_offset, const t_chan_width& nodes_per_chan, - const t_chan_details& chan_details_x, - const DeviceGrid& grid) { + 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(); diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index 1051bf89328..f02b889a188 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -1184,8 +1184,8 @@ void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, if (!device_ctx.inter_cluster_prog_routing_resources.at(layer)) { continue; } - for (int y = 0; y < grid.height() - 1; ++y) { - for (int x = 1; x < grid.width() - 1; ++x) { + for (size_t y = 0; y < grid.height() - 1; ++y) { + for (size_t x = 1; x < grid.width() - 1; ++x) { //count how many track-to-track connection go from current layer to other layers int conn_count = get_number_track_to_track_conn_from_layer(layer, x, y, sb_conn_map); @@ -2185,7 +2185,9 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, } } //incrementing the track index to avoid using same extra for the next iteration - ++(*to_track_index); + if(has_inter_die_conn) { + ++(*to_track_index); + } } } From 0891ca8e1a092197b1cd9be708be9517de6fce94 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Thu, 14 Sep 2023 16:04:26 -0400 Subject: [PATCH 20/83] factor out counting extra nodes --- libs/librrgraph/src/base/check_rr_graph.cpp | 10 +- libs/librrgraph/src/base/rr_rc_data.cpp | 2 +- vpr/src/route/rr_graph.cpp | 48 +++++++-- vpr/src/route/rr_graph2.cpp | 105 ++++++++++++-------- vpr/src/route/rr_graph2.h | 12 +-- 5 files changed, 110 insertions(+), 67 deletions(-) diff --git a/libs/librrgraph/src/base/check_rr_graph.cpp b/libs/librrgraph/src/base/check_rr_graph.cpp index a0c1809b532..dc66aba1587 100644 --- a/libs/librrgraph/src/base/check_rr_graph.cpp +++ b/libs/librrgraph/src/base/check_rr_graph.cpp @@ -485,11 +485,11 @@ void check_rr_node(const RRGraphView& rr_graph, tracks_per_node = ((rr_type == CHANX) ? chan_width.x_list[ylow] : chan_width.y_list[xlow]); } - //todo: SM: we need to allow ptc_num equal to nodes_per_chan - if (ptc_num > nodes_per_chan) { - VPR_ERROR(VPR_ERROR_ROUTE, - "in check_rr_node: inode %d (type %d) has a ptc_num of %d.\n", inode, rr_type, ptc_num); - } + //todo: SM: should come up with better solution than commenting +// if (ptc_num > nodes_per_chan) { +// VPR_ERROR(VPR_ERROR_ROUTE, +// "in check_rr_node: inode %d (type %d) has a ptc_num of %d.\n", inode, rr_type, ptc_num); +// } if (capacity != tracks_per_node) { VPR_FATAL_ERROR(VPR_ERROR_ROUTE, diff --git a/libs/librrgraph/src/base/rr_rc_data.cpp b/libs/librrgraph/src/base/rr_rc_data.cpp index fc24bf396c7..438f4c0633c 100644 --- a/libs/librrgraph/src/base/rr_rc_data.cpp +++ b/libs/librrgraph/src/base/rr_rc_data.cpp @@ -17,7 +17,7 @@ short find_create_rr_rc_data(const float R, const float C, std::vector create it + //Not found -> create it rr_rc_data.emplace_back(R, C); itr = --rr_rc_data.end(); //Iterator to inserted value diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index edb9c367786..306320dc6fa 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -188,6 +188,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder const t_track_to_pin_lookup& track_to_pin_lookup_y, const t_pin_to_track_lookup& opin_to_track_map, const vtr::NdMatrix, 3>& switch_block_conn, + const vtr::NdMatrix& extra_nodes_count_inter_die_count, t_sb_connection_map* sb_conn_map, const DeviceGrid& grid, const int Fs, @@ -486,7 +487,7 @@ 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 t_sb_connection_map* sb_conn_map, + const vtr::NdMatrix& extra_nodes_count_inter_die_count, const int const_index_offset, const t_chan_width& nodes_per_chan, const t_chan_details& chan_details_x); @@ -1261,8 +1262,24 @@ static void build_rr_graph(const t_graph_type graph_type, /* END SB LOOKUP */ /* Add extra nodes to switch blocks for multi-layer FPGAs with custom switch blocks that define track-to_track connections */ + vtr::NdMatrix extra_nodes_count; + auto& grid_ctx = device_ctx.grid; + extra_nodes_count.resize(std::array{(size_t) grid_ctx.get_num_layers(), grid.width(), grid.height()}, 0); + if (grid.get_num_layers() > 1 && sb_type == CUSTOM) { - alloc_and_load_inter_die_rr_node_indices(device_ctx.rr_graph_builder, &nodes_per_chan, grid, sb_conn_map, &num_rr_nodes); + //keep how many nodes each switchblock requires + get_number_track_to_track_intra_die_conn(extra_nodes_count, sb_conn_map); + alloc_and_load_inter_die_rr_node_indices(device_ctx.rr_graph_builder, &nodes_per_chan, grid, extra_nodes_count, &num_rr_nodes); + device_ctx.rr_graph_builder.resize_nodes(num_rr_nodes); + } + + for(int layer = 0; layer < grid.get_num_layers(); layer++){ + for(int x = 0; x < grid.width(); x++){ + for(int y = 0; y < grid.height(); y++){ + if(extra_nodes_count[layer][x][y] > 0) + printf("%d, %d, %d\n",layer,x,y); + } + } } /* START IPIN MAP */ @@ -1353,7 +1370,7 @@ static void build_rr_graph(const t_graph_type graph_type, chan_details_x, chan_details_y, track_to_pin_lookup_x, track_to_pin_lookup_y, opin_to_track_map, - switch_block_conn, sb_conn_map, grid, Fs, unidir_sb_pattern, + switch_block_conn, extra_nodes_count, sb_conn_map, grid, Fs, unidir_sb_pattern, Fc_out, Fc_xofs, Fc_yofs, nodes_per_chan, wire_to_arch_ipin_switch, @@ -1369,7 +1386,7 @@ static void build_rr_graph(const t_graph_type graph_type, // Verify no incremental node allocation. /* AA: Note that in the case of dedicated networks, we are currently underestimating the additional node count due to the clock networks. * Thus, this below error is logged; it's not actually an error, the node estimation needs to get fixed for dedicated clock networks. */ - if (rr_graph.num_nodes() > expected_node_count) { + if (rr_graph.num_nodes() > expected_node_count && clock_modeling == DEDICATED_NETWORK) { VTR_LOG_ERROR("Expected no more than %zu nodes, have %zu nodes\n", expected_node_count, rr_graph.num_nodes()); } @@ -1430,13 +1447,17 @@ static void build_rr_graph(const t_graph_type graph_type, if (!chan_details_x.empty() || !chan_details_y.empty()) { free_chan_details(chan_details_x, chan_details_y); } + if (sb_conn_map) { free_switchblock_permutations(sb_conn_map); sb_conn_map = nullptr; } + extra_nodes_count.clear(); + track_to_pin_lookup_x.clear(); track_to_pin_lookup_y.clear(); + if (clb_to_clb_directs != nullptr) { delete[] clb_to_clb_directs; } @@ -1989,6 +2010,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder const t_track_to_pin_lookup& track_to_pin_lookup_y, const t_pin_to_track_lookup& opin_to_track_map, const vtr::NdMatrix, 3>& switch_block_conn, + const vtr::NdMatrix& extra_nodes_count_inter_die_count, t_sb_connection_map* sb_conn_map, const DeviceGrid& grid, const int Fs, @@ -2162,7 +2184,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder 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()); - build_inter_die_custom_sb_rr_chan(rr_graph_builder, layer, i, j, sb_conn_map, CHANX_COST_INDEX_START, chan_width, chan_details_x); + build_inter_die_custom_sb_rr_chan(rr_graph_builder, layer, i, j, extra_nodes_count_inter_die_count,CHANX_COST_INDEX_START, chan_width, chan_details_x); } } } @@ -3087,7 +3109,8 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, *In case of multi-die FPGAs with custom switchblocks, we map each connection to a new CHANX node with length 0; *To find track num of newly added nodes, we need to keep index of used nodes for each switch blocks. */ - int inter_die_track_offset = 0; + vtr::NdMatrix inter_die_track_offset_custom_switchblocks; + inter_die_track_offset_custom_switchblocks.resize(std::array{(size_t) grid.get_num_layers(), grid.width(), grid.height()}, 0); /* Loads up all the routing resource nodes in the current channel segment */ for (int track = 0; track < tracks_per_chan; ++track) { @@ -3136,7 +3159,7 @@ 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, &inter_die_track_offset, seg_dimension, max_opposite_chan_width, grid, + opposite_chan_type, inter_die_track_offset_custom_switchblocks, seg_dimension, max_opposite_chan_width, grid, Fs_per_side, sblock_pattern, node, rr_edges_to_create, from_seg_details, to_seg_details, opposite_chan_details, directionality, @@ -3156,7 +3179,7 @@ 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, &inter_die_track_offset, seg_dimension, max_opposite_chan_width, grid, + opposite_chan_type, inter_die_track_offset_custom_switchblocks, seg_dimension, max_opposite_chan_width, grid, 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); @@ -3188,7 +3211,7 @@ 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, &inter_die_track_offset, seg_dimension, max_chan_width, grid, + chan_type, inter_die_track_offset_custom_switchblocks, seg_dimension, max_chan_width, grid, Fs_per_side, sblock_pattern, node, rr_edges_to_create, from_seg_details, to_seg_details, from_chan_details, directionality, @@ -3224,13 +3247,16 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, rr_graph_builder.set_node_track_num(node, track); rr_graph_builder.set_node_direction(node, seg_details[track].direction()); } + + //clear temp data structures + inter_die_track_offset_custom_switchblocks.clear(); } 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 t_sb_connection_map* sb_conn_map, + const vtr::NdMatrix& extra_nodes_count_inter_die_count, const int const_index_offset, const t_chan_width& nodes_per_chan, const t_chan_details& chan_details_x) { @@ -3239,7 +3265,7 @@ static void build_inter_die_custom_sb_rr_chan(RRGraphBuilder& rr_graph_builder, /* Loads up all the extra routing resource nodes required to support multi-die custom switch blocks */ int start_track = nodes_per_chan.max; - int conn_count = get_number_track_to_track_conn_from_layer(layer, x_coord, y_coord, sb_conn_map); + int conn_count = extra_nodes_count_inter_die_count[layer][x_coord][y_coord]; for (int offset = 0; offset < conn_count; offset++) { RRNodeId node = rr_graph_builder.node_lookup().find_node(layer, x_coord, y_coord, CHANX, start_track + offset); diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index f02b889a188..0bf6607cd8e 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -104,7 +104,7 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, const int to_x, const int to_y, const t_rr_type to_chan_type, - int* to_track_index, + vtr::NdMatrix& inter_die_track_offset_custom_switchblocks, const int switch_override, t_sb_connection_map* sb_conn_map, t_rr_edge_info_set& rr_edges_to_create, @@ -118,7 +118,7 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, const t_rr_type to_chan_type, const e_side from_side, const e_side to_side, - int* to_track_index, + vtr::NdMatrix& inter_die_track_offset_custom_switchblocks, const int swtich_override, t_sb_connection_map* sb_conn_map, RRNodeId from_rr_node, @@ -1139,34 +1139,54 @@ static void load_chan_rr_indices(const int max_chan_width, } } -int get_number_track_to_track_conn_from_layer(const int layer, - const int x, - const int y, - const t_sb_connection_map* sb_conn_map) { - int conn_count = 0; - for (auto from_side : TOTAL_SIDES) { - for (auto to_side : TOTAL_SIDES) { - if (int(from_side) < NUM_SIDES && int(to_side) < NUM_SIDES) { //this connection will not cross any layer - continue; - } - if (from_side == to_side) { //no connection - continue; - } - - Switchblock_Lookup sb_coord(x, y, layer, from_side, to_side); - if (sb_conn_map->count(sb_coord) > 0) { - conn_count += sb_conn_map->size(); +void get_number_track_to_track_intra_die_conn(vtr::NdMatrix& extra_node_count, + t_sb_connection_map* sb_conn_map) { + auto& grid_ctx = g_vpr_ctx.device().grid; + for(auto layer = 0; layer < grid_ctx.get_num_layers(); layer++){ + for(size_t x = 0; x < grid_ctx.width(); x++){ + for(size_t y = 0; y < grid_ctx.height(); y++){ + for(auto from_side : TOTAL_SIDES){ + for(auto to_side : TOTAL_SIDES){ + if(from_side < NUM_SIDES && to_side < NUM_SIDES){ //this connection is not crossing any layer + continue; + } + else if (from_side == to_side){ + continue; + } + else{ + Switchblock_Lookup sb_coord(x, y, layer, from_side, to_side); + if (sb_conn_map->count(sb_coord) > 0) { + std::vector& conn_vector = (*sb_conn_map)[sb_coord]; + for (int iconn = 0; iconn < (int)conn_vector.size(); ++iconn) { + //connection doesn't cross any layer, no new node is required + if(conn_vector[iconn].to_wire_layer == conn_vector[iconn].from_wire_layer){ + continue; + } + else{ + //check if both from_layer and to_layer are valid, might not be valid since patterns in switchblocks are very general + if(conn_vector[iconn].from_wire_layer >= 0 && conn_vector[iconn].from_wire_layer < grid_ctx.get_num_layers()){ + if(conn_vector[iconn].to_wire_layer >= 0 && conn_vector[iconn].to_wire_layer < grid_ctx.get_num_layers()){ + //add an extra node for source layer + extra_node_count[conn_vector[iconn].from_wire_layer][x][y]++; + //add an extra node for destination layer + extra_node_count[conn_vector[iconn].to_wire_layer][x][y]++; + } + } + } + } + } + } + } + } } } } - - return conn_count; } void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, const t_chan_width* nodes_per_chan, const DeviceGrid& grid, - const t_sb_connection_map* sb_conn_map, + const vtr::NdMatrix& extra_nodes_count, int* index) { /* * In case of multi-die FPGAs, we add extra nodes (can be either CHANX OR CHANY, used CHANX) to @@ -1176,7 +1196,6 @@ void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, * 2) length = 0 (xhigh = xlow, yhigh = ylow) * 3) ptc = [max_chanx_width:max_chanx_width+number_of_connection] */ - auto& device_ctx = g_vpr_ctx.device(); for (int layer = 0; layer < grid.get_num_layers(); layer++) { @@ -1187,8 +1206,7 @@ void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, for (size_t y = 0; y < grid.height() - 1; ++y) { for (size_t x = 1; x < grid.width() - 1; ++x) { //count how many track-to-track connection go from current layer to other layers - int conn_count = get_number_track_to_track_conn_from_layer(layer, x, y, sb_conn_map); - + int conn_count = extra_nodes_count[layer][x][y]; //reserve extra nodes for inter-die track-to-track connection rr_graph_builder.node_lookup().reserve_nodes(layer, x, y, CHANX, conn_count); for (int rr_node_offset = 0; rr_node_offset < conn_count; rr_node_offset++) { @@ -1780,7 +1798,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, const t_rr_type from_type, const int to_seg, const t_rr_type to_type, - int* to_track_index, + vtr::NdMatrix& inter_die_track_offset_custom_switchblocks, const int chan_len, const int max_chan_width, const DeviceGrid& grid, @@ -1922,7 +1940,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, if (custom_switch_block) { 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, to_track_index, + to_type, from_side_a, to_side, inter_die_track_offset_custom_switchblocks, switch_override, sb_conn_map, from_rr_node, rr_edges_to_create); } @@ -1960,7 +1978,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, if (custom_switch_block) { 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, to_track_index, + to_type, from_side_b, to_side, inter_die_track_offset_custom_switchblocks, switch_override, sb_conn_map, from_rr_node, rr_edges_to_create); } @@ -2105,18 +2123,20 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, const int to_x, const int to_y, const t_rr_type to_chan_type, - int* to_track_index, + vtr::NdMatrix& inter_die_track_offset_custom_switchblocks, const int switch_override, t_sb_connection_map* sb_conn_map, t_rr_edge_info_set& rr_edges_to_create, int& edge_count) { + + auto& device_ctx = g_vpr_ctx.device(); + /* get coordinate to index into the SB map */ Switchblock_Lookup sb_coord(tile_x, tile_y, layer, from_side, to_side); if (sb_conn_map->count(sb_coord) > 0) { /* get reference to the connections vector which lists all destination wires for a given source wire * at a specific coordinate sb_coord */ std::vector& conn_vector = (*sb_conn_map)[sb_coord]; - bool has_inter_die_conn = false; /* go through the connections... */ for (int iconn = 0; iconn < (int)conn_vector.size(); ++iconn) { @@ -2142,8 +2162,6 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, rr_edges_to_create.emplace_back(from_rr_node, to_node, src_switch, false); ++edge_count; - auto& device_ctx = g_vpr_ctx.device(); - if (device_ctx.arch_switch_inf[src_switch].directionality() == BI_DIRECTIONAL) { //Add reverse edge since bi-directional rr_edges_to_create.emplace_back(to_node, from_rr_node, src_switch, false); @@ -2160,16 +2178,17 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, * 3) connect "chanx" node located in to_layer to "to_track" * */ - RRNodeId track_to_chanx_node = rr_graph_builder.node_lookup().find_node(layer, tile_x, tile_y, CHANX, chan_width+ (*to_track_index)); - RRNodeId diff_layer_chanx_node = rr_graph_builder.node_lookup().find_node(to_layer, tile_x, tile_y, CHANX, chan_width+ (*to_track_index)); + RRNodeId track_to_chanx_node = rr_graph_builder.node_lookup().find_node(layer, tile_x, tile_y, CHANX, chan_width + inter_die_track_offset_custom_switchblocks[layer][tile_x][tile_y]); + RRNodeId diff_layer_chanx_node = rr_graph_builder.node_lookup().find_node(to_layer, tile_x, tile_y, CHANX, chan_width + inter_die_track_offset_custom_switchblocks[to_layer][tile_x][tile_y]); RRNodeId chanx_to_track_node = rr_graph_builder.node_lookup().find_node(to_layer, to_x, to_y, to_chan_type, to_wire); if(!track_to_chanx_node || !diff_layer_chanx_node || !chanx_to_track_node){ continue; } - //set the flag that we have used one chanx nodes in both switch blocks - has_inter_die_conn = true; + //increase the offset since we have used two new extra nodes + inter_die_track_offset_custom_switchblocks[layer][tile_x][tile_y]++; + inter_die_track_offset_custom_switchblocks[to_layer][tile_x][tile_y]++; //Apply any switch overrides if (should_apply_switch_override(switch_override)) { @@ -2182,12 +2201,12 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, ++edge_count; rr_edges_to_create.emplace_back(diff_layer_chanx_node, chanx_to_track_node, src_switch, false); ++edge_count; + + if (device_ctx.arch_switch_inf[src_switch].directionality() == BI_DIRECTIONAL) { + //todo: SM: should complete this part + } } } - //incrementing the track index to avoid using same extra for the next iteration - if(has_inter_die_conn) { - ++(*to_track_index); - } } } @@ -2204,7 +2223,7 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, const t_rr_type to_chan_type, const e_side from_side, const e_side to_side, - int* to_track_index, + vtr::NdMatrix& inter_die_track_offset_custom_switchblocks, const int switch_override, t_sb_connection_map* sb_conn_map, RRNodeId from_rr_node, @@ -2240,7 +2259,7 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, to_x, to_y, to_chan_type, - to_track_index, + inter_die_track_offset_custom_switchblocks, switch_override, sb_conn_map, rr_edges_to_create, @@ -2259,7 +2278,7 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, to_x, to_y, to_chan_type, - to_track_index, + inter_die_track_offset_custom_switchblocks, switch_override, sb_conn_map, rr_edges_to_create, diff --git a/vpr/src/route/rr_graph2.h b/vpr/src/route/rr_graph2.h index 072ae2246e6..db1e3f2ae70 100644 --- a/vpr/src/route/rr_graph2.h +++ b/vpr/src/route/rr_graph2.h @@ -32,7 +32,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 t_chan_width* nodes_per_chan, const DeviceGrid& grid, - const t_sb_connection_map* sb_conn_map, + const vtr::NdMatrix& extra_nodes_count, int* index); void alloc_and_load_tile_rr_node_indices(RRGraphBuilder& rr_graph_builder, @@ -69,11 +69,9 @@ int get_rr_node_index(const t_rr_node_indices& L_rr_node_indices, int ptc, e_side side = NUM_SIDES); -//Return how many connection inside switch blocks located at (layer,x,y) are going to a different layer -int get_number_track_to_track_conn_from_layer(const int layer, - const int x, - const int y, - const t_sb_connection_map* sb_conn_map); +//Return how many connection inside switch blocks located at each grid location are going to a different layer +void get_number_track_to_track_intra_die_conn(vtr::NdMatrix& extra_node_count, + t_sb_connection_map* sb_conn_map); int find_average_rr_node_index(int device_width, int device_height, @@ -189,7 +187,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, const t_rr_type from_type, const int to_seg, const t_rr_type to_type, - int* to_track_index, + vtr::NdMatrix& inter_die_track_offset_custom_switchblocks, const int chan_len, const int max_chan_width, const DeviceGrid& grid, From aa804c200a68376166c1c4424574360142d1d67c Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Fri, 15 Sep 2023 10:32:47 -0400 Subject: [PATCH 21/83] debug: chanx nodes should have been added by (y,x) --- vpr/src/route/rr_graph.cpp | 29 +++++++++++++---------------- vpr/src/route/rr_graph2.cpp | 29 ++++++++++++++++++++++------- 2 files changed, 35 insertions(+), 23 deletions(-) diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index 306320dc6fa..d21afc77f4d 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -1273,15 +1273,6 @@ static void build_rr_graph(const t_graph_type graph_type, device_ctx.rr_graph_builder.resize_nodes(num_rr_nodes); } - for(int layer = 0; layer < grid.get_num_layers(); layer++){ - for(int x = 0; x < grid.width(); x++){ - for(int y = 0; y < grid.height(); y++){ - if(extra_nodes_count[layer][x][y] > 0) - printf("%d, %d, %d\n",layer,x,y); - } - } - } - /* START IPIN MAP */ /* Create ipin map lookups */ @@ -2143,6 +2134,14 @@ 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 connection between layers, we need to load newly added CHANX nodes + 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()); + build_inter_die_custom_sb_rr_chan(rr_graph_builder, layer, i, j, extra_nodes_count_inter_die_count,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, CHANX, track_to_pin_lookup_x, sb_conn_map, switch_block_conn, @@ -2179,13 +2178,6 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder rr_edges_to_create.clear(); } - - //In multi-die FPGAs with track-to-track connection between layers, we need to load newly added CHANX nodes - 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()); - build_inter_die_custom_sb_rr_chan(rr_graph_builder, layer, i, j, extra_nodes_count_inter_die_count,CHANX_COST_INDEX_START, chan_width, chan_details_x); - } } } } @@ -3267,7 +3259,12 @@ static void build_inter_die_custom_sb_rr_chan(RRGraphBuilder& rr_graph_builder, int start_track = nodes_per_chan.max; int conn_count = extra_nodes_count_inter_die_count[layer][x_coord][y_coord]; + if(conn_count == 0){ + return; //no new node required in this switchblock + } + for (int offset = 0; offset < conn_count; offset++) { + int track_num = start_track + offset; RRNodeId node = rr_graph_builder.node_lookup().find_node(layer, x_coord, y_coord, CHANX, start_track + offset); if (node) { rr_graph_builder.set_node_layer(node, layer); diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index 0bf6607cd8e..bfec867b3a9 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -97,6 +97,7 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, const int tile_x, const int tile_y, const int layer, + const int max_chan_width, const e_side from_side, const int from_wire, RRNodeId from_rr_node, @@ -112,6 +113,7 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, const int layer, + const int max_chan_width, const int from_track, const int to_chan, const int to_seg, @@ -1158,8 +1160,8 @@ void get_number_track_to_track_intra_die_conn(vtr::NdMatrix& extra_node_c if (sb_conn_map->count(sb_coord) > 0) { std::vector& conn_vector = (*sb_conn_map)[sb_coord]; for (int iconn = 0; iconn < (int)conn_vector.size(); ++iconn) { - //connection doesn't cross any layer, no new node is required if(conn_vector[iconn].to_wire_layer == conn_vector[iconn].from_wire_layer){ + //this connection doesn't cross any layer, no new node is required continue; } else{ @@ -1207,10 +1209,14 @@ void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, for (size_t x = 1; x < grid.width() - 1; ++x) { //count how many track-to-track connection go from current layer to other layers int conn_count = extra_nodes_count[layer][x][y]; + if(conn_count == 0){ + continue; + } //reserve extra nodes for inter-die track-to-track connection rr_graph_builder.node_lookup().reserve_nodes(layer, x, y, CHANX, 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, y, x, CHANX, nodes_per_chan->max + rr_node_offset); + int track_num = nodes_per_chan->max + rr_node_offset; + RRNodeId inode = rr_graph_builder.node_lookup().find_node(layer, x, y, CHANX, nodes_per_chan->max + rr_node_offset); if (!inode) { inode = RRNodeId(*index); ++(*index); @@ -1559,6 +1565,11 @@ bool verify_rr_node_indices(const DeviceGrid& grid, if (rr_graph.node_type(inode) == CHANX) { VTR_ASSERT_MSG(rr_graph.node_ylow(inode) == rr_graph.node_yhigh(inode), "CHANX should be horizontal"); + //TODO: SM: remove these + int ylow = rr_graph.node_ylow(inode); + int yhigh = rr_graph.node_yhigh(inode); + int xlow = rr_graph.node_xlow(inode); + int xhigh = rr_graph.node_xhigh(inode); if (y != rr_graph.node_ylow(inode)) { VPR_ERROR(VPR_ERROR_ROUTE, "RR node y position does not agree between rr_nodes (%d) and rr_node_indices (%d): %s", @@ -1939,7 +1950,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, if (sb_seg < end_sb_seg) { if (custom_switch_block) { 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, + num_conn += get_track_to_chan_seg(rr_graph_builder, layer, max_chan_width, from_track, to_chan, to_seg, to_type, from_side_a, to_side, inter_die_track_offset_custom_switchblocks, switch_override, sb_conn_map, from_rr_node, rr_edges_to_create); @@ -1977,7 +1988,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, if (sb_seg > start_sb_seg) { if (custom_switch_block) { 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, + num_conn += get_track_to_chan_seg(rr_graph_builder, layer, max_chan_width, from_track, to_chan, to_seg, to_type, from_side_b, to_side, inter_die_track_offset_custom_switchblocks, switch_override, sb_conn_map, from_rr_node, rr_edges_to_create); @@ -2116,6 +2127,7 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, const int tile_x, const int tile_y, const int layer, + const int max_chan_width, const e_side from_side, const int from_wire, RRNodeId from_rr_node, @@ -2170,7 +2182,7 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, } else{ //track-to_track connection crossing layer VTR_ASSERT(to_layer != layer); - int chan_width = g_vpr_ctx.device().chan_width.max; + /* * In order to connect two tracks in different layers, we need to follow these three steps: * 1) connect "from_track" to extra "chanx" node in the same switchblocks @@ -2178,8 +2190,8 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, * 3) connect "chanx" node located in to_layer to "to_track" * */ - RRNodeId track_to_chanx_node = rr_graph_builder.node_lookup().find_node(layer, tile_x, tile_y, CHANX, chan_width + inter_die_track_offset_custom_switchblocks[layer][tile_x][tile_y]); - RRNodeId diff_layer_chanx_node = rr_graph_builder.node_lookup().find_node(to_layer, tile_x, tile_y, CHANX, chan_width + inter_die_track_offset_custom_switchblocks[to_layer][tile_x][tile_y]); + RRNodeId track_to_chanx_node = rr_graph_builder.node_lookup().find_node(layer, tile_x, tile_y, CHANX, max_chan_width + inter_die_track_offset_custom_switchblocks[layer][tile_x][tile_y]); + RRNodeId diff_layer_chanx_node = rr_graph_builder.node_lookup().find_node(to_layer, tile_x, tile_y, CHANX, max_chan_width + inter_die_track_offset_custom_switchblocks[to_layer][tile_x][tile_y]); RRNodeId chanx_to_track_node = rr_graph_builder.node_lookup().find_node(to_layer, to_x, to_y, to_chan_type, to_wire); if(!track_to_chanx_node || !diff_layer_chanx_node || !chanx_to_track_node){ @@ -2217,6 +2229,7 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, * connection map sb_conn_map is generated. */ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, const int layer, + const int max_chan_width, const int from_wire, const int to_chan, const int to_seg, @@ -2252,6 +2265,7 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, tile_x, tile_y, layer, + max_chan_width, from_side, from_wire, from_rr_node, @@ -2271,6 +2285,7 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, tile_x, tile_y, layer, + max_chan_width, from_side, from_wire, from_rr_node, From 6ba63219d3367eb6d3643b52ee44bfdb996030d8 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Fri, 15 Sep 2023 10:46:23 -0400 Subject: [PATCH 22/83] removed extra TODOs and uncomment check_rr_graph --- libs/librrgraph/src/base/check_rr_graph.cpp | 13 +++-- vpr/src/route/rr_graph.cpp | 22 ++++---- vpr/src/route/rr_graph2.cpp | 59 ++++++++------------- vpr/src/route/rr_graph2.h | 6 +-- 4 files changed, 44 insertions(+), 56 deletions(-) diff --git a/libs/librrgraph/src/base/check_rr_graph.cpp b/libs/librrgraph/src/base/check_rr_graph.cpp index dc66aba1587..e51e8a6c8e6 100644 --- a/libs/librrgraph/src/base/check_rr_graph.cpp +++ b/libs/librrgraph/src/base/check_rr_graph.cpp @@ -485,11 +485,14 @@ void check_rr_node(const RRGraphView& rr_graph, tracks_per_node = ((rr_type == CHANX) ? chan_width.x_list[ylow] : chan_width.y_list[xlow]); } - //todo: SM: should come up with better solution than commenting -// if (ptc_num > nodes_per_chan) { -// VPR_ERROR(VPR_ERROR_ROUTE, -// "in check_rr_node: inode %d (type %d) has a ptc_num of %d.\n", inode, rr_type, ptc_num); -// } + //if a chanx/chany has length 0, it means it is used to connect different dice together + //hence, the ptc number can be larger than nodes_per_chan + if(xlow != xhigh || ylow != yhigh) { + if (ptc_num > nodes_per_chan) { + VPR_ERROR(VPR_ERROR_ROUTE, + "in check_rr_node: inode %d (type %d) has a ptc_num of %d.\n", inode, rr_type, ptc_num); + } + } if (capacity != tracks_per_node) { VPR_FATAL_ERROR(VPR_ERROR_ROUTE, diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index d21afc77f4d..1a4d9ab37cf 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -188,7 +188,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder const t_track_to_pin_lookup& track_to_pin_lookup_y, const t_pin_to_track_lookup& opin_to_track_map, const vtr::NdMatrix, 3>& switch_block_conn, - const vtr::NdMatrix& extra_nodes_count_inter_die_count, + const vtr::NdMatrix& extra_nodes_count_inter_die_count, t_sb_connection_map* sb_conn_map, const DeviceGrid& grid, const int Fs, @@ -487,7 +487,7 @@ 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 vtr::NdMatrix& extra_nodes_count_inter_die_count, + const vtr::NdMatrix& extra_nodes_count_inter_die_count, const int const_index_offset, const t_chan_width& nodes_per_chan, const t_chan_details& chan_details_x); @@ -1262,9 +1262,9 @@ static void build_rr_graph(const t_graph_type graph_type, /* END SB LOOKUP */ /* Add extra nodes to switch blocks for multi-layer FPGAs with custom switch blocks that define track-to_track connections */ - vtr::NdMatrix extra_nodes_count; + vtr::NdMatrix extra_nodes_count; auto& grid_ctx = device_ctx.grid; - extra_nodes_count.resize(std::array{(size_t) grid_ctx.get_num_layers(), grid.width(), grid.height()}, 0); + extra_nodes_count.resize(std::array{(size_t)grid_ctx.get_num_layers(), grid.width(), grid.height()}, 0); if (grid.get_num_layers() > 1 && sb_type == CUSTOM) { //keep how many nodes each switchblock requires @@ -2001,7 +2001,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder const t_track_to_pin_lookup& track_to_pin_lookup_y, const t_pin_to_track_lookup& opin_to_track_map, const vtr::NdMatrix, 3>& switch_block_conn, - const vtr::NdMatrix& extra_nodes_count_inter_die_count, + const vtr::NdMatrix& extra_nodes_count_inter_die_count, t_sb_connection_map* sb_conn_map, const DeviceGrid& grid, const int Fs, @@ -2134,12 +2134,11 @@ 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 connection between layers, we need to load newly added CHANX nodes 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()); - build_inter_die_custom_sb_rr_chan(rr_graph_builder, layer, i, j, extra_nodes_count_inter_die_count,CHANX_COST_INDEX_START, chan_width, chan_details_x); + build_inter_die_custom_sb_rr_chan(rr_graph_builder, layer, i, j, extra_nodes_count_inter_die_count, CHANX_COST_INDEX_START, chan_width, chan_details_x); } if (i > 0) { @@ -3101,8 +3100,8 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, *In case of multi-die FPGAs with custom switchblocks, we map each connection to a new CHANX node with length 0; *To find track num of newly added nodes, we need to keep index of used nodes for each switch blocks. */ - vtr::NdMatrix inter_die_track_offset_custom_switchblocks; - inter_die_track_offset_custom_switchblocks.resize(std::array{(size_t) grid.get_num_layers(), grid.width(), grid.height()}, 0); + vtr::NdMatrix inter_die_track_offset_custom_switchblocks; + inter_die_track_offset_custom_switchblocks.resize(std::array{(size_t)grid.get_num_layers(), grid.width(), grid.height()}, 0); /* Loads up all the routing resource nodes in the current channel segment */ for (int track = 0; track < tracks_per_chan; ++track) { @@ -3248,7 +3247,7 @@ 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 vtr::NdMatrix& extra_nodes_count_inter_die_count, + const vtr::NdMatrix& extra_nodes_count_inter_die_count, const int const_index_offset, const t_chan_width& nodes_per_chan, const t_chan_details& chan_details_x) { @@ -3259,12 +3258,11 @@ static void build_inter_die_custom_sb_rr_chan(RRGraphBuilder& rr_graph_builder, int start_track = nodes_per_chan.max; int conn_count = extra_nodes_count_inter_die_count[layer][x_coord][y_coord]; - if(conn_count == 0){ + if (conn_count == 0) { return; //no new node required in this switchblock } for (int offset = 0; offset < conn_count; offset++) { - int track_num = start_track + offset; RRNodeId node = rr_graph_builder.node_lookup().find_node(layer, x_coord, y_coord, CHANX, start_track + offset); if (node) { rr_graph_builder.set_node_layer(node, layer); diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index bfec867b3a9..d17684b73fa 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -105,7 +105,7 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, const int to_x, const int to_y, const t_rr_type to_chan_type, - vtr::NdMatrix& inter_die_track_offset_custom_switchblocks, + vtr::NdMatrix& inter_die_track_offset_custom_switchblocks, const int switch_override, t_sb_connection_map* sb_conn_map, t_rr_edge_info_set& rr_edges_to_create, @@ -120,7 +120,7 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, const t_rr_type to_chan_type, const e_side from_side, const e_side to_side, - vtr::NdMatrix& inter_die_track_offset_custom_switchblocks, + vtr::NdMatrix& inter_die_track_offset_custom_switchblocks, const int swtich_override, t_sb_connection_map* sb_conn_map, RRNodeId from_rr_node, @@ -1141,33 +1141,30 @@ static void load_chan_rr_indices(const int max_chan_width, } } -void get_number_track_to_track_intra_die_conn(vtr::NdMatrix& extra_node_count, +void get_number_track_to_track_intra_die_conn(vtr::NdMatrix& extra_node_count, t_sb_connection_map* sb_conn_map) { auto& grid_ctx = g_vpr_ctx.device().grid; - for(auto layer = 0; layer < grid_ctx.get_num_layers(); layer++){ - for(size_t x = 0; x < grid_ctx.width(); x++){ - for(size_t y = 0; y < grid_ctx.height(); y++){ - for(auto from_side : TOTAL_SIDES){ - for(auto to_side : TOTAL_SIDES){ - if(from_side < NUM_SIDES && to_side < NUM_SIDES){ //this connection is not crossing any layer + for (auto layer = 0; layer < grid_ctx.get_num_layers(); layer++) { + for (size_t x = 0; x < grid_ctx.width(); x++) { + for (size_t y = 0; y < grid_ctx.height(); y++) { + for (auto from_side : TOTAL_SIDES) { + for (auto to_side : TOTAL_SIDES) { + if (from_side < NUM_SIDES && to_side < NUM_SIDES) { //this connection is not crossing any layer continue; - } - else if (from_side == to_side){ + } else if (from_side == to_side) { continue; - } - else{ + } else { Switchblock_Lookup sb_coord(x, y, layer, from_side, to_side); if (sb_conn_map->count(sb_coord) > 0) { std::vector& conn_vector = (*sb_conn_map)[sb_coord]; for (int iconn = 0; iconn < (int)conn_vector.size(); ++iconn) { - if(conn_vector[iconn].to_wire_layer == conn_vector[iconn].from_wire_layer){ + if (conn_vector[iconn].to_wire_layer == conn_vector[iconn].from_wire_layer) { //this connection doesn't cross any layer, no new node is required continue; - } - else{ + } else { //check if both from_layer and to_layer are valid, might not be valid since patterns in switchblocks are very general - if(conn_vector[iconn].from_wire_layer >= 0 && conn_vector[iconn].from_wire_layer < grid_ctx.get_num_layers()){ - if(conn_vector[iconn].to_wire_layer >= 0 && conn_vector[iconn].to_wire_layer < grid_ctx.get_num_layers()){ + if (conn_vector[iconn].from_wire_layer >= 0 && conn_vector[iconn].from_wire_layer < grid_ctx.get_num_layers()) { + if (conn_vector[iconn].to_wire_layer >= 0 && conn_vector[iconn].to_wire_layer < grid_ctx.get_num_layers()) { //add an extra node for source layer extra_node_count[conn_vector[iconn].from_wire_layer][x][y]++; //add an extra node for destination layer @@ -1188,7 +1185,7 @@ void get_number_track_to_track_intra_die_conn(vtr::NdMatrix& extra_node_c void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, const t_chan_width* nodes_per_chan, const DeviceGrid& grid, - const vtr::NdMatrix& extra_nodes_count, + const vtr::NdMatrix& extra_nodes_count, int* index) { /* * In case of multi-die FPGAs, we add extra nodes (can be either CHANX OR CHANY, used CHANX) to @@ -1209,13 +1206,12 @@ void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, for (size_t x = 1; x < grid.width() - 1; ++x) { //count how many track-to-track connection go from current layer to other layers int conn_count = extra_nodes_count[layer][x][y]; - if(conn_count == 0){ + if (conn_count == 0) { continue; } //reserve extra nodes for inter-die track-to-track connection rr_graph_builder.node_lookup().reserve_nodes(layer, x, y, CHANX, conn_count); for (int rr_node_offset = 0; rr_node_offset < conn_count; rr_node_offset++) { - int track_num = nodes_per_chan->max + rr_node_offset; RRNodeId inode = rr_graph_builder.node_lookup().find_node(layer, x, y, CHANX, nodes_per_chan->max + rr_node_offset); if (!inode) { inode = RRNodeId(*index); @@ -1565,12 +1561,6 @@ bool verify_rr_node_indices(const DeviceGrid& grid, if (rr_graph.node_type(inode) == CHANX) { VTR_ASSERT_MSG(rr_graph.node_ylow(inode) == rr_graph.node_yhigh(inode), "CHANX should be horizontal"); - //TODO: SM: remove these - int ylow = rr_graph.node_ylow(inode); - int yhigh = rr_graph.node_yhigh(inode); - int xlow = rr_graph.node_xlow(inode); - int xhigh = rr_graph.node_xhigh(inode); - if (y != rr_graph.node_ylow(inode)) { VPR_ERROR(VPR_ERROR_ROUTE, "RR node y position does not agree between rr_nodes (%d) and rr_node_indices (%d): %s", rr_graph.node_ylow(inode), @@ -1809,7 +1799,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, const t_rr_type from_type, const int to_seg, const t_rr_type to_type, - vtr::NdMatrix& inter_die_track_offset_custom_switchblocks, + vtr::NdMatrix& inter_die_track_offset_custom_switchblocks, const int chan_len, const int max_chan_width, const DeviceGrid& grid, @@ -2135,12 +2125,11 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, const int to_x, const int to_y, const t_rr_type to_chan_type, - vtr::NdMatrix& inter_die_track_offset_custom_switchblocks, + vtr::NdMatrix& inter_die_track_offset_custom_switchblocks, const int switch_override, t_sb_connection_map* sb_conn_map, t_rr_edge_info_set& rr_edges_to_create, int& edge_count) { - auto& device_ctx = g_vpr_ctx.device(); /* get coordinate to index into the SB map */ @@ -2159,8 +2148,7 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, /* Get the index of the switch connecting the two wires */ int src_switch = conn_vector[iconn].switch_ind; - - if(to_layer == layer){ //track-to-track connection within the same layer + if (to_layer == layer) { //track-to-track connection within the same layer RRNodeId to_node = rr_graph_builder.node_lookup().find_node(to_layer, to_x, to_y, to_chan_type, to_wire); if (!to_node) { @@ -2179,8 +2167,7 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, rr_edges_to_create.emplace_back(to_node, from_rr_node, src_switch, false); ++edge_count; } - } - else{ //track-to_track connection crossing layer + } else { //track-to_track connection crossing layer VTR_ASSERT(to_layer != layer); /* @@ -2194,7 +2181,7 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, RRNodeId diff_layer_chanx_node = rr_graph_builder.node_lookup().find_node(to_layer, tile_x, tile_y, CHANX, max_chan_width + inter_die_track_offset_custom_switchblocks[to_layer][tile_x][tile_y]); RRNodeId chanx_to_track_node = rr_graph_builder.node_lookup().find_node(to_layer, to_x, to_y, to_chan_type, to_wire); - if(!track_to_chanx_node || !diff_layer_chanx_node || !chanx_to_track_node){ + if (!track_to_chanx_node || !diff_layer_chanx_node || !chanx_to_track_node) { continue; } @@ -2236,7 +2223,7 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, const t_rr_type to_chan_type, const e_side from_side, const e_side to_side, - vtr::NdMatrix& inter_die_track_offset_custom_switchblocks, + vtr::NdMatrix& inter_die_track_offset_custom_switchblocks, const int switch_override, t_sb_connection_map* sb_conn_map, RRNodeId from_rr_node, diff --git a/vpr/src/route/rr_graph2.h b/vpr/src/route/rr_graph2.h index db1e3f2ae70..0342ad428d3 100644 --- a/vpr/src/route/rr_graph2.h +++ b/vpr/src/route/rr_graph2.h @@ -32,7 +32,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 t_chan_width* nodes_per_chan, const DeviceGrid& grid, - const vtr::NdMatrix& extra_nodes_count, + const vtr::NdMatrix& extra_nodes_count, int* index); void alloc_and_load_tile_rr_node_indices(RRGraphBuilder& rr_graph_builder, @@ -70,7 +70,7 @@ int get_rr_node_index(const t_rr_node_indices& L_rr_node_indices, e_side side = NUM_SIDES); //Return how many connection inside switch blocks located at each grid location are going to a different layer -void get_number_track_to_track_intra_die_conn(vtr::NdMatrix& extra_node_count, +void get_number_track_to_track_intra_die_conn(vtr::NdMatrix& extra_node_count, t_sb_connection_map* sb_conn_map); int find_average_rr_node_index(int device_width, @@ -187,7 +187,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, const t_rr_type from_type, const int to_seg, const t_rr_type to_type, - vtr::NdMatrix& inter_die_track_offset_custom_switchblocks, + vtr::NdMatrix& inter_die_track_offset_custom_switchblocks, const int chan_len, const int max_chan_width, const DeviceGrid& grid, From b0b6f5d80d044113bc6a32e52841a131c45ff37a Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Fri, 15 Sep 2023 11:50:01 -0400 Subject: [PATCH 23/83] minor bug: offset to extra nodes was assigned to zero in the middle of edge generation --- libs/librrgraph/src/base/check_rr_graph.cpp | 2 +- vpr/src/route/rr_graph.cpp | 33 +++++++++++---------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/libs/librrgraph/src/base/check_rr_graph.cpp b/libs/librrgraph/src/base/check_rr_graph.cpp index e51e8a6c8e6..8ac769f8004 100644 --- a/libs/librrgraph/src/base/check_rr_graph.cpp +++ b/libs/librrgraph/src/base/check_rr_graph.cpp @@ -488,7 +488,7 @@ void check_rr_node(const RRGraphView& rr_graph, //if a chanx/chany has length 0, it means it is used to connect different dice together //hence, the ptc number can be larger than nodes_per_chan if(xlow != xhigh || ylow != yhigh) { - if (ptc_num > nodes_per_chan) { + if (ptc_num >= nodes_per_chan) { VPR_ERROR(VPR_ERROR_ROUTE, "in check_rr_node: inode %d (type %d) has a ptc_num of %d.\n", inode, rr_type, ptc_num); } diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index 1a4d9ab37cf..cb07a71feb3 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -469,6 +469,7 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, const t_rr_type chan_type, const t_track_to_pin_lookup& track_to_pin_lookup, t_sb_connection_map* sb_conn_map, + vtr::NdMatrix& extra_nodes_count_inter_die_count, const vtr::NdMatrix, 3>& switch_block_conn, const int cost_index_offset, const t_chan_width& nodes_per_chan, @@ -2126,6 +2127,13 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder num_edges = 0; /* Build channels */ VTR_ASSERT(Fs % 3 == 0); + /* + *In case of multi-die FPGAs with custom switchblocks, we map each connection to a new CHANX node with length 0; + *To find track num of newly added nodes, we need to keep index of used nodes for each switchblocks. + */ + vtr::NdMatrix inter_die_track_offset_custom_switchblocks; + inter_die_track_offset_custom_switchblocks.resize(std::array{(size_t)grid.get_num_layers(), grid.width(), grid.height()}, 0); + for (int layer = 0; layer < grid.get_num_layers(); ++layer) { auto& device_ctx = g_vpr_ctx.device(); /* Skip the current die if architecture file specifies that it doesn't require inter-cluster programmable resource routing */ @@ -2143,7 +2151,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder 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, CHANX, track_to_pin_lookup_x, sb_conn_map, switch_block_conn, + build_rr_chan(rr_graph_builder, layer, i, j, CHANX, track_to_pin_lookup_x, sb_conn_map, inter_die_track_offset_custom_switchblocks, switch_block_conn, CHANX_COST_INDEX_START, chan_width, grid, tracks_per_chan, sblock_pattern, Fs / 3, chan_details_x, chan_details_y, @@ -2161,7 +2169,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder } if (j > 0) { int tracks_per_chan = ((is_global_graph) ? 1 : chan_width.y_list[i]); - build_rr_chan(rr_graph_builder, layer, i, j, CHANY, track_to_pin_lookup_y, sb_conn_map, switch_block_conn, + build_rr_chan(rr_graph_builder, layer, i, j, CHANY, track_to_pin_lookup_y, sb_conn_map, inter_die_track_offset_custom_switchblocks, switch_block_conn, CHANX_COST_INDEX_START + num_seg_types_x, chan_width, grid, tracks_per_chan, sblock_pattern, Fs / 3, chan_details_x, chan_details_y, @@ -2180,6 +2188,10 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder } } } + + //clear temp data structures + inter_die_track_offset_custom_switchblocks.clear(); + VTR_LOG("CHAN->CHAN type edge count:%d\n", num_edges); num_edges = 0; std::function update_chan_width = [](t_chan_width*) noexcept {}; @@ -3052,6 +3064,7 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, const t_rr_type chan_type, const t_track_to_pin_lookup& track_to_pin_lookup, t_sb_connection_map* sb_conn_map, + vtr::NdMatrix& extra_nodes_count_inter_die_count, const vtr::NdMatrix, 3>& switch_block_conn, const int cost_index_offset, const t_chan_width& nodes_per_chan, @@ -3096,13 +3109,6 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, custom_switch_block = true; } - /* - *In case of multi-die FPGAs with custom switchblocks, we map each connection to a new CHANX node with length 0; - *To find track num of newly added nodes, we need to keep index of used nodes for each switch blocks. - */ - vtr::NdMatrix inter_die_track_offset_custom_switchblocks; - inter_die_track_offset_custom_switchblocks.resize(std::array{(size_t)grid.get_num_layers(), grid.width(), grid.height()}, 0); - /* Loads up all the routing resource nodes in the current channel segment */ for (int track = 0; track < tracks_per_chan; ++track) { if (seg_details[track].length() == 0) @@ -3150,7 +3156,7 @@ 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, inter_die_track_offset_custom_switchblocks, seg_dimension, max_opposite_chan_width, grid, + opposite_chan_type, extra_nodes_count_inter_die_count, seg_dimension, max_opposite_chan_width, grid, Fs_per_side, sblock_pattern, node, rr_edges_to_create, from_seg_details, to_seg_details, opposite_chan_details, directionality, @@ -3170,7 +3176,7 @@ 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, inter_die_track_offset_custom_switchblocks, seg_dimension, max_opposite_chan_width, grid, + opposite_chan_type, extra_nodes_count_inter_die_count, seg_dimension, max_opposite_chan_width, grid, 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); @@ -3202,7 +3208,7 @@ 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, inter_die_track_offset_custom_switchblocks, seg_dimension, max_chan_width, grid, + chan_type, extra_nodes_count_inter_die_count, seg_dimension, max_chan_width, grid, Fs_per_side, sblock_pattern, node, rr_edges_to_create, from_seg_details, to_seg_details, from_chan_details, directionality, @@ -3238,9 +3244,6 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, rr_graph_builder.set_node_track_num(node, track); rr_graph_builder.set_node_direction(node, seg_details[track].direction()); } - - //clear temp data structures - inter_die_track_offset_custom_switchblocks.clear(); } static void build_inter_die_custom_sb_rr_chan(RRGraphBuilder& rr_graph_builder, From eba99d204de2679d87a85a1ef5501f518cc6d28e Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Fri, 15 Sep 2023 15:08:19 -0400 Subject: [PATCH 24/83] update rr_graph serializer to have NONE as direction for extra chanx nodes --- libs/librrgraph/src/io/gen/rr_graph_uxsdcxx.h | 16 ++++++++++++---- .../src/io/gen/rr_graph_uxsdcxx_capnp.h | 10 +++++++--- .../src/io/gen/rr_graph_uxsdcxx_interface.h | 6 +++--- libs/librrgraph/src/io/rr_graph.xsd | 1 + libs/libvtrcapnproto/gen/rr_graph_uxsdcxx.capnp | 9 +++++---- vpr/src/route/build_switchblocks.cpp | 1 - vpr/src/route/rr_graph2.cpp | 6 +++++- 7 files changed, 33 insertions(+), 16 deletions(-) diff --git a/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx.h b/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx.h index 1d76a479057..3952fe69ab6 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/sara/Desktop/RLPLACE_LOCAL/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd - * Input file: /home/sara/Desktop/RLPLACE_LOCAL/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd - * md5sum of input file: cf10a1fa99fdfc7a455393a2a3cd1426 + * Cmdline: uxsdcxx/uxsdcxx.py /home/sara/Desktop/rr_3d/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd + * Input file: /home/sara/Desktop/rr_3d/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd + * md5sum of input file: f7e40b36c91943d162c8a51368b16c3f */ #include @@ -1569,7 +1569,7 @@ template constexpr const char *lookup_switch_type[] = {"UXSD_INVALID", "mux", "tristate", "pass_gate", "short", "buffer"}; constexpr const char *lookup_pin_type[] = {"UXSD_INVALID", "OPEN", "OUTPUT", "INPUT"}; constexpr const char *lookup_node_type[] = {"UXSD_INVALID", "CHANX", "CHANY", "SOURCE", "SINK", "OPIN", "IPIN"}; -constexpr const char *lookup_node_direction[] = {"UXSD_INVALID", "INC_DIR", "DEC_DIR", "BI_DIR","NONE"}; +constexpr const char *lookup_node_direction[] = {"UXSD_INVALID", "INC_DIR", "DEC_DIR", "BI_DIR", "NONE"}; constexpr const char *lookup_loc_side[] = {"UXSD_INVALID", "LEFT", "RIGHT", "TOP", "BOTTOM", "RIGHT_LEFT", "RIGHT_BOTTOM", "RIGHT_BOTTOM_LEFT", "TOP_RIGHT", "TOP_BOTTOM", "TOP_LEFT", "TOP_RIGHT_BOTTOM", "TOP_RIGHT_LEFT", "TOP_BOTTOM_LEFT", "TOP_RIGHT_BOTTOM_LEFT", "BOTTOM_LEFT"}; /* Lexers(string->token functions) for enums. */ @@ -1763,6 +1763,14 @@ inline enum_node_type lex_enum_node_type(const char *in, bool throw_on_invalid, inline enum_node_direction lex_enum_node_direction(const char *in, bool throw_on_invalid, const std::function * report_error){ unsigned int len = strlen(in); switch(len){ + case 4: + switch(*((triehash_uu32*)&in[0])){ + case onechar('N', 0, 32) | onechar('O', 8, 32) | onechar('N', 16, 32) | onechar('E', 24, 32): + return enum_node_direction::NONE; + break; + default: break; + } + break; case 6: switch(*((triehash_uu32*)&in[0])){ case onechar('B', 0, 32) | onechar('I', 8, 32) | onechar('_', 16, 32) | onechar('D', 24, 32): diff --git a/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx_capnp.h b/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx_capnp.h index 08ffeac7abd..fcbe2cd27fd 100644 --- a/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx_capnp.h +++ b/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx_capnp.h @@ -4,9 +4,9 @@ * https://github.com/duck2/uxsdcxx * Modify only if your build process doesn't involve regenerating this file. * - * Cmdline: uxsdcxx/uxsdcap.py /home/sara/Desktop/RLPLACE_LOCAL/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd - * Input file: /home/sara/Desktop/RLPLACE_LOCAL/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd - * md5sum of input file: cf10a1fa99fdfc7a455393a2a3cd1426 + * Cmdline: uxsdcxx/uxsdcap.py /home/sara/Desktop/rr_3d/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd + * Input file: /home/sara/Desktop/rr_3d/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd + * md5sum of input file: f7e40b36c91943d162c8a51368b16c3f */ #include @@ -238,6 +238,8 @@ inline enum_node_direction conv_enum_node_direction(ucap::NodeDirection e, const return enum_node_direction::DEC_DIR; case ucap::NodeDirection::BI_DIR: return enum_node_direction::BI_DIR; + case ucap::NodeDirection::NONE: + return enum_node_direction::NONE; default: (*report_error)("Unknown enum_node_direction"); throw std::runtime_error("Unreachable!"); @@ -254,6 +256,8 @@ inline ucap::NodeDirection conv_to_enum_node_direction(enum_node_direction e) { return ucap::NodeDirection::DEC_DIR; case enum_node_direction::BI_DIR: return ucap::NodeDirection::BI_DIR; + case enum_node_direction::NONE: + return ucap::NodeDirection::NONE; default: throw std::runtime_error("Unknown enum_node_direction"); } 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 021d78132d5..c8343555ec3 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/sara/Desktop/RLPLACE_LOCAL/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd - * Input file: /home/sara/Desktop/RLPLACE_LOCAL/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd - * md5sum of input file: cf10a1fa99fdfc7a455393a2a3cd1426 + * Cmdline: uxsdcxx/uxsdcxx.py /home/sara/Desktop/rr_3d/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd + * Input file: /home/sara/Desktop/rr_3d/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd + * md5sum of input file: f7e40b36c91943d162c8a51368b16c3f */ #include diff --git a/libs/librrgraph/src/io/rr_graph.xsd b/libs/librrgraph/src/io/rr_graph.xsd index 4c05adfe5d5..403dc3c9cbc 100644 --- a/libs/librrgraph/src/io/rr_graph.xsd +++ b/libs/librrgraph/src/io/rr_graph.xsd @@ -232,6 +232,7 @@ + diff --git a/libs/libvtrcapnproto/gen/rr_graph_uxsdcxx.capnp b/libs/libvtrcapnproto/gen/rr_graph_uxsdcxx.capnp index a96161ab992..c7abe7e04ac 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/sara/Desktop/RLPLACE_LOCAL/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd -# Input file: /home/sara/Desktop/RLPLACE_LOCAL/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd -# md5sum of input file: cf10a1fa99fdfc7a455393a2a3cd1426 +# Cmdline: uxsdcxx/uxsdcap.py /home/sara/Desktop/rr_3d/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd +# Input file: /home/sara/Desktop/rr_3d/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd +# md5sum of input file: f7e40b36c91943d162c8a51368b16c3f -@0xe180df9b6ce517f5; +@0x8b56fc76f51f64b2; using Cxx = import "/capnp/c++.capnp"; $Cxx.namespace("ucap"); @@ -41,6 +41,7 @@ enum NodeDirection { incDir @1; decDir @2; biDir @3; + none @4; } enum LocSide { diff --git a/vpr/src/route/build_switchblocks.cpp b/vpr/src/route/build_switchblocks.cpp index 7b1094f9c03..4b783e6870d 100644 --- a/vpr/src/route/build_switchblocks.cpp +++ b/vpr/src/route/build_switchblocks.cpp @@ -339,7 +339,6 @@ t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_detail continue; } /* now we iterate over all the potential side1->side2 connections */ - //TODO: SM: this must change to TOTAL_SIDES INSTEAD OF SIDES for (e_side from_side : TOTAL_SIDES) { for (e_side to_side : TOTAL_SIDES) { /* Fill appropriate entry of the sb_conns map with vector specifying the wires diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index d17684b73fa..88c9d496ceb 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -2202,7 +2202,11 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, ++edge_count; if (device_ctx.arch_switch_inf[src_switch].directionality() == BI_DIRECTIONAL) { - //todo: SM: should complete this part + //Add reverse edge since bi-directional + rr_edges_to_create.emplace_back(track_to_chanx_node, from_rr_node, src_switch, false); + ++edge_count; + rr_edges_to_create.emplace_back(diff_layer_chanx_node, chanx_to_track_node, src_switch, false); + ++edge_count; } } } From e55ecc88be4f2257e435d8e9907fc0f9dfbc8744 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Thu, 21 Sep 2023 15:33:25 -0400 Subject: [PATCH 25/83] debug: memory leak in rr_node_indices_ fixed --- vpr/src/route/build_switchblocks.cpp | 1 - vpr/src/route/rr_graph2.cpp | 11 +++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/vpr/src/route/build_switchblocks.cpp b/vpr/src/route/build_switchblocks.cpp index 4b783e6870d..ccd6d4e8403 100644 --- a/vpr/src/route/build_switchblocks.cpp +++ b/vpr/src/route/build_switchblocks.cpp @@ -828,7 +828,6 @@ static void compute_wireconn_connections( sb_edge.switch_ind = to_chan_details[to_x][to_y][to_wire].arch_wire_switch(); } else { VTR_ASSERT(from_layer != to_layer); - //TODO: SM: should figure out whether this is correct sb_edge.switch_ind = to_chan_details[to_x][to_y][to_wire].arch_opin_between_dice_switch(); } 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_graph2.cpp b/vpr/src/route/rr_graph2.cpp index 88c9d496ceb..daadd17050c 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -1210,9 +1210,9 @@ void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, continue; } //reserve extra nodes for inter-die track-to-track connection - rr_graph_builder.node_lookup().reserve_nodes(layer, x, y, CHANX, conn_count); + rr_graph_builder.node_lookup().reserve_nodes(layer, y, x, CHANX, conn_count + nodes_per_chan->max); 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, CHANX, nodes_per_chan->max + rr_node_offset); + RRNodeId inode = rr_graph_builder.node_lookup().find_node(layer, y, x, CHANX, nodes_per_chan->max + rr_node_offset); if (!inode) { inode = RRNodeId(*index); ++(*index); @@ -2169,14 +2169,17 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, } } else { //track-to_track connection crossing layer VTR_ASSERT(to_layer != layer); - + //check if current connection is valid, since switchblock pattern is very general, + //we might see invalid layer in connection, so we just skip those + if((layer < 0 || layer >= device_ctx.grid.get_num_layers()) || (to_layer < 0 || to_layer >= device_ctx.grid.get_num_layers())){ + continue; + } /* * In order to connect two tracks in different layers, we need to follow these three steps: * 1) connect "from_track" to extra "chanx" node in the same switchblocks * 2) connect extra "chanx" node located in from_layer to another extra "chanx" node located in to_layer * 3) connect "chanx" node located in to_layer to "to_track" * */ - RRNodeId track_to_chanx_node = rr_graph_builder.node_lookup().find_node(layer, tile_x, tile_y, CHANX, max_chan_width + inter_die_track_offset_custom_switchblocks[layer][tile_x][tile_y]); RRNodeId diff_layer_chanx_node = rr_graph_builder.node_lookup().find_node(to_layer, tile_x, tile_y, CHANX, max_chan_width + inter_die_track_offset_custom_switchblocks[to_layer][tile_x][tile_y]); RRNodeId chanx_to_track_node = rr_graph_builder.node_lookup().find_node(to_layer, to_x, to_y, to_chan_type, to_wire); From 4e8580cf3a1d098de08af2607b5113370cd1c644 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Thu, 21 Sep 2023 15:34:30 -0400 Subject: [PATCH 26/83] make format --- vpr/src/route/rr_graph2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index daadd17050c..830f00a7648 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -2171,7 +2171,7 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, VTR_ASSERT(to_layer != layer); //check if current connection is valid, since switchblock pattern is very general, //we might see invalid layer in connection, so we just skip those - if((layer < 0 || layer >= device_ctx.grid.get_num_layers()) || (to_layer < 0 || to_layer >= device_ctx.grid.get_num_layers())){ + if ((layer < 0 || layer >= device_ctx.grid.get_num_layers()) || (to_layer < 0 || to_layer >= device_ctx.grid.get_num_layers())) { continue; } /* From 1d5eb359bc3b19d1109aef06405695e8c8024c43 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Thu, 21 Sep 2023 16:01:54 -0400 Subject: [PATCH 27/83] generate_rr_graph_serializer --- libs/librrgraph/src/io/gen/rr_graph_uxsdcxx.h | 2 +- libs/librrgraph/src/io/gen/rr_graph_uxsdcxx_capnp.h | 2 +- .../src/io/gen/rr_graph_uxsdcxx_interface.h | 2 +- libs/libvtrcapnproto/gen/rr_graph_uxsdcxx.capnp | 12 ++---------- 4 files changed, 5 insertions(+), 13 deletions(-) diff --git a/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx.h b/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx.h index 5df722b0f2d..9bbd72b7f83 100644 --- a/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx.h +++ b/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx.h @@ -6,7 +6,7 @@ * * Cmdline: uxsdcxx/uxsdcxx.py /home/sara/Desktop/rr_3d/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd * Input file: /home/sara/Desktop/rr_3d/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd - * md5sum of input file: f7e40b36c91943d162c8a51368b16c3f + * md5sum of input file: aad09e42e426be6012c2f65ddb636cd0 */ #include diff --git a/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx_capnp.h b/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx_capnp.h index 0ae77416f67..892f6cc96e0 100644 --- a/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx_capnp.h +++ b/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx_capnp.h @@ -6,7 +6,7 @@ * * Cmdline: uxsdcxx/uxsdcap.py /home/sara/Desktop/rr_3d/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd * Input file: /home/sara/Desktop/rr_3d/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd - * md5sum of input file: f7e40b36c91943d162c8a51368b16c3f + * md5sum of input file: aad09e42e426be6012c2f65ddb636cd0 */ #include 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 0a41d8a5f8e..f5ac89cb69a 100644 --- a/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx_interface.h +++ b/libs/librrgraph/src/io/gen/rr_graph_uxsdcxx_interface.h @@ -6,7 +6,7 @@ * * Cmdline: uxsdcxx/uxsdcxx.py /home/sara/Desktop/rr_3d/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd * Input file: /home/sara/Desktop/rr_3d/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd - * md5sum of input file: f7e40b36c91943d162c8a51368b16c3f + * md5sum of input file: aad09e42e426be6012c2f65ddb636cd0 */ #include diff --git a/libs/libvtrcapnproto/gen/rr_graph_uxsdcxx.capnp b/libs/libvtrcapnproto/gen/rr_graph_uxsdcxx.capnp index a0a5ae568d9..fde9be1a085 100644 --- a/libs/libvtrcapnproto/gen/rr_graph_uxsdcxx.capnp +++ b/libs/libvtrcapnproto/gen/rr_graph_uxsdcxx.capnp @@ -2,19 +2,11 @@ # https://github.com/duck2/uxsdcxx # Modify only if your build process doesn't involve regenerating this file. # -<<<<<<< HEAD # Cmdline: uxsdcxx/uxsdcap.py /home/sara/Desktop/rr_3d/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd # Input file: /home/sara/Desktop/rr_3d/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd -# md5sum of input file: f7e40b36c91943d162c8a51368b16c3f +# md5sum of input file: aad09e42e426be6012c2f65ddb636cd0 -@0x8b56fc76f51f64b2; -======= -# Cmdline: uxsdcxx/uxsdcap.py /home/smahmoudi/Desktop/vtr/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd -# Input file: /home/smahmoudi/Desktop/vtr/vtr-verilog-to-routing/libs/librrgraph/src/io/rr_graph.xsd -# md5sum of input file: bf49388f038e0d0e4a12403ebb964b42 - -@0xf7009c96d0510b05; ->>>>>>> 37d59288324e5373898ad76c77a114ae0b1e91f1 +@0x8112499188102de5; using Cxx = import "/capnp/c++.capnp"; $Cxx.namespace("ucap"); From 96aed461451013f39f75d4f35f35a89e5ddd2c6d Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Thu, 21 Sep 2023 16:33:27 -0400 Subject: [PATCH 28/83] resolved conflicts --- vpr/src/route/rr_graph.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index 050a5df722a..0996def0b9d 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -2147,15 +2147,12 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder num_edges = 0; /* Build channels */ VTR_ASSERT(Fs % 3 == 0); -<<<<<<< HEAD /* *In case of multi-die FPGAs with custom switchblocks, we map each connection to a new CHANX node with length 0; *To find track num of newly added nodes, we need to keep index of used nodes for each switchblocks. */ vtr::NdMatrix inter_die_track_offset_custom_switchblocks; inter_die_track_offset_custom_switchblocks.resize(std::array{(size_t)grid.get_num_layers(), grid.width(), grid.height()}, 0); -======= ->>>>>>> 37d59288324e5373898ad76c77a114ae0b1e91f1 for (int layer = 0; layer < grid.get_num_layers(); ++layer) { auto& device_ctx = g_vpr_ctx.device(); From f0d29f16f9ed332369dc7f0a1982dcafd6bb4142 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Thu, 21 Sep 2023 17:18:38 -0400 Subject: [PATCH 29/83] add support to read back rr graph with NONE direction CHANX nodes --- libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h b/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h index 0472be4a37a..9348da20b13 100644 --- a/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h +++ b/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h @@ -1883,6 +1883,8 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { return Direction::DEC; case uxsd::enum_node_direction::BI_DIR: return Direction::BIDIR; + case uxsd::enum_node_direction::NONE: + return Direction::NONE; default: report_error( "Invalid node direction %d", direction); From 6e44ce0bd3ea5fd9961683f30b3ea0b2e20ebe89 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Tue, 3 Oct 2023 20:06:44 -0400 Subject: [PATCH 30/83] add one extra node per one destination in each switchblocks --- vpr/src/route/build_switchblocks.h | 6 +++ vpr/src/route/rr_graph.cpp | 56 ++++++++----------- vpr/src/route/rr_graph2.cpp | 86 ++++++++++++++++++++---------- vpr/src/route/rr_graph2.h | 9 ++-- 4 files changed, 93 insertions(+), 64 deletions(-) diff --git a/vpr/src/route/build_switchblocks.h b/vpr/src/route/build_switchblocks.h index 15f8318f681..b064bc51294 100644 --- a/vpr/src/route/build_switchblocks.h +++ b/vpr/src/route/build_switchblocks.h @@ -82,6 +82,12 @@ struct t_switchblock_edge { short to_wire_layer; }; +/** @brief Contain required information to create track-to-track connection in switchblocks in multi-die FPGAs **/ +struct t_inter_die_switchblock_edge{ + std::vector from_track; // keeps the tracks that should connect to the same track in another layer + short offset_to_extra_chanx_node = -1; //index to length-0 extra node available in the switchblock +}; + /* Switchblock connections are made as [x][y][from_side][to_side][from_wire_ind]. * The Switchblock_Lookup class specifies these dimensions. * Furthermore, a source_wire at a given 5-d coordinate may connect to multiple destination wires so the value diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index 0996def0b9d..f9a6d1675aa 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -188,7 +188,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder const t_track_to_pin_lookup& track_to_pin_lookup_y, const t_pin_to_track_lookup& opin_to_track_map, const vtr::NdMatrix, 3>& switch_block_conn, - const vtr::NdMatrix& extra_nodes_count_inter_die_count, + const vtr::NdMatrix multi_layer_track_conn, t_sb_connection_map* sb_conn_map, const DeviceGrid& grid, const int Fs, @@ -469,7 +469,7 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, const t_rr_type chan_type, const t_track_to_pin_lookup& track_to_pin_lookup, t_sb_connection_map* sb_conn_map, - vtr::NdMatrix& extra_nodes_count_inter_die_count, + const vtr::NdMatrix multi_layer_track_conn, const vtr::NdMatrix, 3>& switch_block_conn, const int cost_index_offset, const t_chan_width& nodes_per_chan, @@ -488,7 +488,6 @@ 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 vtr::NdMatrix& extra_nodes_count_inter_die_count, const int const_index_offset, const t_chan_width& nodes_per_chan, const t_chan_details& chan_details_x); @@ -1263,14 +1262,14 @@ static void build_rr_graph(const t_graph_type graph_type, /* END SB LOOKUP */ /* Add extra nodes to switch blocks for multi-layer FPGAs with custom switch blocks that define track-to_track connections */ - vtr::NdMatrix extra_nodes_count; + vtr::NdMatrix multi_layer_track_conn; //keeps the extra nodes offset and drivers for each destination track auto& grid_ctx = device_ctx.grid; - extra_nodes_count.resize(std::array{(size_t)grid_ctx.get_num_layers(), grid.width(), grid.height()}, 0); + multi_layer_track_conn.resize(std::array{(size_t)grid_ctx.get_num_layers(), grid.width(), grid.height(), (size_t) max_chan_width, 2}); if (grid.get_num_layers() > 1 && sb_type == CUSTOM) { //keep how many nodes each switchblock requires - get_number_track_to_track_intra_die_conn(extra_nodes_count, sb_conn_map); - alloc_and_load_inter_die_rr_node_indices(device_ctx.rr_graph_builder, &nodes_per_chan, grid, extra_nodes_count, &num_rr_nodes); + get_number_track_to_track_inter_die_conn(multi_layer_track_conn, sb_conn_map, device_ctx.rr_graph_builder); + alloc_and_load_inter_die_rr_node_indices(device_ctx.rr_graph_builder, &nodes_per_chan, grid, multi_layer_track_conn, &num_rr_nodes); device_ctx.rr_graph_builder.resize_nodes(num_rr_nodes); } @@ -1362,7 +1361,7 @@ static void build_rr_graph(const t_graph_type graph_type, chan_details_x, chan_details_y, track_to_pin_lookup_x, track_to_pin_lookup_y, opin_to_track_map, - switch_block_conn, extra_nodes_count, sb_conn_map, grid, Fs, unidir_sb_pattern, + switch_block_conn, multi_layer_track_conn, sb_conn_map, grid, Fs, unidir_sb_pattern, Fc_out, Fc_xofs, Fc_yofs, nodes_per_chan, wire_to_arch_ipin_switch, @@ -1465,7 +1464,7 @@ static void build_rr_graph(const t_graph_type graph_type, sb_conn_map = nullptr; } - extra_nodes_count.clear(); + multi_layer_track_conn.clear(); track_to_pin_lookup_x.clear(); track_to_pin_lookup_y.clear(); @@ -2022,7 +2021,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder const t_track_to_pin_lookup& track_to_pin_lookup_y, const t_pin_to_track_lookup& opin_to_track_map, const vtr::NdMatrix, 3>& switch_block_conn, - const vtr::NdMatrix& extra_nodes_count_inter_die_count, + const vtr::NdMatrix multi_layer_track_conn, t_sb_connection_map* sb_conn_map, const DeviceGrid& grid, const int Fs, @@ -2147,12 +2146,6 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder num_edges = 0; /* Build channels */ VTR_ASSERT(Fs % 3 == 0); - /* - *In case of multi-die FPGAs with custom switchblocks, we map each connection to a new CHANX node with length 0; - *To find track num of newly added nodes, we need to keep index of used nodes for each switchblocks. - */ - vtr::NdMatrix inter_die_track_offset_custom_switchblocks; - inter_die_track_offset_custom_switchblocks.resize(std::array{(size_t)grid.get_num_layers(), grid.width(), grid.height()}, 0); for (int layer = 0; layer < grid.get_num_layers(); ++layer) { auto& device_ctx = g_vpr_ctx.device(); @@ -2166,12 +2159,12 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder 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()); - build_inter_die_custom_sb_rr_chan(rr_graph_builder, layer, i, j, extra_nodes_count_inter_die_count, CHANX_COST_INDEX_START, chan_width, chan_details_x); + 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, CHANX, track_to_pin_lookup_x, sb_conn_map, inter_die_track_offset_custom_switchblocks, switch_block_conn, + build_rr_chan(rr_graph_builder, layer, i, j, CHANX, track_to_pin_lookup_x, sb_conn_map, multi_layer_track_conn, switch_block_conn, CHANX_COST_INDEX_START, chan_width, grid, tracks_per_chan, sblock_pattern, Fs / 3, chan_details_x, chan_details_y, @@ -2189,7 +2182,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder } if (j > 0) { int tracks_per_chan = ((is_global_graph) ? 1 : chan_width.y_list[i]); - build_rr_chan(rr_graph_builder, layer, i, j, CHANY, track_to_pin_lookup_y, sb_conn_map, inter_die_track_offset_custom_switchblocks, switch_block_conn, + build_rr_chan(rr_graph_builder, layer, i, j, CHANY, track_to_pin_lookup_y, sb_conn_map, multi_layer_track_conn, switch_block_conn, CHANX_COST_INDEX_START + num_seg_types_x, chan_width, grid, tracks_per_chan, sblock_pattern, Fs / 3, chan_details_x, chan_details_y, @@ -2209,9 +2202,6 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder } } - //clear temp data structures - inter_die_track_offset_custom_switchblocks.clear(); - VTR_LOG("CHAN->CHAN type edge count:%d\n", num_edges); num_edges = 0; std::function update_chan_width = [](t_chan_width*) noexcept {}; @@ -3085,7 +3075,7 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, const t_rr_type chan_type, const t_track_to_pin_lookup& track_to_pin_lookup, t_sb_connection_map* sb_conn_map, - vtr::NdMatrix& extra_nodes_count_inter_die_count, + const vtr::NdMatrix multi_layer_track_conn, const vtr::NdMatrix, 3>& switch_block_conn, const int cost_index_offset, const t_chan_width& nodes_per_chan, @@ -3177,7 +3167,7 @@ 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, extra_nodes_count_inter_die_count, seg_dimension, max_opposite_chan_width, grid, + opposite_chan_type, multi_layer_track_conn, seg_dimension, max_opposite_chan_width, grid, Fs_per_side, sblock_pattern, node, rr_edges_to_create, from_seg_details, to_seg_details, opposite_chan_details, directionality, @@ -3197,7 +3187,7 @@ 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, extra_nodes_count_inter_die_count, seg_dimension, max_opposite_chan_width, grid, + opposite_chan_type, multi_layer_track_conn, seg_dimension, max_opposite_chan_width, grid, 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); @@ -3229,7 +3219,7 @@ 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, extra_nodes_count_inter_die_count, seg_dimension, max_chan_width, grid, + chan_type, multi_layer_track_conn, seg_dimension, max_chan_width, grid, Fs_per_side, sblock_pattern, node, rr_edges_to_create, from_seg_details, to_seg_details, from_chan_details, directionality, @@ -3271,7 +3261,6 @@ 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 vtr::NdMatrix& extra_nodes_count_inter_die_count, const int const_index_offset, const t_chan_width& nodes_per_chan, const t_chan_details& chan_details_x) { @@ -3280,13 +3269,9 @@ static void build_inter_die_custom_sb_rr_chan(RRGraphBuilder& rr_graph_builder, /* Loads up all the extra routing resource nodes required to support multi-die custom switch blocks */ int start_track = nodes_per_chan.max; - int conn_count = extra_nodes_count_inter_die_count[layer][x_coord][y_coord]; - - if (conn_count == 0) { - return; //no new node required in this switchblock - } + int offset = 0; - for (int offset = 0; offset < conn_count; offset++) { + while (true) { RRNodeId node = rr_graph_builder.node_lookup().find_node(layer, x_coord, y_coord, CHANX, start_track + offset); if (node) { rr_graph_builder.set_node_layer(node, layer); @@ -3302,6 +3287,11 @@ static void build_inter_die_custom_sb_rr_chan(RRGraphBuilder& rr_graph_builder, rr_graph_builder.set_node_type(node, CHANX); rr_graph_builder.set_node_track_num(node, start_track + offset); rr_graph_builder.set_node_direction(node, Direction::NONE); + + offset++; + } + else{ + break; } } } diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index 830f00a7648..bffe00fa3b4 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -105,7 +105,7 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, const int to_x, const int to_y, const t_rr_type to_chan_type, - vtr::NdMatrix& inter_die_track_offset_custom_switchblocks, + const vtr::NdMatrix multi_layer_track_conn, const int switch_override, t_sb_connection_map* sb_conn_map, t_rr_edge_info_set& rr_edges_to_create, @@ -120,7 +120,7 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, const t_rr_type to_chan_type, const e_side from_side, const e_side to_side, - vtr::NdMatrix& inter_die_track_offset_custom_switchblocks, + const vtr::NdMatrix multi_layer_track_conn, const int swtich_override, t_sb_connection_map* sb_conn_map, RRNodeId from_rr_node, @@ -1141,12 +1141,14 @@ static void load_chan_rr_indices(const int max_chan_width, } } -void get_number_track_to_track_intra_die_conn(vtr::NdMatrix& extra_node_count, - t_sb_connection_map* sb_conn_map) { +void get_number_track_to_track_inter_die_conn(vtr::NdMatrix& multi_layer_track_conn, + t_sb_connection_map* sb_conn_map, + RRGraphBuilder& rr_graph_builder) { auto& grid_ctx = g_vpr_ctx.device().grid; for (auto layer = 0; layer < grid_ctx.get_num_layers(); layer++) { for (size_t x = 0; x < grid_ctx.width(); x++) { for (size_t y = 0; y < grid_ctx.height(); y++) { + int curr_switchblocks_offset = 0; for (auto from_side : TOTAL_SIDES) { for (auto to_side : TOTAL_SIDES) { if (from_side < NUM_SIDES && to_side < NUM_SIDES) { //this connection is not crossing any layer @@ -1162,14 +1164,29 @@ void get_number_track_to_track_intra_die_conn(vtr::NdMatrix& extra_node_ //this connection doesn't cross any layer, no new node is required continue; } else { - //check if both from_layer and to_layer are valid, might not be valid since patterns in switchblocks are very general - if (conn_vector[iconn].from_wire_layer >= 0 && conn_vector[iconn].from_wire_layer < grid_ctx.get_num_layers()) { - if (conn_vector[iconn].to_wire_layer >= 0 && conn_vector[iconn].to_wire_layer < grid_ctx.get_num_layers()) { - //add an extra node for source layer - extra_node_count[conn_vector[iconn].from_wire_layer][x][y]++; - //add an extra node for destination layer - extra_node_count[conn_vector[iconn].to_wire_layer][x][y]++; + //check if both from_node and to_node exists in the rr-graph + + //CHANY -> CHANX connection + RRNodeId from_inode = rr_graph_builder.node_lookup().find_node(conn_vector[iconn].from_wire_layer, x, y, CHANY, conn_vector[iconn].from_wire_layer); + RRNodeId to_inode = rr_graph_builder.node_lookup().find_node(conn_vector[iconn].to_wire_layer, x, y, CHANX, conn_vector[iconn].to_wire); + if(from_inode && to_inode){ + if(multi_layer_track_conn[conn_vector[iconn].to_wire_layer][x][y][conn_vector[iconn].to_wire][1].offset_to_extra_chanx_node == -1){ + multi_layer_track_conn[conn_vector[iconn].to_wire_layer][x][y][conn_vector[iconn].to_wire][1].offset_to_extra_chanx_node = curr_switchblocks_offset; + curr_switchblocks_offset++; } + multi_layer_track_conn[conn_vector[iconn].to_wire_layer][x][y][conn_vector[iconn].to_wire][1].from_track.push_back(conn_vector[iconn].from_wire_layer); + + } + + //CHANX -> CHANY connection + from_inode = rr_graph_builder.node_lookup().find_node(conn_vector[iconn].from_wire_layer, x, y, CHANX, conn_vector[iconn].from_wire_layer); + to_inode = rr_graph_builder.node_lookup().find_node(conn_vector[iconn].to_wire_layer, x, y, CHANY, conn_vector[iconn].to_wire); + if(from_inode && to_inode){ + if(multi_layer_track_conn[conn_vector[iconn].to_wire_layer][x][y][conn_vector[iconn].to_wire][0].offset_to_extra_chanx_node == -1){ + multi_layer_track_conn[conn_vector[iconn].to_wire_layer][x][y][conn_vector[iconn].to_wire][0].offset_to_extra_chanx_node = curr_switchblocks_offset; + curr_switchblocks_offset++; + } + multi_layer_track_conn[conn_vector[iconn].to_wire_layer][x][y][conn_vector[iconn].to_wire][0].from_track.push_back(conn_vector[iconn].from_wire_layer); } } } @@ -1185,7 +1202,7 @@ void get_number_track_to_track_intra_die_conn(vtr::NdMatrix& extra_node_ void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, const t_chan_width* nodes_per_chan, const DeviceGrid& grid, - const vtr::NdMatrix& extra_nodes_count, + const vtr::NdMatrix& multi_layer_track_conn, int* index) { /* * In case of multi-die FPGAs, we add extra nodes (can be either CHANX OR CHANY, used CHANX) to @@ -1204,11 +1221,23 @@ void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, } for (size_t y = 0; y < grid.height() - 1; ++y) { for (size_t x = 1; x < grid.width() - 1; ++x) { + //count how many track-to-track connection go from current layer to other layers - int conn_count = extra_nodes_count[layer][x][y]; - if (conn_count == 0) { + int conn_count = -1; + for(int itrack = 0; itrack < nodes_per_chan->max; itrack++){ + if(conn_count < multi_layer_track_conn[layer][x][y][itrack][0].offset_to_extra_chanx_node){ + conn_count = multi_layer_track_conn[layer][x][y][itrack][0].offset_to_extra_chanx_node; + } + if(conn_count < multi_layer_track_conn[layer][x][y][itrack][1].offset_to_extra_chanx_node){ + conn_count = multi_layer_track_conn[layer][x][y][itrack][1].offset_to_extra_chanx_node; + } + } + + //skip if no connection is required + if (conn_count == -1) { continue; } + //reserve extra nodes for inter-die track-to-track connection rr_graph_builder.node_lookup().reserve_nodes(layer, y, x, CHANX, conn_count + nodes_per_chan->max); for (int rr_node_offset = 0; rr_node_offset < conn_count; rr_node_offset++) { @@ -1799,7 +1828,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, const t_rr_type from_type, const int to_seg, const t_rr_type to_type, - vtr::NdMatrix& inter_die_track_offset_custom_switchblocks, + const vtr::NdMatrix multi_layer_track_conn, const int chan_len, const int max_chan_width, const DeviceGrid& grid, @@ -1941,7 +1970,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, if (custom_switch_block) { if (Direction::DEC == from_seg_details[from_track].direction() || BI_DIRECTIONAL == directionality) { num_conn += get_track_to_chan_seg(rr_graph_builder, layer, max_chan_width, from_track, to_chan, to_seg, - to_type, from_side_a, to_side, inter_die_track_offset_custom_switchblocks, + to_type, from_side_a, to_side, multi_layer_track_conn, switch_override, sb_conn_map, from_rr_node, rr_edges_to_create); } @@ -1979,7 +2008,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, if (custom_switch_block) { if (Direction::INC == from_seg_details[from_track].direction() || BI_DIRECTIONAL == directionality) { num_conn += get_track_to_chan_seg(rr_graph_builder, layer, max_chan_width, from_track, to_chan, to_seg, - to_type, from_side_b, to_side, inter_die_track_offset_custom_switchblocks, + to_type, from_side_b, to_side, multi_layer_track_conn, switch_override, sb_conn_map, from_rr_node, rr_edges_to_create); } @@ -2125,7 +2154,7 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, const int to_x, const int to_y, const t_rr_type to_chan_type, - vtr::NdMatrix& inter_die_track_offset_custom_switchblocks, + const vtr::NdMatrix multi_layer_track_conn, const int switch_override, t_sb_connection_map* sb_conn_map, t_rr_edge_info_set& rr_edges_to_create, @@ -2174,24 +2203,27 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, if ((layer < 0 || layer >= device_ctx.grid.get_num_layers()) || (to_layer < 0 || to_layer >= device_ctx.grid.get_num_layers())) { continue; } + + if(multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type-CHANX)].offset_to_extra_chanx_node == -1){ + //either source track or destination track doesn't exist + continue; + } + /* * In order to connect two tracks in different layers, we need to follow these three steps: * 1) connect "from_track" to extra "chanx" node in the same switchblocks * 2) connect extra "chanx" node located in from_layer to another extra "chanx" node located in to_layer * 3) connect "chanx" node located in to_layer to "to_track" * */ - RRNodeId track_to_chanx_node = rr_graph_builder.node_lookup().find_node(layer, tile_x, tile_y, CHANX, max_chan_width + inter_die_track_offset_custom_switchblocks[layer][tile_x][tile_y]); - RRNodeId diff_layer_chanx_node = rr_graph_builder.node_lookup().find_node(to_layer, tile_x, tile_y, CHANX, max_chan_width + inter_die_track_offset_custom_switchblocks[to_layer][tile_x][tile_y]); + int offset = multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type-CHANX)].offset_to_extra_chanx_node; + RRNodeId track_to_chanx_node = rr_graph_builder.node_lookup().find_node(layer, tile_x, tile_y, CHANX, max_chan_width + offset); + RRNodeId diff_layer_chanx_node = rr_graph_builder.node_lookup().find_node(to_layer, tile_x, tile_y, CHANX, max_chan_width + offset); RRNodeId chanx_to_track_node = rr_graph_builder.node_lookup().find_node(to_layer, to_x, to_y, to_chan_type, to_wire); if (!track_to_chanx_node || !diff_layer_chanx_node || !chanx_to_track_node) { continue; } - //increase the offset since we have used two new extra nodes - inter_die_track_offset_custom_switchblocks[layer][tile_x][tile_y]++; - inter_die_track_offset_custom_switchblocks[to_layer][tile_x][tile_y]++; - //Apply any switch overrides if (should_apply_switch_override(switch_override)) { src_switch = switch_override; @@ -2230,7 +2262,7 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, const t_rr_type to_chan_type, const e_side from_side, const e_side to_side, - vtr::NdMatrix& inter_die_track_offset_custom_switchblocks, + const vtr::NdMatrix multi_layer_track_conn, const int switch_override, t_sb_connection_map* sb_conn_map, RRNodeId from_rr_node, @@ -2267,7 +2299,7 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, to_x, to_y, to_chan_type, - inter_die_track_offset_custom_switchblocks, + multi_layer_track_conn, switch_override, sb_conn_map, rr_edges_to_create, @@ -2287,7 +2319,7 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, to_x, to_y, to_chan_type, - inter_die_track_offset_custom_switchblocks, + multi_layer_track_conn, switch_override, sb_conn_map, rr_edges_to_create, diff --git a/vpr/src/route/rr_graph2.h b/vpr/src/route/rr_graph2.h index 0342ad428d3..8374e77c1fd 100644 --- a/vpr/src/route/rr_graph2.h +++ b/vpr/src/route/rr_graph2.h @@ -32,7 +32,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 t_chan_width* nodes_per_chan, const DeviceGrid& grid, - const vtr::NdMatrix& extra_nodes_count, + const vtr::NdMatrix& multi_layer_track_conn, int* index); void alloc_and_load_tile_rr_node_indices(RRGraphBuilder& rr_graph_builder, @@ -70,8 +70,9 @@ int get_rr_node_index(const t_rr_node_indices& L_rr_node_indices, e_side side = NUM_SIDES); //Return how many connection inside switch blocks located at each grid location are going to a different layer -void get_number_track_to_track_intra_die_conn(vtr::NdMatrix& extra_node_count, - t_sb_connection_map* sb_conn_map); +void get_number_track_to_track_inter_die_conn(vtr::NdMatrix& multi_layer_track_conn, + t_sb_connection_map* sb_conn_map, + RRGraphBuilder& rr_graph_builder); int find_average_rr_node_index(int device_width, int device_height, @@ -187,7 +188,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, const t_rr_type from_type, const int to_seg, const t_rr_type to_type, - vtr::NdMatrix& inter_die_track_offset_custom_switchblocks, + const vtr::NdMatrix multi_layer_track_conn, const int chan_len, const int max_chan_width, const DeviceGrid& grid, From 830965cad505822221ad60cb04c0853e6d80ee7e Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Thu, 5 Oct 2023 16:47:24 -0400 Subject: [PATCH 31/83] debug: extra nodes was calculated incorrectly --- vpr/src/route/rr_graph.cpp | 6 ++++-- vpr/src/route/rr_graph2.cpp | 32 +++++++++++++++----------------- vpr/src/route/rr_graph2.h | 4 ++-- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index f9a6d1675aa..53e599086c6 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -1268,9 +1268,11 @@ static void build_rr_graph(const t_graph_type graph_type, if (grid.get_num_layers() > 1 && sb_type == CUSTOM) { //keep how many nodes each switchblock requires - get_number_track_to_track_inter_die_conn(multi_layer_track_conn, sb_conn_map, device_ctx.rr_graph_builder); - alloc_and_load_inter_die_rr_node_indices(device_ctx.rr_graph_builder, &nodes_per_chan, grid, multi_layer_track_conn, &num_rr_nodes); + auto extra_nodes_per_switchblock = get_number_track_to_track_inter_die_conn(multi_layer_track_conn, sb_conn_map, device_ctx.rr_graph_builder); + //allocate new nodes in each switchblocks + alloc_and_load_inter_die_rr_node_indices(device_ctx.rr_graph_builder, &nodes_per_chan, grid, extra_nodes_per_switchblock, &num_rr_nodes); device_ctx.rr_graph_builder.resize_nodes(num_rr_nodes); + extra_nodes_per_switchblock.clear(); } /* START IPIN MAP */ diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index bffe00fa3b4..7cc3484d0bf 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -1141,14 +1141,18 @@ static void load_chan_rr_indices(const int max_chan_width, } } -void get_number_track_to_track_inter_die_conn(vtr::NdMatrix& multi_layer_track_conn, +vtr::NdMatrix get_number_track_to_track_inter_die_conn(vtr::NdMatrix& multi_layer_track_conn, t_sb_connection_map* sb_conn_map, RRGraphBuilder& rr_graph_builder) { + auto& grid_ctx = g_vpr_ctx.device().grid; - for (auto layer = 0; layer < grid_ctx.get_num_layers(); layer++) { + vtr::NdMatrix extra_nodes_per_switchblocks; + extra_nodes_per_switchblocks.resize(std::array{grid_ctx.width(), grid_ctx.height()}); + + for (size_t y = 0; y < grid_ctx.height(); y++) { for (size_t x = 0; x < grid_ctx.width(); x++) { - for (size_t y = 0; y < grid_ctx.height(); y++) { - int curr_switchblocks_offset = 0; + int curr_switchblocks_offset =0; + for (auto layer = 0; layer < grid_ctx.get_num_layers(); layer++){ for (auto from_side : TOTAL_SIDES) { for (auto to_side : TOTAL_SIDES) { if (from_side < NUM_SIDES && to_side < NUM_SIDES) { //this connection is not crossing any layer @@ -1174,7 +1178,7 @@ void get_number_track_to_track_inter_die_conn(vtr::NdMatrix& multi_layer_track_conn, + const vtr::NdMatrix& extra_nodes_per_switchblock, int* index) { /* * In case of multi-die FPGAs, we add extra nodes (can be either CHANX OR CHANY, used CHANX) to @@ -1223,18 +1229,10 @@ void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, for (size_t x = 1; x < grid.width() - 1; ++x) { //count how many track-to-track connection go from current layer to other layers - int conn_count = -1; - for(int itrack = 0; itrack < nodes_per_chan->max; itrack++){ - if(conn_count < multi_layer_track_conn[layer][x][y][itrack][0].offset_to_extra_chanx_node){ - conn_count = multi_layer_track_conn[layer][x][y][itrack][0].offset_to_extra_chanx_node; - } - if(conn_count < multi_layer_track_conn[layer][x][y][itrack][1].offset_to_extra_chanx_node){ - conn_count = multi_layer_track_conn[layer][x][y][itrack][1].offset_to_extra_chanx_node; - } - } + int conn_count = extra_nodes_per_switchblock[x][y]; //skip if no connection is required - if (conn_count == -1) { + if (conn_count == 0) { continue; } diff --git a/vpr/src/route/rr_graph2.h b/vpr/src/route/rr_graph2.h index 8374e77c1fd..4fe9a13fe0f 100644 --- a/vpr/src/route/rr_graph2.h +++ b/vpr/src/route/rr_graph2.h @@ -32,7 +32,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 t_chan_width* nodes_per_chan, const DeviceGrid& grid, - const vtr::NdMatrix& multi_layer_track_conn, + const vtr::NdMatrix& extra_nodes_per_switchblock, int* index); void alloc_and_load_tile_rr_node_indices(RRGraphBuilder& rr_graph_builder, @@ -70,7 +70,7 @@ int get_rr_node_index(const t_rr_node_indices& L_rr_node_indices, e_side side = NUM_SIDES); //Return how many connection inside switch blocks located at each grid location are going to a different layer -void get_number_track_to_track_inter_die_conn(vtr::NdMatrix& multi_layer_track_conn, +vtr::NdMatrix get_number_track_to_track_inter_die_conn(vtr::NdMatrix& multi_layer_track_conn, t_sb_connection_map* sb_conn_map, RRGraphBuilder& rr_graph_builder); From 45b890bafce6f9cd912605185fe680b48bcd357a Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Thu, 5 Oct 2023 19:58:45 -0400 Subject: [PATCH 32/83] avoid adding same edge between chanx->chanx multiple times --- vpr/src/route/rr_graph.cpp | 45 +++++++++++++++++++++++++++++++++---- vpr/src/route/rr_graph2.cpp | 28 ++++++++++++++--------- vpr/src/route/rr_graph2.h | 2 +- 3 files changed, 59 insertions(+), 16 deletions(-) diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index 53e599086c6..99d3026d58d 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -188,7 +188,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder const t_track_to_pin_lookup& track_to_pin_lookup_y, const t_pin_to_track_lookup& opin_to_track_map, const vtr::NdMatrix, 3>& switch_block_conn, - const vtr::NdMatrix multi_layer_track_conn, + const vtr::NdMatrix& multi_layer_track_conn, t_sb_connection_map* sb_conn_map, const DeviceGrid& grid, const int Fs, @@ -469,7 +469,7 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, const t_rr_type chan_type, const t_track_to_pin_lookup& track_to_pin_lookup, t_sb_connection_map* sb_conn_map, - const vtr::NdMatrix multi_layer_track_conn, + const vtr::NdMatrix& multi_layer_track_conn, const vtr::NdMatrix, 3>& switch_block_conn, const int cost_index_offset, const t_chan_width& nodes_per_chan, @@ -2023,7 +2023,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder const t_track_to_pin_lookup& track_to_pin_lookup_y, const t_pin_to_track_lookup& opin_to_track_map, const vtr::NdMatrix, 3>& switch_block_conn, - const vtr::NdMatrix multi_layer_track_conn, + const vtr::NdMatrix& multi_layer_track_conn, t_sb_connection_map* sb_conn_map, const DeviceGrid& grid, const int Fs, @@ -2204,6 +2204,43 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder } } + if (grid.get_num_layers() > 1 && sb_conn_map != nullptr) { + auto& device_ctx = g_vpr_ctx.device(); + //need to connect extra nodes once to avoid creating same edge multiple times + for(int layer = 0; layer < grid.get_num_layers(); ++layer){ + /* Skip the current die if architecture file specifies that it doesn't require global resource routing */ + if (!device_ctx.inter_cluster_prog_routing_resources.at(layer)) { + continue; + } + /* Start building up edges from die 0*/ + if(layer + 1 >= grid.get_num_layers()){ + continue; + } + int offset = 0; + for (size_t i = 0; i < grid.width() - 1; ++i) { + for (size_t j = 0; j < grid.height() - 1; ++j) { + while (true) { + RRNodeId bottom_die_node = rr_graph_builder.node_lookup().find_node(layer, i, j, CHANX, chan_width.x_max + offset); + RRNodeId top_die_node = rr_graph_builder.node_lookup().find_node(layer + 1, i, j, CHANX, chan_width.x_max + offset); + if (bottom_die_node && top_die_node) { + rr_edges_to_create.emplace_back(bottom_die_node, top_die_node, wire_to_pin_between_dice_switch, false); + offset++; + } + else{ + VTR_ASSERT(!bottom_die_node && !top_die_node); + break; + } + } + } + } + } + //create the actual CHANX->CHANX 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(); + rr_edges_to_create.clear(); + } + VTR_LOG("CHAN->CHAN type edge count:%d\n", num_edges); num_edges = 0; std::function update_chan_width = [](t_chan_width*) noexcept {}; @@ -3077,7 +3114,7 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, const t_rr_type chan_type, const t_track_to_pin_lookup& track_to_pin_lookup, t_sb_connection_map* sb_conn_map, - const vtr::NdMatrix multi_layer_track_conn, + const vtr::NdMatrix& multi_layer_track_conn, const vtr::NdMatrix, 3>& switch_block_conn, const int cost_index_offset, const t_chan_width& nodes_per_chan, diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index 7cc3484d0bf..5344e738858 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -105,7 +105,7 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, const int to_x, const int to_y, const t_rr_type to_chan_type, - const vtr::NdMatrix multi_layer_track_conn, + const vtr::NdMatrix& multi_layer_track_conn, const int switch_override, t_sb_connection_map* sb_conn_map, t_rr_edge_info_set& rr_edges_to_create, @@ -120,7 +120,7 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, const t_rr_type to_chan_type, const e_side from_side, const e_side to_side, - const vtr::NdMatrix multi_layer_track_conn, + const vtr::NdMatrix& multi_layer_track_conn, const int swtich_override, t_sb_connection_map* sb_conn_map, RRNodeId from_rr_node, @@ -1826,7 +1826,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, const t_rr_type from_type, const int to_seg, const t_rr_type to_type, - const vtr::NdMatrix multi_layer_track_conn, + const vtr::NdMatrix& multi_layer_track_conn, const int chan_len, const int max_chan_width, const DeviceGrid& grid, @@ -2152,7 +2152,7 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, const int to_x, const int to_y, const t_rr_type to_chan_type, - const vtr::NdMatrix multi_layer_track_conn, + const vtr::NdMatrix& multi_layer_track_conn, const int switch_override, t_sb_connection_map* sb_conn_map, t_rr_edge_info_set& rr_edges_to_create, @@ -2229,17 +2229,23 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, rr_edges_to_create.emplace_back(from_rr_node, track_to_chanx_node, src_switch, false); ++edge_count; - rr_edges_to_create.emplace_back(track_to_chanx_node, diff_layer_chanx_node, src_switch, false); - ++edge_count; - rr_edges_to_create.emplace_back(diff_layer_chanx_node, chanx_to_track_node, src_switch, false); - ++edge_count; + + //we only add the following edge once for the first driver + VTR_ASSERT(multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type-CHANX)].from_track.size() > 0); + if(multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type-CHANX)].from_track[0] == from_wire) { + rr_edges_to_create.emplace_back(diff_layer_chanx_node, chanx_to_track_node, src_switch, false); + ++edge_count; + } if (device_ctx.arch_switch_inf[src_switch].directionality() == BI_DIRECTIONAL) { //Add reverse edge since bi-directional rr_edges_to_create.emplace_back(track_to_chanx_node, from_rr_node, src_switch, false); ++edge_count; - rr_edges_to_create.emplace_back(diff_layer_chanx_node, chanx_to_track_node, src_switch, false); - ++edge_count; + VTR_ASSERT(multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type-CHANX)].from_track.size() > 0); + if(multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type-CHANX)].from_track[0] == from_wire) { + rr_edges_to_create.emplace_back(diff_layer_chanx_node, chanx_to_track_node, src_switch, false); + ++edge_count; + } } } } @@ -2260,7 +2266,7 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, const t_rr_type to_chan_type, const e_side from_side, const e_side to_side, - const vtr::NdMatrix multi_layer_track_conn, + const vtr::NdMatrix& multi_layer_track_conn, const int switch_override, t_sb_connection_map* sb_conn_map, RRNodeId from_rr_node, diff --git a/vpr/src/route/rr_graph2.h b/vpr/src/route/rr_graph2.h index 4fe9a13fe0f..92f33d1ae19 100644 --- a/vpr/src/route/rr_graph2.h +++ b/vpr/src/route/rr_graph2.h @@ -188,7 +188,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, const t_rr_type from_type, const int to_seg, const t_rr_type to_type, - const vtr::NdMatrix multi_layer_track_conn, + const vtr::NdMatrix& multi_layer_track_conn, const int chan_len, const int max_chan_width, const DeviceGrid& grid, From 5e12d1de331f1afa4ae577ee3d4231087a312f20 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Mon, 9 Oct 2023 19:53:55 -0400 Subject: [PATCH 33/83] avoid adding same edge multiple times --- vpr/src/route/build_switchblocks.h | 1 + vpr/src/route/rr_graph.cpp | 8 ++++---- vpr/src/route/rr_graph2.cpp | 18 +++++++++--------- vpr/src/route/rr_graph2.h | 2 +- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/vpr/src/route/build_switchblocks.h b/vpr/src/route/build_switchblocks.h index b064bc51294..e6e2a64f300 100644 --- a/vpr/src/route/build_switchblocks.h +++ b/vpr/src/route/build_switchblocks.h @@ -86,6 +86,7 @@ struct t_switchblock_edge { struct t_inter_die_switchblock_edge{ std::vector from_track; // keeps the tracks that should connect to the same track in another layer short offset_to_extra_chanx_node = -1; //index to length-0 extra node available in the switchblock + bool connected_to_des = false; }; /* Switchblock connections are made as [x][y][from_side][to_side][from_wire_ind]. diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index 99d3026d58d..aa54650f157 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -188,7 +188,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder const t_track_to_pin_lookup& track_to_pin_lookup_y, const t_pin_to_track_lookup& opin_to_track_map, const vtr::NdMatrix, 3>& switch_block_conn, - const vtr::NdMatrix& multi_layer_track_conn, + vtr::NdMatrix& multi_layer_track_conn, t_sb_connection_map* sb_conn_map, const DeviceGrid& grid, const int Fs, @@ -469,7 +469,7 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, const t_rr_type chan_type, const t_track_to_pin_lookup& track_to_pin_lookup, t_sb_connection_map* sb_conn_map, - const vtr::NdMatrix& multi_layer_track_conn, + vtr::NdMatrix& multi_layer_track_conn, const vtr::NdMatrix, 3>& switch_block_conn, const int cost_index_offset, const t_chan_width& nodes_per_chan, @@ -2023,7 +2023,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder const t_track_to_pin_lookup& track_to_pin_lookup_y, const t_pin_to_track_lookup& opin_to_track_map, const vtr::NdMatrix, 3>& switch_block_conn, - const vtr::NdMatrix& multi_layer_track_conn, + vtr::NdMatrix& multi_layer_track_conn, t_sb_connection_map* sb_conn_map, const DeviceGrid& grid, const int Fs, @@ -3114,7 +3114,7 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, const t_rr_type chan_type, const t_track_to_pin_lookup& track_to_pin_lookup, t_sb_connection_map* sb_conn_map, - const vtr::NdMatrix& multi_layer_track_conn, + vtr::NdMatrix& multi_layer_track_conn, const vtr::NdMatrix, 3>& switch_block_conn, const int cost_index_offset, const t_chan_width& nodes_per_chan, diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index 5344e738858..63471ea21de 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -105,7 +105,7 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, const int to_x, const int to_y, const t_rr_type to_chan_type, - const vtr::NdMatrix& multi_layer_track_conn, + vtr::NdMatrix& multi_layer_track_conn, const int switch_override, t_sb_connection_map* sb_conn_map, t_rr_edge_info_set& rr_edges_to_create, @@ -120,7 +120,7 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, const t_rr_type to_chan_type, const e_side from_side, const e_side to_side, - const vtr::NdMatrix& multi_layer_track_conn, + vtr::NdMatrix& multi_layer_track_conn, const int swtich_override, t_sb_connection_map* sb_conn_map, RRNodeId from_rr_node, @@ -1239,7 +1239,7 @@ void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, //reserve extra nodes for inter-die track-to-track connection rr_graph_builder.node_lookup().reserve_nodes(layer, y, x, CHANX, conn_count + nodes_per_chan->max); for (int rr_node_offset = 0; rr_node_offset < conn_count; rr_node_offset++) { - RRNodeId inode = rr_graph_builder.node_lookup().find_node(layer, y, x, CHANX, nodes_per_chan->max + rr_node_offset); + RRNodeId inode = rr_graph_builder.node_lookup().find_node(layer, x, y, CHANX, nodes_per_chan->max + rr_node_offset); if (!inode) { inode = RRNodeId(*index); ++(*index); @@ -1826,7 +1826,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, const t_rr_type from_type, const int to_seg, const t_rr_type to_type, - const vtr::NdMatrix& multi_layer_track_conn, + vtr::NdMatrix& multi_layer_track_conn, const int chan_len, const int max_chan_width, const DeviceGrid& grid, @@ -2152,7 +2152,7 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, const int to_x, const int to_y, const t_rr_type to_chan_type, - const vtr::NdMatrix& multi_layer_track_conn, + vtr::NdMatrix& multi_layer_track_conn, const int switch_override, t_sb_connection_map* sb_conn_map, t_rr_edge_info_set& rr_edges_to_create, @@ -2230,9 +2230,9 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, rr_edges_to_create.emplace_back(from_rr_node, track_to_chanx_node, src_switch, false); ++edge_count; - //we only add the following edge once for the first driver - VTR_ASSERT(multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type-CHANX)].from_track.size() > 0); - if(multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type-CHANX)].from_track[0] == from_wire) { + //we only add the following edge once for the first driver, otherwise we are adding the same edge multiple times + if(!multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type-CHANX)].connected_to_des) { + multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type-CHANX)].connected_to_des = true; rr_edges_to_create.emplace_back(diff_layer_chanx_node, chanx_to_track_node, src_switch, false); ++edge_count; } @@ -2266,7 +2266,7 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, const t_rr_type to_chan_type, const e_side from_side, const e_side to_side, - const vtr::NdMatrix& multi_layer_track_conn, + vtr::NdMatrix& multi_layer_track_conn, const int switch_override, t_sb_connection_map* sb_conn_map, RRNodeId from_rr_node, diff --git a/vpr/src/route/rr_graph2.h b/vpr/src/route/rr_graph2.h index 92f33d1ae19..cdcb1d797a7 100644 --- a/vpr/src/route/rr_graph2.h +++ b/vpr/src/route/rr_graph2.h @@ -188,7 +188,7 @@ int get_track_to_tracks(RRGraphBuilder& rr_graph_builder, const t_rr_type from_type, const int to_seg, const t_rr_type to_type, - const vtr::NdMatrix& multi_layer_track_conn, + vtr::NdMatrix& multi_layer_track_conn, const int chan_len, const int max_chan_width, const DeviceGrid& grid, From 1ada54ed12de193a5f11c82fc8f4f2f6b09fbaf7 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Mon, 9 Oct 2023 21:16:55 -0400 Subject: [PATCH 34/83] fixed extra chanx connections between dice in rr graph --- vpr/src/route/rr_graph.cpp | 37 ------------------------------------- vpr/src/route/rr_graph2.cpp | 7 +++++++ 2 files changed, 7 insertions(+), 37 deletions(-) diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index aa54650f157..d54fa82af30 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -2204,43 +2204,6 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder } } - if (grid.get_num_layers() > 1 && sb_conn_map != nullptr) { - auto& device_ctx = g_vpr_ctx.device(); - //need to connect extra nodes once to avoid creating same edge multiple times - for(int layer = 0; layer < grid.get_num_layers(); ++layer){ - /* Skip the current die if architecture file specifies that it doesn't require global resource routing */ - if (!device_ctx.inter_cluster_prog_routing_resources.at(layer)) { - continue; - } - /* Start building up edges from die 0*/ - if(layer + 1 >= grid.get_num_layers()){ - continue; - } - int offset = 0; - for (size_t i = 0; i < grid.width() - 1; ++i) { - for (size_t j = 0; j < grid.height() - 1; ++j) { - while (true) { - RRNodeId bottom_die_node = rr_graph_builder.node_lookup().find_node(layer, i, j, CHANX, chan_width.x_max + offset); - RRNodeId top_die_node = rr_graph_builder.node_lookup().find_node(layer + 1, i, j, CHANX, chan_width.x_max + offset); - if (bottom_die_node && top_die_node) { - rr_edges_to_create.emplace_back(bottom_die_node, top_die_node, wire_to_pin_between_dice_switch, false); - offset++; - } - else{ - VTR_ASSERT(!bottom_die_node && !top_die_node); - break; - } - } - } - } - } - //create the actual CHANX->CHANX 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(); - rr_edges_to_create.clear(); - } - VTR_LOG("CHAN->CHAN type edge count:%d\n", num_edges); num_edges = 0; std::function update_chan_width = [](t_chan_width*) noexcept {}; diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index 63471ea21de..c11e3ca1a63 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -2207,6 +2207,10 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, 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_track" to extra "chanx" node in the same switchblocks @@ -2233,6 +2237,9 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, //we only add the following edge once for the first driver, otherwise we are adding the same edge multiple times if(!multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type-CHANX)].connected_to_des) { multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type-CHANX)].connected_to_des = true; + rr_edges_to_create.emplace_back(track_to_chanx_node, diff_layer_chanx_node, src_switch, false); + ++edge_count; + rr_edges_to_create.emplace_back(diff_layer_chanx_node, chanx_to_track_node, src_switch, false); ++edge_count; } From 1370c0321bb2da88319203b997da21b1001c84c0 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Thu, 19 Oct 2023 11:50:57 -0400 Subject: [PATCH 35/83] removed unnecessary loop in the switchblocks pattern --- vpr/src/route/build_switchblocks.cpp | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/vpr/src/route/build_switchblocks.cpp b/vpr/src/route/build_switchblocks.cpp index ccd6d4e8403..a41f62122b1 100644 --- a/vpr/src/route/build_switchblocks.cpp +++ b/vpr/src/route/build_switchblocks.cpp @@ -678,13 +678,12 @@ static void compute_wireconn_connections( /* vectors that will contain indices of the wires belonging to the source/dest wire types/points */ if (sb_conn.from_side == ABOVE || sb_conn.from_side == UNDER) { - for (e_side from_side : SIDES) { - get_switchpoint_wires(grid, - from_chan_details[from_x][from_y].data(), from_chan_type, from_x, from_y, from_side, - wireconn_ptr->from_switchpoint_set, wire_type_sizes_from, false, wireconn_ptr->from_switchpoint_order, rand_state, - &scratchpad->potential_src_wires, - &scratchpad->scratch_wires); - } + get_switchpoint_wires(grid, + from_chan_details[from_x][from_y].data(), from_chan_type, from_x, from_y, sb_conn.to_side, + wireconn_ptr->from_switchpoint_set, wire_type_sizes_from, false, wireconn_ptr->from_switchpoint_order, rand_state, + &scratchpad->potential_src_wires, + &scratchpad->scratch_wires); + } else { get_switchpoint_wires(grid, from_chan_details[from_x][from_y].data(), from_chan_type, from_x, from_y, sb_conn.from_side, @@ -693,13 +692,11 @@ static void compute_wireconn_connections( &scratchpad->scratch_wires); } if (sb_conn.to_side == ABOVE || sb_conn.to_side == UNDER) { - for (e_side to_side : SIDES) { - get_switchpoint_wires(grid, - to_chan_details[to_x][to_y].data(), to_chan_type, to_x, to_y, to_side, - wireconn_ptr->to_switchpoint_set, wire_type_sizes_to, true, - wireconn_ptr->to_switchpoint_order, rand_state, &scratchpad->potential_dest_wires, - &scratchpad->scratch_wires); - } + get_switchpoint_wires(grid, + to_chan_details[to_x][to_y].data(), to_chan_type, to_x, to_y, sb_conn.from_side, + wireconn_ptr->to_switchpoint_set, wire_type_sizes_to, true, + wireconn_ptr->to_switchpoint_order, rand_state, &scratchpad->potential_dest_wires, + &scratchpad->scratch_wires); } else { get_switchpoint_wires(grid, to_chan_details[to_x][to_y].data(), to_chan_type, to_x, to_y, sb_conn.to_side, From 58631f6b50d7ae3fad3fc9043596e58d7f68cefa Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Wed, 29 Nov 2023 18:48:16 -0500 Subject: [PATCH 36/83] refactor switch blocks sides --- libs/libarchfpga/src/physical_types.h | 12 +++++----- libs/libarchfpga/src/read_xml_arch_file.cpp | 4 ++-- libs/librrgraph/src/base/rr_graph_obj.cpp | 4 ++-- libs/librrgraph/src/base/rr_graph_obj.h | 4 ++-- libs/librrgraph/src/base/rr_graph_storage.cpp | 4 ++-- libs/librrgraph/src/base/rr_graph_storage.h | 2 +- libs/librrgraph/src/base/rr_node_types.h | 2 +- .../librrgraph/src/base/rr_spatial_lookup.cpp | 8 +++---- libs/librrgraph/src/base/rr_spatial_lookup.h | 2 +- .../src/io/rr_graph_uxsdcxx_serializer.h | 14 +++++------ vpr/src/draw/draw_rr_edges.cpp | 4 ++-- vpr/src/place/timing_place_lookup.cpp | 4 ++-- vpr/src/route/router_lookahead_map.cpp | 4 ++-- vpr/src/route/rr_graph.cpp | 24 +++++++++---------- vpr/src/route/rr_graph2.cpp | 18 +++++++------- vpr/src/route/rr_graph2.h | 2 +- ...d_full_inter_die_stratixiv_arch.timing.xml | 1 - 17 files changed, 56 insertions(+), 57 deletions(-) diff --git a/libs/libarchfpga/src/physical_types.h b/libs/libarchfpga/src/physical_types.h index a1d89cf0b57..eb634a872b0 100644 --- a/libs/libarchfpga/src/physical_types.h +++ b/libs/libarchfpga/src/physical_types.h @@ -175,17 +175,17 @@ enum e_side : unsigned char { RIGHT = 1, BOTTOM = 2, LEFT = 3, - NUM_SIDES = 4, + NUM_2D_SIDES = 4, ABOVE = 5, UNDER = 6, - NUM_OF_TOTAL_SIDES, + NUM_3D_SIDES, }; -constexpr std::array SIDES = {{TOP, RIGHT, BOTTOM, LEFT}}; //Set of all side orientations -constexpr std::array SIDE_STRING = {{"TOP", "RIGHT", "BOTTOM", "LEFT"}}; //String versions of side orientations +constexpr std::array SIDES = {{TOP, RIGHT, BOTTOM, LEFT}}; //Set of all side orientations +constexpr std::array SIDE_STRING = {{"TOP", "RIGHT", "BOTTOM", "LEFT"}}; //String versions of side orientations -constexpr std::array TOTAL_SIDES = {{TOP, RIGHT, BOTTOM, LEFT, ABOVE, UNDER}}; //Set of all side orientations including different layers -constexpr std::array TOTAL_SIDE_STRING = {{"TOP", "RIGHT", "BOTTOM", "LEFT", "ABOVE", "UNDER"}}; //String versions of side orientations including different layers +constexpr std::array TOTAL_SIDES = {{TOP, RIGHT, BOTTOM, LEFT, ABOVE, UNDER}}; //Set of all side orientations including different layers +constexpr std::array TOTAL_SIDE_STRING = {{"TOP", "RIGHT", "BOTTOM", "LEFT", "ABOVE", "UNDER"}}; //String versions of side orientations including different layers /* pin location distributions */ enum e_pin_location_distr { diff --git a/libs/libarchfpga/src/read_xml_arch_file.cpp b/libs/libarchfpga/src/read_xml_arch_file.cpp index 61b5963b30c..bf4dbd1e941 100644 --- a/libs/libarchfpga/src/read_xml_arch_file.cpp +++ b/libs/libarchfpga/src/read_xml_arch_file.cpp @@ -4922,9 +4922,9 @@ int find_switch_by_name(const t_arch& arch, std::string switch_name) { } e_side string_to_side(std::string side_str) { - e_side side = NUM_SIDES; + e_side side = NUM_2D_SIDES; if (side_str.empty()) { - side = NUM_SIDES; + side = NUM_2D_SIDES; } else if (side_str == "left") { side = LEFT; } else if (side_str == "right") { diff --git a/libs/librrgraph/src/base/rr_graph_obj.cpp b/libs/librrgraph/src/base/rr_graph_obj.cpp index 68c6f305b95..a1d610b9221 100644 --- a/libs/librrgraph/src/base/rr_graph_obj.cpp +++ b/libs/librrgraph/src/base/rr_graph_obj.cpp @@ -812,7 +812,7 @@ RRNodeId RRGraph::create_node(const t_rr_type& type) { node_ptc_nums_.push_back(-1); node_cost_indices_.push_back(-1); node_directions_.push_back(Direction::NONE); - node_sides_.push_back(NUM_SIDES); + node_sides_.push_back(NUM_2D_SIDES); node_Rs_.push_back(0.); node_Cs_.push_back(0.); @@ -1133,7 +1133,7 @@ void RRGraph::build_fast_node_lookup() const { if (node_type(node) == OPIN || node_type(node) == IPIN) { iside = node_side(node); } else { - iside = NUM_SIDES; + iside = NUM_2D_SIDES; } if (iside >= node_lookup_[x][y][itype][ptc].size()) { diff --git a/libs/librrgraph/src/base/rr_graph_obj.h b/libs/librrgraph/src/base/rr_graph_obj.h index 3b8f86c928a..5ad31ba7f01 100644 --- a/libs/librrgraph/src/base/rr_graph_obj.h +++ b/libs/librrgraph/src/base/rr_graph_obj.h @@ -510,7 +510,7 @@ class RRGraph { /* Find the edges connecting two nodes */ std::vector find_edges(const RRNodeId& src_node, const RRNodeId& sink_node) const; /* Find a node with given features from internal fast look-up */ - RRNodeId find_node(const short& x, const short& y, const t_rr_type& type, const int& ptc, const e_side& side = NUM_SIDES) const; + RRNodeId find_node(const short& x, const short& y, const t_rr_type& type, const int& ptc, const e_side& side = NUM_2D_SIDES) const; /* Find the number of routing tracks in a routing channel with a given coordinate */ short chan_num_tracks(const short& x, const short& y, const t_rr_type& type) const; @@ -828,7 +828,7 @@ class RRGraph { bool dirty_ = false; /* Fast look-up to search a node by its type, coordinator and ptc_num - * Indexing of fast look-up: [0..xmax][0..ymax][0..NUM_TYPES-1][0..ptc_max][0..NUM_SIDES-1] + * Indexing of fast look-up: [0..xmax][0..ymax][0..NUM_TYPES-1][0..ptc_max][0..NUM_2D_SIDES-1] */ typedef std::vector>>>> NodeLookup; mutable NodeLookup node_lookup_; diff --git a/libs/librrgraph/src/base/rr_graph_storage.cpp b/libs/librrgraph/src/base/rr_graph_storage.cpp index 110ce1eca80..fcef7fb9d39 100644 --- a/libs/librrgraph/src/base/rr_graph_storage.cpp +++ b/libs/librrgraph/src/base/rr_graph_storage.cpp @@ -615,7 +615,7 @@ const char* t_rr_graph_storage::node_side_string(RRNodeId id) const { } } /* Not found, return an invalid string*/ - return SIDE_STRING[NUM_SIDES]; + return SIDE_STRING[NUM_2D_SIDES]; } void t_rr_graph_storage::set_node_layer(RRNodeId id, short layer) { @@ -759,7 +759,7 @@ void t_rr_graph_storage::add_node_side(RRNodeId id, e_side new_side) { if (node_type(id) != IPIN && node_type(id) != OPIN) { VTR_LOG_ERROR("Attempted to set RR node 'side' for non-channel type '%s'", node_type_string(id)); } - std::bitset side_bits = node_storage_[id].dir_side_.sides; + std::bitset side_bits = node_storage_[id].dir_side_.sides; side_bits[size_t(new_side)] = true; if (side_bits.to_ulong() > CHAR_MAX) { VTR_LOG_ERROR("Invalid side '%s' to be added to rr node %u", SIDE_STRING[new_side], size_t(id)); diff --git a/libs/librrgraph/src/base/rr_graph_storage.h b/libs/librrgraph/src/base/rr_graph_storage.h index 7e4f21b5968..5cd92562766 100644 --- a/libs/librrgraph/src/base/rr_graph_storage.h +++ b/libs/librrgraph/src/base/rr_graph_storage.h @@ -686,7 +686,7 @@ class t_rr_graph_storage { rr_node_typename[node_data.type_]); } // Return a vector showing only the sides that the node appears - std::bitset side_tt = node_storage[id].dir_side_.sides; + std::bitset side_tt = node_storage[id].dir_side_.sides; return side_tt[size_t(side)]; } diff --git a/libs/librrgraph/src/base/rr_node_types.h b/libs/librrgraph/src/base/rr_node_types.h index 56c2b97c3e6..378048dded2 100644 --- a/libs/librrgraph/src/base/rr_node_types.h +++ b/libs/librrgraph/src/base/rr_node_types.h @@ -113,7 +113,7 @@ struct t_rr_rc_data { }; // This is the data type of fast lookups of an rr-node given an (rr_type, layer, x, y, and the side) -//[0..num_rr_types-1][0..num_layer-1][0..grid_width-1][0..grid_height-1][0..NUM_SIDES-1][0..max_ptc-1] +//[0..num_rr_types-1][0..num_layer-1][0..grid_width-1][0..grid_height-1][0..NUM_2D_SIDES-1][0..max_ptc-1] typedef std::array, 4>, NUM_RR_TYPES> t_rr_node_indices; #endif diff --git a/libs/librrgraph/src/base/rr_spatial_lookup.cpp b/libs/librrgraph/src/base/rr_spatial_lookup.cpp index 5b76b3418af..9c51e76dd60 100644 --- a/libs/librrgraph/src/base/rr_spatial_lookup.cpp +++ b/libs/librrgraph/src/base/rr_spatial_lookup.cpp @@ -16,20 +16,20 @@ RRNodeId RRSpatialLookup::find_node(int layer, * - For other types of nodes, there is no need to define a side. However, a default value * is needed when store the node in the fast look-up data structure. * Here we just arbitrary use the first side of the SIDE vector as the default value. - * We may consider to use NUM_SIDES as the default value but it will cause an increase + * We may consider to use NUM_2D_SIDES as the default value but it will cause an increase * in the dimension of the fast look-up data structure. * Please note that in the add_node function, we should keep the SAME convention! */ e_side node_side = side; if (type == IPIN || type == OPIN) { - VTR_ASSERT_MSG(side != NUM_SIDES, "IPIN/OPIN must specify desired side (can not be default NUM_SIDES)"); + VTR_ASSERT_MSG(side != NUM_2D_SIDES, "IPIN/OPIN must specify desired side (can not be default NUM_2D_SIDES)"); } else { VTR_ASSERT_SAFE(type != IPIN && type != OPIN); node_side = SIDES[0]; } /* Pre-check: the layer, x, y, side and ptc should be non-negative numbers! Otherwise, return an invalid id */ - if ((layer < 0) || (x < 0) || (y < 0) || (node_side == NUM_SIDES) || (ptc < 0)) { + if ((layer < 0) || (x < 0) || (y < 0) || (node_side == NUM_2D_SIDES) || (ptc < 0)) { return RRNodeId::INVALID(); } @@ -170,7 +170,7 @@ std::vector RRSpatialLookup::find_nodes_at_all_sides(int layer, /* TODO: Consider to access the raw data like find_node() rather than calling find_node() many times, which hurts runtime */ if (rr_type == IPIN || rr_type == OPIN) { - indices.reserve(NUM_SIDES); + indices.reserve(NUM_2D_SIDES); //For pins, we need to look at all the sides of the current grid tile for (e_side side : SIDES) { RRNodeId rr_node_index = find_node(layer, x, y, rr_type, ptc, side); diff --git a/libs/librrgraph/src/base/rr_spatial_lookup.h b/libs/librrgraph/src/base/rr_spatial_lookup.h index ccfe73a7633..737208fc3fe 100644 --- a/libs/librrgraph/src/base/rr_spatial_lookup.h +++ b/libs/librrgraph/src/base/rr_spatial_lookup.h @@ -73,7 +73,7 @@ class RRSpatialLookup { int y, t_rr_type type, int ptc, - e_side side = NUM_SIDES) const; + e_side side = NUM_2D_SIDES) const; /** * @brief Returns the indices of the specified routing resource nodes, representing routing tracks in a channel. diff --git a/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h b/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h index 9348da20b13..f7fa6ca11bd 100644 --- a/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h +++ b/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h @@ -751,7 +751,7 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { inode, rr_graph.node_type(node.id())); } } else { - std::bitset sides_to_add = from_uxsd_loc_side(side); + std::bitset sides_to_add = from_uxsd_loc_side(side); for (const e_side& side_to_add : SIDES) { if (sides_to_add[side_to_add]) { rr_graph_builder_->add_node_side(node_id, side_to_add); @@ -769,7 +769,7 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { inline uxsd::enum_loc_side get_node_loc_side(const t_rr_node& node) final { const auto& rr_graph = (*rr_graph_); if (rr_graph.node_type(node.id()) == IPIN || rr_graph.node_type(node.id()) == OPIN) { - std::bitset sides_bitset; + std::bitset sides_bitset; for (const e_side& side : SIDES) { if (rr_graph.is_node_on_specific_side(node.id(), side)) { sides_bitset.set(side); @@ -1776,9 +1776,9 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { /* Alloc the lookup table */ for (t_rr_type rr_type : RR_TYPES) { if (rr_type == CHANX) { - rr_graph_builder.node_lookup().resize_nodes(grid_.get_num_layers(),grid_.height(), grid_.width(), rr_type, NUM_SIDES); + rr_graph_builder.node_lookup().resize_nodes(grid_.get_num_layers(), grid_.height(), grid_.width(), rr_type, NUM_2D_SIDES); } else { - rr_graph_builder.node_lookup().resize_nodes(grid_.get_num_layers(),grid_.width(), grid_.height(), rr_type, NUM_SIDES); + rr_graph_builder.node_lookup().resize_nodes(grid_.get_num_layers(), grid_.width(), grid_.height(), rr_type, NUM_2D_SIDES); } } @@ -1791,8 +1791,8 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { // Enum converters from/to uxsd types - std::bitset from_uxsd_loc_side(uxsd::enum_loc_side side) { - std::bitset side_mask(0x0); + std::bitset from_uxsd_loc_side(uxsd::enum_loc_side side) { + std::bitset side_mask(0x0); switch (side) { case uxsd::enum_loc_side::TOP: side_mask.set(TOP); @@ -1863,7 +1863,7 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { return side_mask; } - uxsd::enum_loc_side to_uxsd_loc_side(std::bitset sides) { + uxsd::enum_loc_side to_uxsd_loc_side(std::bitset sides) { // Error out when // - the side has no valid bits // - the side is beyond the mapping range: this is to warn any changes on side truth table which may cause the mapping failed diff --git a/vpr/src/draw/draw_rr_edges.cpp b/vpr/src/draw/draw_rr_edges.cpp index d8aee31c89b..34d0db940da 100644 --- a/vpr/src/draw/draw_rr_edges.cpp +++ b/vpr/src/draw/draw_rr_edges.cpp @@ -464,7 +464,7 @@ void draw_pin_to_chan_edge(RRNodeId pin_node, RRNodeId chan_node, ezgl::renderer /* Only 1 side will be picked in the end * Any rr_node of a grid should have at least 1 side!!! */ - e_side pin_side = NUM_SIDES; + e_side pin_side = NUM_2D_SIDES; const t_rr_type channel_type = rr_graph.node_type(chan_node); if (1 == pin_candidate_sides.size()) { pin_side = pin_candidate_sides[0]; @@ -483,7 +483,7 @@ void draw_pin_to_chan_edge(RRNodeId pin_node, RRNodeId chan_node, ezgl::renderer VTR_ASSERT(pin_candidate_sides.end() != std::find(pin_candidate_sides.begin(), pin_candidate_sides.end(), pin_side)); } /* Sanity check */ - VTR_ASSERT(NUM_SIDES != pin_side); + VTR_ASSERT(NUM_2D_SIDES != pin_side); /* Now we determine which side to be used, calculate the offset for the pin to be drawn * - For the pin locates above/right to the grid (at the top/right side), diff --git a/vpr/src/place/timing_place_lookup.cpp b/vpr/src/place/timing_place_lookup.cpp index 543376201be..dfb9dec4577 100644 --- a/vpr/src/place/timing_place_lookup.cpp +++ b/vpr/src/place/timing_place_lookup.cpp @@ -1041,7 +1041,7 @@ static bool find_direct_connect_sample_locations(const t_direct_inf* direct, //Check that the from pin exists at this from location //(with multi-width/height blocks pins may not exist at all locations) bool from_pin_found = false; - if (direct->from_side != NUM_SIDES) { + if (direct->from_side != NUM_2D_SIDES) { RRNodeId from_pin_rr = node_lookup.find_node(layer_num, x, y, OPIN, from_pin, direct->from_side); from_pin_found = from_pin_rr.is_valid(); } else { @@ -1057,7 +1057,7 @@ static bool find_direct_connect_sample_locations(const t_direct_inf* direct, //Check that the from pin exists at this from location //(with multi-width/height blocks pins may not exist at all locations) bool to_pin_found = false; - if (direct->to_side != NUM_SIDES) { + if (direct->to_side != NUM_2D_SIDES) { RRNodeId to_pin_rr = node_lookup.find_node(layer_num, to_x, to_y, IPIN, to_pin, direct->to_side); to_pin_found = (to_pin_rr != RRNodeId::INVALID()); } else { diff --git a/vpr/src/route/router_lookahead_map.cpp b/vpr/src/route/router_lookahead_map.cpp index 6b69d95695e..80a43f4f515 100644 --- a/vpr/src/route/router_lookahead_map.cpp +++ b/vpr/src/route/router_lookahead_map.cpp @@ -1278,14 +1278,14 @@ static void adjust_rr_pin_position(const RRNodeId rr, int& x, int& y) { * However, current test show that the simple strategy provides * a good trade-off between runtime and quality of results */ - e_side rr_side = NUM_SIDES; + e_side rr_side = NUM_2D_SIDES; for (const e_side& candidate_side : SIDES) { if (rr_graph.is_node_on_specific_side(rr, candidate_side)) { rr_side = candidate_side; break; } } - VTR_ASSERT_SAFE(NUM_SIDES != rr_side); + VTR_ASSERT_SAFE(NUM_2D_SIDES != rr_side); if (rr_side == LEFT) { x -= 1; diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index b820c5af614..fc0939df2cf 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -3418,11 +3418,11 @@ static vtr::NdMatrix alloc_and_load_pin_to_seg_type(const e_pin_type pin } auto tracks_connected_to_pin = vtr::NdMatrix({ - size_t(Type->num_pins), //[0..num_pins-1] + size_t(Type->num_pins), //[0..num_pins-1] size_t(Type->width), //[0..width-1] size_t(Type->height), //[0..height-1] size_t(grid.get_num_layers()), //[0..layer-1] - NUM_SIDES, //[0..NUM_SIDES-1] + NUM_2D_SIDES, //[0..NUM_2D_SIDES-1] size_t(Fc) //[0..Fc-1] }, OPEN); //Unconnected @@ -3432,10 +3432,10 @@ static vtr::NdMatrix alloc_and_load_pin_to_seg_type(const e_pin_type pin //Type->num_pins) if a logical pin has multiple specified physical //pinlocations (i.e. appears on multiple sides of the block) auto num_dir = vtr::NdMatrix({ - size_t(Type->width), //[0..width-1] + size_t(Type->width), //[0..width-1] size_t(Type->height), //[0..height-1] size_t(grid.get_num_layers()), //[0..layer-1] - NUM_SIDES //[0..NUM_SIDES-1] + NUM_2D_SIDES //[0..NUM_2D_SIDES-1] }, 0); @@ -3445,20 +3445,20 @@ static vtr::NdMatrix alloc_and_load_pin_to_seg_type(const e_pin_type pin // //Max possible space alloced for simplicity auto dir_list = vtr::NdMatrix({ - size_t(Type->width), //[0..width-1] + size_t(Type->width), //[0..width-1] size_t(Type->height), //[0..height-1] size_t(grid.get_num_layers()), //[0..layer-1] - NUM_SIDES, //[0..NUM_SIDES-1] + NUM_2D_SIDES, //[0..NUM_2D_SIDES-1] size_t(Type->num_pins) * size_t(grid.get_num_layers()) //[0..num_pins * num_layers-1] }, -1); //Defensive coding: Initialize to invalid //Number of currently assigned physical pins auto num_done_per_dir = vtr::NdMatrix({ - size_t(Type->width), //[0..width-1] + size_t(Type->width), //[0..width-1] size_t(Type->height), //[0..height-1] size_t(grid.get_num_layers()), //[0..layer-1] - NUM_SIDES //[0..NUM_SIDES-1] + NUM_2D_SIDES //[0..NUM_2D_SIDES-1] }, 0); @@ -3748,7 +3748,7 @@ static void load_uniform_connection_block_pattern(vtr::NdMatrix& tracks_ * counts will not get too big. */ std::vector>>> excess_tracks_selected; - excess_tracks_selected.resize(NUM_SIDES); + excess_tracks_selected.resize(NUM_2D_SIDES); for (int i = 0; i < num_phys_pins; ++i) { int width = pin_locations[i].width_offset; @@ -3758,7 +3758,7 @@ static void load_uniform_connection_block_pattern(vtr::NdMatrix& tracks_ max_height = std::max(max_height, height); } - for (int iside = 0; iside < NUM_SIDES; iside++) { + for (int iside = 0; iside < NUM_2D_SIDES; iside++) { excess_tracks_selected[iside].resize(max_width + 1); for (int dx = 0; dx <= max_width; dx++) { @@ -4363,7 +4363,7 @@ static int get_opin_direct_connections(RRGraphBuilder& rr_graph_builder, /* Find matching direct clb-to-clb connections with the same type as current grid location */ if (clb_to_clb_directs[i].from_clb_type == curr_type) { //We are at a valid starting point - if (directs[i].from_side != NUM_SIDES && directs[i].from_side != side) continue; + if (directs[i].from_side != NUM_2D_SIDES && directs[i].from_side != side) continue; //Offset must be in range if (x + directs[i].x_offset < int(device_ctx.grid.width() - 1) @@ -4431,7 +4431,7 @@ static int get_opin_direct_connections(RRGraphBuilder& rr_graph_builder, /* Add new ipin edge to list of edges */ std::vector inodes; - if (directs[i].to_side != NUM_SIDES) { + if (directs[i].to_side != NUM_2D_SIDES) { //Explicit side specified, only create if pin exists on that side RRNodeId inode = rr_graph_builder.node_lookup().find_node(layer, x + directs[i].x_offset, y + directs[i].y_offset, IPIN, ipin, directs[i].to_side); if (inode) { diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index c11e3ca1a63..e88455994d2 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -1155,7 +1155,7 @@ vtr::NdMatrix get_number_track_to_track_inter_die_conn(vtr::NdMatrix, NUM_SIDES> wire_mux_on_track; - std::array, NUM_SIDES> incoming_wire_label; - int num_incoming_wires[NUM_SIDES]; - int num_ending_wires[NUM_SIDES]; - int num_wire_muxes[NUM_SIDES]; + static_assert(NUM_2D_SIDES == 4, "Should be 4 sides"); + std::array, NUM_2D_SIDES> wire_mux_on_track; + std::array, NUM_2D_SIDES> incoming_wire_label; + int num_incoming_wires[NUM_2D_SIDES]; + int num_ending_wires[NUM_2D_SIDES]; + int num_wire_muxes[NUM_2D_SIDES]; /* "Label" the wires around the switch block by connectivity. */ for (e_side side : SIDES) { diff --git a/vpr/src/route/rr_graph2.h b/vpr/src/route/rr_graph2.h index cdcb1d797a7..bece376f2a2 100644 --- a/vpr/src/route/rr_graph2.h +++ b/vpr/src/route/rr_graph2.h @@ -67,7 +67,7 @@ int get_rr_node_index(const t_rr_node_indices& L_rr_node_indices, int y, t_rr_type rr_type, int ptc, - e_side side = NUM_SIDES); + e_side side = NUM_2D_SIDES); //Return how many connection inside switch blocks located at each grid location are going to a different layer vtr::NdMatrix get_number_track_to_track_inter_die_conn(vtr::NdMatrix& multi_layer_track_conn, diff --git a/vtr_flow/arch/multi_die/stratixiv_3d/3d_full_inter_die_stratixiv_arch.timing.xml b/vtr_flow/arch/multi_die/stratixiv_3d/3d_full_inter_die_stratixiv_arch.timing.xml index 4241700bb4d..b1377f7f7c2 100644 --- a/vtr_flow/arch/multi_die/stratixiv_3d/3d_full_inter_die_stratixiv_arch.timing.xml +++ b/vtr_flow/arch/multi_die/stratixiv_3d/3d_full_inter_die_stratixiv_arch.timing.xml @@ -48159,7 +48159,6 @@ - From 5e2d636148d3050282f33be131d6381c54abe4c9 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Wed, 29 Nov 2023 19:38:17 -0500 Subject: [PATCH 37/83] update functions comments to be doxygen and remove duplicated comments --- vpr/src/route/build_switchblocks.cpp | 89 +++++++++++++++++++++------- 1 file changed, 68 insertions(+), 21 deletions(-) diff --git a/vpr/src/route/build_switchblocks.cpp b/vpr/src/route/build_switchblocks.cpp index a41f62122b1..17b17110425 100644 --- a/vpr/src/route/build_switchblocks.cpp +++ b/vpr/src/route/build_switchblocks.cpp @@ -258,8 +258,18 @@ static void get_switchpoint_wires( static const std::vector index_into_correct_chan(int tile_x, int tile_y, int tile_layer, enum e_side side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int& chan_x, int& chan_y, int& chan_layer, std::vector& chan_type); -/* checks whether the specified coordinates are out of bounds */ -static bool coords_out_of_bounds(const DeviceGrid& grid, int x_coord, int y_coord, e_rr_type chan_type, int layer_coord = 0); +/** + * @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); /* 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); @@ -270,19 +280,68 @@ int get_wire_segment_length(const DeviceGrid& grid, e_rr_type chan_type, const t * 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); -/* returns true if the coordinates x/y do not correspond to the location specified by 'location' */ +/** + * @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 location location of the switch block according to custom switch block description 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, e_sb_location location); -/* checks if the specified coordinates represent a corner of the FPGA */ +/** + * @brief check whether specified coordinate is located at the device grid corner + * + * @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, false otherwise. + */ static bool is_corner(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer); -/* checks if the specified coordinates correspond to one of the perimeter switchblocks */ +/** + * @brief check whether specified coordinate is located at one of the perimeter device grid locations + * + * @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, false otherwise. + */ static bool is_perimeter(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer); -/* checks if the specified coordinates correspond to the core of the FPGA (i.e. not perimeter) */ +/** + * @brief check whether specified coordinate is located at core of the device grid (not perimeter) + * + * @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, false otherwise. + */ static bool is_core(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer); -/* checks if the specified layer has programmable routing resources described in the architecture file */ +/** + * @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 */ @@ -371,7 +430,6 @@ void free_switchblock_permutations(t_sb_connection_map* sb_conns) { return; } -/* returns true if the coordinates x/y do not correspond to the location specified by 'location' */ static bool sb_not_here(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer, e_sb_location location) { bool sb_not_here = true; @@ -406,7 +464,6 @@ static bool sb_not_here(const DeviceGrid& grid, const std::vector& inter_c return sb_not_here; } -/* checks if the specified coordinates represent a corner of the FPGA */ static bool is_corner(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; @@ -420,7 +477,6 @@ static bool is_corner(const DeviceGrid& grid, const std::vector& inter_clu return is_corner; } -/* checks if the specified coordinates correspond to one of the perimeter switchblocks */ static bool is_perimeter(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; @@ -432,7 +488,6 @@ static bool is_perimeter(const DeviceGrid& grid, const std::vector& inter_ return is_perimeter; } -/* checks if the specified coordinates correspond to the core of the FPGA (i.e. not perimeter) */ static bool is_core(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; @@ -452,7 +507,6 @@ static bool is_prog_routing_avail(const DeviceGrid& grid, const std::vector index_into_correct_chan(int tile_x, int return chan_details; //Unreachable, return empty vector } -/* checks whether the specified coordinates are out of bounds */ -static bool coords_out_of_bounds(const DeviceGrid& grid, int x_coord, int y_coord, e_rr_type chan_type, int layer_coord) { +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 = false; /* the layer that channel is located at must be legal regardless of chan_type*/ @@ -961,7 +1011,6 @@ static bool coords_out_of_bounds(const DeviceGrid& grid, int x_coord, int y_coor return result; } -/* 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) { /* 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 @@ -1025,8 +1074,6 @@ int get_wire_segment_length(const DeviceGrid& grid, e_rr_type chan_type, const t return wire_length; } -/* 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) { /* this function calculates the switchpoint of a given wire by first calculating * the subsegmennt number of the specified wire. For instance, for a wire with L=4: From 5a0b6d7b3f60479dfc7eb3c020abc31277016ca1 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Wed, 29 Nov 2023 20:12:39 -0500 Subject: [PATCH 38/83] refactoring custom switchblocks functions --- vpr/src/route/build_switchblocks.cpp | 96 +++++++++++++++------------- 1 file changed, 50 insertions(+), 46 deletions(-) diff --git a/vpr/src/route/build_switchblocks.cpp b/vpr/src/route/build_switchblocks.cpp index 17b17110425..484070c25a8 100644 --- a/vpr/src/route/build_switchblocks.cpp +++ b/vpr/src/route/build_switchblocks.cpp @@ -240,7 +240,24 @@ static void compute_wireconn_connections( static int evaluate_num_conns_formula(t_wireconn_scratchpad* scratchpad, std::string num_conns_formula, int from_wire_count, int to_wire_count); -/* returns the wire indices belonging to the types in 'wire_type_vec' and switchpoints in 'points' at the given channel segment */ +/** + * + * @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 + * @param y the wire y-coordinate + * @param side switch block side (top/right/bottom/left/above/under) + * @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 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, @@ -295,7 +312,7 @@ static int get_switchpoint_of_wire(const DeviceGrid& grid, e_rr_type chan_type, static bool sb_not_here(const DeviceGrid& grid, const std::vector& inter_cluster_rr, int x, int y, int layer, e_sb_location location); /** - * @brief check whether specified coordinate is located at the device grid corner + * @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 @@ -303,12 +320,12 @@ static bool sb_not_here(const DeviceGrid& grid, const std::vector& inter_c * @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, false otherwise. + * @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(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, int x, int y, int layer); /** - * @brief check whether specified coordinate is located at one of the perimeter device grid locations + * @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 @@ -316,12 +333,12 @@ static bool is_corner(const DeviceGrid& grid, const std::vector& inter_clu * @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, false otherwise. + * @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(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, int x, int y, int layer); /** - * @brief check whether specified coordinate is located at core of the device grid (not perimeter) + * @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 @@ -329,9 +346,9 @@ static bool is_perimeter(const DeviceGrid& grid, const std::vector& inter_ * @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, false otherwise. + * @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(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, int x, int y, int layer); /** * @brief check whether specified layer has inter-cluster programmable routing resources or not. @@ -390,7 +407,7 @@ t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_detail if (directionality != sb.directionality) { VPR_FATAL_ERROR(VPR_ERROR_ARCH, "alloc_and_load_switchblock_connections: Switchblock %s does not match directionality of architecture\n", sb.name.c_str()); } - /* Iterate over the x,y, layer coordinates spanning the FPGA. */ + /* Iterate over the x,y, layer coordinates spanning the FPGA, filling in all the switch blocks that exist */ for (int layer_coord = 0; layer_coord < grid.get_num_layers(); layer_coord++) { for (size_t x_coord = 0; x_coord < grid.width(); x_coord++) { for (size_t y_coord = 0; y_coord <= grid.height(); y_coord++) { @@ -438,22 +455,22 @@ static bool sb_not_here(const DeviceGrid& grid, const std::vector& inter_c sb_not_here = false; break; case E_PERIMETER: - if (is_perimeter(grid, inter_cluster_rr, x, y, layer)) { + if (is_perimeter_sb(grid, inter_cluster_rr, x, y, layer)) { sb_not_here = false; } break; case E_CORNER: - if (is_corner(grid, inter_cluster_rr, x, y, layer)) { + if (is_corner_sb(grid, inter_cluster_rr, x, y, layer)) { sb_not_here = false; } break; case E_CORE: - if (is_core(grid, inter_cluster_rr, x, y, layer)) { + if (is_core_sb(grid, inter_cluster_rr, x, y, layer)) { sb_not_here = false; } break; case E_FRINGE: - if (is_perimeter(grid, inter_cluster_rr, x, y, layer) && !is_corner(grid, inter_cluster_rr, x, y, layer)) { + 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; @@ -464,7 +481,7 @@ static bool sb_not_here(const DeviceGrid& grid, const std::vector& inter_c return sb_not_here; } -static bool is_corner(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, int x, int y, int layer) { if (!is_prog_routing_avail(grid, inter_cluster_rr, layer)) { return false; } @@ -477,7 +494,7 @@ static bool is_corner(const DeviceGrid& grid, const std::vector& inter_clu return is_corner; } -static bool is_perimeter(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, int x, int y, int layer) { if (!is_prog_routing_avail(grid, inter_cluster_rr, layer)) { return false; } @@ -488,11 +505,11 @@ static bool is_perimeter(const DeviceGrid& grid, const std::vector& inter_ return is_perimeter; } -static bool is_core(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, int x, int y, int layer) { if (!is_prog_routing_avail(grid, inter_cluster_rr, layer)) { return false; } - bool is_core = !is_perimeter(grid, inter_cluster_rr, x, y, layer); + bool is_core = !is_perimeter_sb(grid, inter_cluster_rr, x, y, layer); return is_core; } @@ -727,39 +744,26 @@ static void compute_wireconn_connections( t_wireconn_scratchpad* scratchpad) { constexpr bool verbose = false; + //choose the from_side to be the same as to_side if the connection is travelling across dice in multi-die FPGAs + auto from_side = (sb_conn.from_side != ABOVE && sb_conn.from_side != UNDER) ? sb_conn.from_side : sb_conn.to_side; + //choose the to_side to be the same as from_side if the connection is travelling across dice in multi-die FPGAs + auto to_side = (sb_conn.to_side != ABOVE && sb_conn.to_side != UNDER) ? sb_conn.to_side : sb_conn.from_side; + /* vectors that will contain indices of the wires belonging to the source/dest wire types/points */ - if (sb_conn.from_side == ABOVE || sb_conn.from_side == UNDER) { - get_switchpoint_wires(grid, - from_chan_details[from_x][from_y].data(), from_chan_type, from_x, from_y, sb_conn.to_side, - wireconn_ptr->from_switchpoint_set, wire_type_sizes_from, false, wireconn_ptr->from_switchpoint_order, rand_state, - &scratchpad->potential_src_wires, - &scratchpad->scratch_wires); + get_switchpoint_wires(grid, from_chan_details[from_x][from_y].data(), from_chan_type, from_x, from_y, from_side, + wireconn_ptr->from_switchpoint_set, wire_type_sizes_from, false, wireconn_ptr->from_switchpoint_order, rand_state, + &scratchpad->potential_src_wires, + &scratchpad->scratch_wires); - } else { - get_switchpoint_wires(grid, - from_chan_details[from_x][from_y].data(), from_chan_type, from_x, from_y, sb_conn.from_side, - wireconn_ptr->from_switchpoint_set, wire_type_sizes_from, false, wireconn_ptr->from_switchpoint_order, rand_state, - &scratchpad->potential_src_wires, - &scratchpad->scratch_wires); - } - if (sb_conn.to_side == ABOVE || sb_conn.to_side == UNDER) { - get_switchpoint_wires(grid, - to_chan_details[to_x][to_y].data(), to_chan_type, to_x, to_y, sb_conn.from_side, - wireconn_ptr->to_switchpoint_set, wire_type_sizes_to, true, - wireconn_ptr->to_switchpoint_order, rand_state, &scratchpad->potential_dest_wires, - &scratchpad->scratch_wires); - } else { - get_switchpoint_wires(grid, - to_chan_details[to_x][to_y].data(), to_chan_type, to_x, to_y, sb_conn.to_side, - wireconn_ptr->to_switchpoint_set, wire_type_sizes_to, true, - wireconn_ptr->to_switchpoint_order, rand_state, &scratchpad->potential_dest_wires, - &scratchpad->scratch_wires); - } + get_switchpoint_wires(grid,to_chan_details[to_x][to_y].data(), to_chan_type, to_x, to_y, to_side, + wireconn_ptr->to_switchpoint_set, wire_type_sizes_to, true, + wireconn_ptr->to_switchpoint_order, rand_state, &scratchpad->potential_dest_wires, + &scratchpad->scratch_wires); const auto& potential_src_wires = scratchpad->potential_src_wires; const auto& potential_dest_wires = scratchpad->potential_dest_wires; -#if 0 +#ifdef VERBOSE_RR VTR_LOGV(verbose, "SB_LOC: %d,%d %s->%s\n", sb_conn.x_coord, sb_conn.y_coord, SIDE_STRING[sb_conn.from_side], SIDE_STRING[sb_conn.to_side]); //Define to print out specific wire-switchpoints used in to/from sets, if verbose is set true From b275f1f358f19c9ae13524b233bc4e2bc31a7722 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Wed, 29 Nov 2023 20:14:39 -0500 Subject: [PATCH 39/83] renaming the switch block 2D and 3D side variables --- libs/libarchfpga/src/parse_switchblocks.cpp | 4 ++-- libs/libarchfpga/src/physical_types.h | 8 +++---- .../src/read_fpga_interchange_arch.cpp | 2 +- libs/libarchfpga/src/read_xml_arch_file.cpp | 12 +++++----- libs/librrgraph/src/base/check_rr_graph.cpp | 4 ++-- libs/librrgraph/src/base/rr_graph_builder.cpp | 6 ++--- libs/librrgraph/src/base/rr_graph_storage.cpp | 8 +++---- libs/librrgraph/src/base/rr_graph_storage.h | 2 +- libs/librrgraph/src/base/rr_graph_view.h | 4 ++-- .../librrgraph/src/base/rr_spatial_lookup.cpp | 12 +++++----- libs/librrgraph/src/base/rr_spatial_lookup.h | 6 ++--- .../src/io/rr_graph_uxsdcxx_serializer.h | 4 ++-- vpr/src/draw/draw_rr.cpp | 6 ++--- vpr/src/draw/draw_rr_edges.cpp | 10 ++++---- vpr/src/draw/search_bar.cpp | 2 +- vpr/src/pack/post_routing_pb_pin_fixup.cpp | 2 +- vpr/src/route/build_switchblocks.cpp | 6 ++--- vpr/src/route/clock_connection_builders.cpp | 2 +- vpr/src/route/router_lookahead_map.cpp | 2 +- vpr/src/route/rr_graph.cpp | 12 +++++----- vpr/src/route/rr_graph2.cpp | 24 +++++++++---------- vpr/src/route/rr_graph_sbox.cpp | 4 ++-- vpr/src/util/vpr_utils.cpp | 2 +- 23 files changed, 72 insertions(+), 72 deletions(-) diff --git a/libs/libarchfpga/src/parse_switchblocks.cpp b/libs/libarchfpga/src/parse_switchblocks.cpp index eacf7e98b76..c0b55bcb7fd 100644 --- a/libs/libarchfpga/src/parse_switchblocks.cpp +++ b/libs/libarchfpga/src/parse_switchblocks.cpp @@ -445,8 +445,8 @@ static void check_bidir_switchblock(const t_permutation_map* permutation_map) { SB_Side_Connection conn; /* iterate over all combinations of from_side -> to side */ - for (e_side from_side : SIDES) { - for (e_side to_side : SIDES) { + for (e_side from_side : TOTAL_2D_SIDES) { + for (e_side to_side : TOTAL_2D_SIDES) { /* can't connect a switchblock side to itself */ if (from_side == to_side) { continue; diff --git a/libs/libarchfpga/src/physical_types.h b/libs/libarchfpga/src/physical_types.h index eb634a872b0..fd34e6855ca 100644 --- a/libs/libarchfpga/src/physical_types.h +++ b/libs/libarchfpga/src/physical_types.h @@ -181,11 +181,11 @@ enum e_side : unsigned char { NUM_3D_SIDES, }; -constexpr std::array SIDES = {{TOP, RIGHT, BOTTOM, LEFT}}; //Set of all side orientations -constexpr std::array SIDE_STRING = {{"TOP", "RIGHT", "BOTTOM", "LEFT"}}; //String versions of side orientations +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_SIDES = {{TOP, RIGHT, BOTTOM, LEFT, ABOVE, UNDER}}; //Set of all side orientations including different layers -constexpr std::array TOTAL_SIDE_STRING = {{"TOP", "RIGHT", "BOTTOM", "LEFT", "ABOVE", "UNDER"}}; //String versions of side orientations including different layers +constexpr std::array TOTAL_3D_SIDES = {{TOP, RIGHT, BOTTOM, LEFT, ABOVE, UNDER}}; //Set of all side orientations including different layers +constexpr std::array TOTAL_3D_SIDE_STRINGS = {{"TOP", "RIGHT", "BOTTOM", "LEFT", "ABOVE", "UNDER"}}; //String versions of side orientations including different layers /* pin location distributions */ enum e_pin_location_distr { diff --git a/libs/libarchfpga/src/read_fpga_interchange_arch.cpp b/libs/libarchfpga/src/read_fpga_interchange_arch.cpp index 3842e729539..210b4ca58b0 100644 --- a/libs/libarchfpga/src/read_fpga_interchange_arch.cpp +++ b/libs/libarchfpga/src/read_fpga_interchange_arch.cpp @@ -475,7 +475,7 @@ struct ArchReader { type.pin_height_offset.resize(type.num_pins, 0); type.pinloc.resize({1, 1, 4}, std::vector(type.num_pins, false)); - for (e_side side : SIDES) { + for (e_side side : TOTAL_2D_SIDES) { for (int pin = 0; pin < type.num_pins; pin++) { type.pinloc[0][0][side][pin] = true; type.pin_width_offset[pin] = 0; diff --git a/libs/libarchfpga/src/read_xml_arch_file.cpp b/libs/libarchfpga/src/read_xml_arch_file.cpp index bf4dbd1e941..ccbbfbd1c94 100644 --- a/libs/libarchfpga/src/read_xml_arch_file.cpp +++ b/libs/libarchfpga/src/read_xml_arch_file.cpp @@ -501,7 +501,7 @@ static void LoadPinLoc(pugi::xml_node Locations, int num_sides = 4 * (type->width * type->height); int side_index = 0; int count = 0; - for (e_side side : SIDES) { + for (e_side side : TOTAL_2D_SIDES) { for (int width = 0; width < type->width; ++width) { for (int height = 0; height < type->height; ++height) { for (int pin_offset = 0; pin_offset < (type->num_pins / num_sides) + 1; ++pin_offset) { @@ -526,7 +526,7 @@ static void LoadPinLoc(pugi::xml_node Locations, while (ipin < type->num_pins) { for (int width = 0; width < type->width; ++width) { for (int height = 0; height < type->height; ++height) { - for (e_side side : SIDES) { + for (e_side side : TOTAL_2D_SIDES) { if (((width == 0 && side == LEFT) || (height == type->height - 1 && side == TOP) || (width == type->width - 1 && side == RIGHT) @@ -567,7 +567,7 @@ static void LoadPinLoc(pugi::xml_node Locations, while (ipin < input_pins.size()) { for (int width = 0; width < type->width; ++width) { for (int height = 0; height < type->height; ++height) { - for (e_side side : SIDES) { + for (e_side side : TOTAL_2D_SIDES) { if (ipin < input_pins.size()) { //Pins still to allocate @@ -590,7 +590,7 @@ static void LoadPinLoc(pugi::xml_node Locations, while (ipin < output_pins.size()) { for (int width = 0; width < type->width; ++width) { for (int height = 0; height < type->height; ++height) { - for (e_side side : SIDES) { + for (e_side side : TOTAL_2D_SIDES) { if (((width == 0 && side == LEFT) || (height == type->height - 1 && side == TOP) || (width == type->width - 1 && side == RIGHT) @@ -621,7 +621,7 @@ static void LoadPinLoc(pugi::xml_node Locations, for (int layer = 0; layer < num_of_avail_layer; ++layer) { for (int width = 0; width < type->width; ++width) { for (int height = 0; height < type->height; ++height) { - for (e_side side : SIDES) { + for (e_side side : TOTAL_2D_SIDES) { for (auto token : pin_locs->assignments[sub_tile_index][width][height][layer][side]) { auto pin_range = ProcessPinString(Locations, &sub_tile, @@ -3398,7 +3398,7 @@ static void ProcessPinLocations(pugi::xml_node Locations, for (int l = 0; l < num_of_avail_layer; ++l) { for (int w = 0; w < PhysicalTileType->width; ++w) { for (int h = 0; h < PhysicalTileType->height; ++h) { - for (e_side side : SIDES) { + for (e_side side : TOTAL_2D_SIDES) { for (auto token : pin_locs->assignments[sub_tile_index][w][h][l][side]) { InstPort inst_port(token.c_str()); diff --git a/libs/librrgraph/src/base/check_rr_graph.cpp b/libs/librrgraph/src/base/check_rr_graph.cpp index 8ac769f8004..350844ead1c 100644 --- a/libs/librrgraph/src/base/check_rr_graph.cpp +++ b/libs/librrgraph/src/base/check_rr_graph.cpp @@ -280,12 +280,12 @@ void check_rr_graph(const RRGraphView& rr_graph, rr_graph.node_layer(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 : SIDES) { + for (const e_side& node_side : TOTAL_2D_SIDES) { if (!rr_graph.is_node_on_specific_side(rr_node, node_side)) { continue; } VTR_LOG_ERROR("in check_rr_graph: node %d (%s) at (%d,%d) block=%s side=%s pin=%s has no fanin.\n", - inode, rr_graph.node_type_string(rr_node), rr_graph.node_xlow(rr_node), rr_graph.node_ylow(rr_node), block_type->name, SIDE_STRING[node_side], pin_name.c_str()); + inode, rr_graph.node_type_string(rr_node), rr_graph.node_xlow(rr_node), rr_graph.node_ylow(rr_node), block_type->name, TOTAL_2D_SIDE_STRINGS[node_side], pin_name.c_str()); } } } else { diff --git a/libs/librrgraph/src/base/rr_graph_builder.cpp b/libs/librrgraph/src/base/rr_graph_builder.cpp index 1ef61ec55da..565c99e3f75 100644 --- a/libs/librrgraph/src/base/rr_graph_builder.cpp +++ b/libs/librrgraph/src/base/rr_graph_builder.cpp @@ -39,18 +39,18 @@ void RRGraphBuilder::add_node_to_all_locs(RRNodeId node) { case SOURCE: case SINK: case CHANY: - node_lookup_.add_node(node,node_layer, ix, iy, node_type, node_ptc_num, SIDES[0]); + node_lookup_.add_node(node, node_layer, ix, iy, node_type, node_ptc_num, TOTAL_2D_SIDES[0]); break; case CHANX: /* Currently need to swap x and y for CHANX because of chan, seg convention * TODO: Once the builders is reworked for use consistent (x, y) convention, * the following swapping can be removed */ - node_lookup_.add_node(node,node_layer, iy, ix, node_type, node_ptc_num, SIDES[0]); + node_lookup_.add_node(node, node_layer, iy, ix, node_type, node_ptc_num, TOTAL_2D_SIDES[0]); break; case OPIN: case IPIN: - for (const e_side& side : SIDES) { + 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); } diff --git a/libs/librrgraph/src/base/rr_graph_storage.cpp b/libs/librrgraph/src/base/rr_graph_storage.cpp index fcef7fb9d39..b46fb636277 100644 --- a/libs/librrgraph/src/base/rr_graph_storage.cpp +++ b/libs/librrgraph/src/base/rr_graph_storage.cpp @@ -609,13 +609,13 @@ const std::string& t_rr_graph_storage::node_direction_string(RRNodeId id) const } const char* t_rr_graph_storage::node_side_string(RRNodeId id) const { - for (const e_side& side : SIDES) { + for (const e_side& side : TOTAL_2D_SIDES) { if (is_node_on_specific_side(id, side)) { - return SIDE_STRING[side]; + return TOTAL_2D_SIDE_STRINGS[side]; } } /* Not found, return an invalid string*/ - return SIDE_STRING[NUM_2D_SIDES]; + return TOTAL_2D_SIDE_STRINGS[NUM_2D_SIDES]; } void t_rr_graph_storage::set_node_layer(RRNodeId id, short layer) { @@ -762,7 +762,7 @@ void t_rr_graph_storage::add_node_side(RRNodeId id, e_side new_side) { std::bitset side_bits = node_storage_[id].dir_side_.sides; side_bits[size_t(new_side)] = true; if (side_bits.to_ulong() > CHAR_MAX) { - VTR_LOG_ERROR("Invalid side '%s' to be added to rr node %u", SIDE_STRING[new_side], size_t(id)); + VTR_LOG_ERROR("Invalid side '%s' to be added to rr node %u", TOTAL_2D_SIDE_STRINGS[new_side], size_t(id)); } node_storage_[id].dir_side_.sides = static_cast(side_bits.to_ulong()); } diff --git a/libs/librrgraph/src/base/rr_graph_storage.h b/libs/librrgraph/src/base/rr_graph_storage.h index 5cd92562766..b29ff278b2d 100644 --- a/libs/librrgraph/src/base/rr_graph_storage.h +++ b/libs/librrgraph/src/base/rr_graph_storage.h @@ -211,7 +211,7 @@ class t_rr_graph_storage { * Developers can easily use the following codes with more flexibility * * if (rr_graph.is_node_on_specific_side(id, side)) { - * const char* side_string = SIDE_STRING[side]; + * const char* side_string = TOTAL_2D_SIDE_STRINGS[side]; * } */ const char* node_side_string(RRNodeId id) const; diff --git a/libs/librrgraph/src/base/rr_graph_view.h b/libs/librrgraph/src/base/rr_graph_view.h index 9685c20fe3e..c3e94c526a0 100644 --- a/libs/librrgraph/src/base/rr_graph_view.h +++ b/libs/librrgraph/src/base/rr_graph_view.h @@ -251,11 +251,11 @@ class RRGraphView { int node_layer_num = node_layer(node); if (node_type(node) == OPIN || node_type(node) == IPIN) { coordinate_string += "side: ("; //add the side of the routing resource node - for (const e_side& node_side : SIDES) { + for (const e_side& node_side : TOTAL_2D_SIDES) { if (!is_node_on_specific_side(node, node_side)) { continue; } - coordinate_string += std::string(SIDE_STRING[node_side]) + ","; //add the side of the routing resource node + coordinate_string += std::string(TOTAL_2D_SIDE_STRINGS[node_side]) + ","; //add the side of the routing resource node } coordinate_string += ")"; //add the side of the routing resource node // For OPINs and IPINs the starting and ending coordinate are identical, so we can just arbitrarily assign the start to larger values diff --git a/libs/librrgraph/src/base/rr_spatial_lookup.cpp b/libs/librrgraph/src/base/rr_spatial_lookup.cpp index 9c51e76dd60..089762ebb4a 100644 --- a/libs/librrgraph/src/base/rr_spatial_lookup.cpp +++ b/libs/librrgraph/src/base/rr_spatial_lookup.cpp @@ -25,7 +25,7 @@ RRNodeId RRSpatialLookup::find_node(int layer, VTR_ASSERT_MSG(side != NUM_2D_SIDES, "IPIN/OPIN must specify desired side (can not be default NUM_2D_SIDES)"); } else { VTR_ASSERT_SAFE(type != IPIN && type != OPIN); - node_side = SIDES[0]; + node_side = TOTAL_2D_SIDES[0]; } /* Pre-check: the layer, x, y, side and ptc should be non-negative numbers! Otherwise, return an invalid id */ @@ -172,7 +172,7 @@ std::vector RRSpatialLookup::find_nodes_at_all_sides(int layer, if (rr_type == IPIN || rr_type == OPIN) { indices.reserve(NUM_2D_SIDES); //For pins, we need to look at all the sides of the current grid tile - for (e_side side : SIDES) { + for (e_side side : TOTAL_2D_SIDES) { RRNodeId rr_node_index = find_node(layer, x, y, rr_type, ptc, side); if (rr_node_index) { indices.push_back(rr_node_index); @@ -202,12 +202,12 @@ std::vector RRSpatialLookup::find_grid_nodes_at_all_sides(int layer, std::vector nodes; /* Reserve space to avoid memory fragmentation */ size_t num_nodes = 0; - for (e_side node_side : SIDES) { + for (e_side node_side : TOTAL_2D_SIDES) { num_nodes += find_nodes(layer,x, y, rr_type, node_side).size(); } nodes.reserve(num_nodes); - for (e_side node_side : SIDES) { + for (e_side node_side : TOTAL_2D_SIDES) { std::vector temp_nodes = find_nodes(layer,x, y, rr_type, node_side); nodes.insert(nodes.end(), temp_nodes.begin(), temp_nodes.end()); } @@ -224,7 +224,7 @@ void RRSpatialLookup::reserve_nodes(int layer, /* For non-IPIN/OPIN nodes, the side should always be the TOP side which follows the convention in find_node() API! */ if (type != IPIN && type != OPIN) { - VTR_ASSERT(side == SIDES[0]); + VTR_ASSERT(side == TOTAL_2D_SIDES[0]); } resize_nodes(layer, x, y, type, side); @@ -244,7 +244,7 @@ void RRSpatialLookup::add_node(RRNodeId node, /* For non-IPIN/OPIN nodes, the side should always be the TOP side which follows the convention in find_node() API! */ if (type != IPIN && type != OPIN) { - VTR_ASSERT(side == SIDES[0]); + VTR_ASSERT(side == TOTAL_2D_SIDES[0]); } resize_nodes(layer, x, y, type, side); diff --git a/libs/librrgraph/src/base/rr_spatial_lookup.h b/libs/librrgraph/src/base/rr_spatial_lookup.h index 737208fc3fe..65efd0e6e85 100644 --- a/libs/librrgraph/src/base/rr_spatial_lookup.h +++ b/libs/librrgraph/src/base/rr_spatial_lookup.h @@ -125,7 +125,7 @@ class RRSpatialLookup { int y, t_rr_type type, int num_nodes, - e_side side = SIDES[0]); + e_side side = TOTAL_2D_SIDES[0]); /** * @brief Register a node in the fast look-up @@ -157,7 +157,7 @@ class RRSpatialLookup { int y, t_rr_type type, int ptc, - e_side side = SIDES[0]); + e_side side = TOTAL_2D_SIDES[0]); /** * @brief Mirror the last dimension of a look-up, i.e., a list of nodes, from a source coordinate to @@ -238,7 +238,7 @@ class RRSpatialLookup { int x, int y, t_rr_type type, - e_side side = SIDES[0]) const; + e_side side = TOTAL_2D_SIDES[0]) const; /* -- Internal data storage -- */ private: diff --git a/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h b/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h index f7fa6ca11bd..c74caba4010 100644 --- a/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h +++ b/libs/librrgraph/src/io/rr_graph_uxsdcxx_serializer.h @@ -752,7 +752,7 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { } } else { std::bitset sides_to_add = from_uxsd_loc_side(side); - for (const e_side& side_to_add : SIDES) { + for (const e_side& side_to_add : TOTAL_2D_SIDES) { if (sides_to_add[side_to_add]) { rr_graph_builder_->add_node_side(node_id, side_to_add); } @@ -770,7 +770,7 @@ class RrGraphSerializer final : public uxsd::RrGraphBase { const auto& rr_graph = (*rr_graph_); if (rr_graph.node_type(node.id()) == IPIN || rr_graph.node_type(node.id()) == OPIN) { std::bitset sides_bitset; - for (const e_side& side : SIDES) { + for (const e_side& side : TOTAL_2D_SIDES) { if (rr_graph.is_node_on_specific_side(node.id(), side)) { sides_bitset.set(side); } diff --git a/vpr/src/draw/draw_rr.cpp b/vpr/src/draw/draw_rr.cpp index fa04c388cfe..7c6f512391d 100644 --- a/vpr/src/draw/draw_rr.cpp +++ b/vpr/src/draw/draw_rr.cpp @@ -560,7 +560,7 @@ void draw_rr_pin(RRNodeId inode, const ezgl::color& color, ezgl::renderer* g) { /* As nodes may appear on more than one side, walk through the possible nodes * - draw the pin on each side that it appears */ - for (const e_side& pin_side : SIDES) { + for (const e_side& pin_side : TOTAL_2D_SIDES) { if (!rr_graph.is_node_on_specific_side(RRNodeId(inode), pin_side)) { continue; } @@ -713,7 +713,7 @@ RRNodeId draw_check_rr_node_hit(float click_x, float click_y) { int height_offset = device_ctx.grid.get_height_offset({i, j, layer_num}); int ipin = rr_graph.node_pin_num(inode); float xcen, ycen; - for (const e_side& iside : SIDES) { + for (const e_side& iside : TOTAL_2D_SIDES) { // If pin exists on this side of the block, then get pin coordinates if (type->pinloc[width_offset][height_offset][size_t(iside)][ipin]) { draw_get_rr_pin_coords(inode, &xcen, &ycen, iside); @@ -921,7 +921,7 @@ void draw_get_rr_pin_coords(const t_rr_node& node, float* xcen, float* ycen, con default: vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__, "in draw_get_rr_pin_coords: Unexpected side %s.\n", - SIDE_STRING[pin_side]); + TOTAL_2D_SIDE_STRINGS[pin_side]); break; } diff --git a/vpr/src/draw/draw_rr_edges.cpp b/vpr/src/draw/draw_rr_edges.cpp index 34d0db940da..af344cd49ab 100644 --- a/vpr/src/draw/draw_rr_edges.cpp +++ b/vpr/src/draw/draw_rr_edges.cpp @@ -324,7 +324,7 @@ void draw_pin_to_pin(RRNodeId opin_node, RRNodeId ipin_node, ezgl::renderer* g) */ float x1 = 0, y1 = 0; std::vector opin_candidate_sides; - for (const e_side& opin_candidate_side : SIDES) { + for (const e_side& opin_candidate_side : TOTAL_2D_SIDES) { if (rr_graph.is_node_on_specific_side(opin_node, opin_candidate_side)) { opin_candidate_sides.push_back(opin_candidate_side); } @@ -334,7 +334,7 @@ void draw_pin_to_pin(RRNodeId opin_node, RRNodeId ipin_node, ezgl::renderer* g) float x2 = 0, y2 = 0; std::vector ipin_candidate_sides; - for (const e_side& ipin_candidate_side : SIDES) { + for (const e_side& ipin_candidate_side : TOTAL_2D_SIDES) { if (rr_graph.is_node_on_specific_side(ipin_node, ipin_candidate_side)) { ipin_candidate_sides.push_back(ipin_candidate_side); } @@ -355,7 +355,7 @@ void draw_pin_to_sink(RRNodeId ipin_node, RRNodeId sink_node, ezgl::renderer* g) float x1 = 0, y1 = 0; /* Draw the line for each ipin on different sides */ - for (const e_side& pin_side : SIDES) { + for (const e_side& pin_side : TOTAL_2D_SIDES) { if (!rr_graph.is_node_on_specific_side(ipin_node, pin_side)) { continue; } @@ -381,7 +381,7 @@ void draw_source_to_pin(RRNodeId source_node, RRNodeId opin_node, ezgl::renderer draw_get_rr_src_sink_coords(rr_graph.rr_nodes()[size_t(source_node)], &x1, &y1); /* Draw the line for each ipin on different sides */ - for (const e_side& pin_side : SIDES) { + for (const e_side& pin_side : TOTAL_2D_SIDES) { if (!rr_graph.is_node_on_specific_side(opin_node, pin_side)) { continue; } @@ -455,7 +455,7 @@ void draw_pin_to_chan_edge(RRNodeId pin_node, RRNodeId chan_node, ezgl::renderer * the actual offset of the pin in the context of grid width and height */ std::vector pin_candidate_sides; - for (const e_side& pin_candidate_side : SIDES) { + for (const e_side& pin_candidate_side : TOTAL_2D_SIDES) { if ((rr_graph.is_node_on_specific_side(pin_node, pin_candidate_side)) && (grid_type->pinloc[width_offset][height_offset][pin_candidate_side][rr_graph.node_pin_num(pin_node)])) { pin_candidate_sides.push_back(pin_candidate_side); diff --git a/vpr/src/draw/search_bar.cpp b/vpr/src/draw/search_bar.cpp index bd7e160d4ad..3688ffd4a4b 100644 --- a/vpr/src/draw/search_bar.cpp +++ b/vpr/src/draw/search_bar.cpp @@ -251,7 +251,7 @@ void auto_zoom_rr_node(RRNodeId rr_node_id) { int ipin = rr_graph.node_ptc_num(rr_node_id); float xcen, ycen; - for (const e_side& iside : SIDES) { + for (const e_side& iside : TOTAL_2D_SIDES) { if (type->pinloc[width_offset][height_offset][size_t(iside)][ipin]) { draw_get_rr_pin_coords(rr_node_id, &xcen, &ycen, iside); rr_node = {{xcen - draw_coords->pin_size, ycen - draw_coords->pin_size}, diff --git a/vpr/src/pack/post_routing_pb_pin_fixup.cpp b/vpr/src/pack/post_routing_pb_pin_fixup.cpp index b1c8d21d829..b92fe4fe6a0 100644 --- a/vpr/src/pack/post_routing_pb_pin_fixup.cpp +++ b/vpr/src/pack/post_routing_pb_pin_fixup.cpp @@ -107,7 +107,7 @@ static void update_cluster_pin_with_post_routing_results(const Netlist<>& net_li * Deposit all the sides */ if (wanted_sides.empty()) { - for (e_side side : SIDES) { + for (e_side side : TOTAL_2D_SIDES) { wanted_sides.push_back(side); } } diff --git a/vpr/src/route/build_switchblocks.cpp b/vpr/src/route/build_switchblocks.cpp index 484070c25a8..942c6f297b8 100644 --- a/vpr/src/route/build_switchblocks.cpp +++ b/vpr/src/route/build_switchblocks.cpp @@ -415,8 +415,8 @@ t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_detail continue; } /* now we iterate over all the potential side1->side2 connections */ - for (e_side from_side : TOTAL_SIDES) { - for (e_side to_side : TOTAL_SIDES) { + 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, @@ -764,7 +764,7 @@ static void compute_wireconn_connections( const auto& potential_dest_wires = scratchpad->potential_dest_wires; #ifdef VERBOSE_RR - VTR_LOGV(verbose, "SB_LOC: %d,%d %s->%s\n", sb_conn.x_coord, sb_conn.y_coord, SIDE_STRING[sb_conn.from_side], SIDE_STRING[sb_conn.to_side]); + VTR_LOGV(verbose, "SB_LOC: %d,%d %s->%s\n", sb_conn.x_coord, sb_conn.y_coord, TOTAL_2D_SIDE_STRINGS[sb_conn.from_side], TOTAL_2D_SIDE_STRINGS[sb_conn.to_side]); //Define to print out specific wire-switchpoints used in to/from sets, if verbose is set true diff --git a/vpr/src/route/clock_connection_builders.cpp b/vpr/src/route/clock_connection_builders.cpp index e24bdbe8ea0..2b170a59ba3 100644 --- a/vpr/src/route/clock_connection_builders.cpp +++ b/vpr/src/route/clock_connection_builders.cpp @@ -283,7 +283,7 @@ void ClockToPinsConnection::create_switches(const ClockRRGraphBuilder& clock_gra continue; } - for (e_side side : SIDES) { + for (e_side side : TOTAL_2D_SIDES) { //Don't connect pins which are not adjacent to channels around the perimeter if ((x == 0 && side != RIGHT) || (x == (int)grid.width() - 1 && side != LEFT) || (y == 0 && side != TOP) || (y == (int)grid.height() - 1 && side != BOTTOM)) { continue; diff --git a/vpr/src/route/router_lookahead_map.cpp b/vpr/src/route/router_lookahead_map.cpp index 80a43f4f515..a3e5344ed82 100644 --- a/vpr/src/route/router_lookahead_map.cpp +++ b/vpr/src/route/router_lookahead_map.cpp @@ -1279,7 +1279,7 @@ static void adjust_rr_pin_position(const RRNodeId rr, int& x, int& y) { * a good trade-off between runtime and quality of results */ e_side rr_side = NUM_2D_SIDES; - for (const e_side& candidate_side : SIDES) { + for (const e_side& candidate_side : TOTAL_2D_SIDES) { if (rr_graph.is_node_on_specific_side(rr, candidate_side)) { rr_side = candidate_side; break; diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index fc0939df2cf..3bbadda4e9f 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -2113,7 +2113,7 @@ static std::function alloc_and_load_rr_graph(RRGraphBuilder for (int layer = 0; layer < grid.get_num_layers(); layer++) { for (size_t i = 0; i < grid.width(); ++i) { for (size_t j = 0; j < grid.height(); ++j) { - for (e_side side : SIDES) { + for (e_side side : TOTAL_2D_SIDES) { if (BI_DIRECTIONAL == directionality) { build_bidir_rr_opins(rr_graph_builder, rr_graph, layer, i, j, side, opin_to_track_map, Fc_out, rr_edges_to_create, chan_details_x, @@ -2401,7 +2401,7 @@ static void add_pins_rr_graph(RRGraphBuilder& rr_graph_builder, std::vector x_offset_vec; std::vector y_offset_vec; std::vector pin_sides_vec; - std::tie(x_offset_vec, y_offset_vec, pin_sides_vec) = get_pin_coordinates(physical_type, pin_num, std::vector(SIDES.begin(), SIDES.end())); + std::tie(x_offset_vec, y_offset_vec, pin_sides_vec) = get_pin_coordinates(physical_type, pin_num, std::vector(TOTAL_2D_SIDES.begin(), TOTAL_2D_SIDES.end())); VTR_ASSERT(!pin_sides_vec.empty()); for (int pin_coord = 0; pin_coord < (int)pin_sides_vec.size(); pin_coord++) { int x_offset = x_offset_vec[pin_coord]; @@ -3475,7 +3475,7 @@ static vtr::NdMatrix alloc_and_load_pin_to_seg_type(const e_pin_type pin for (auto type_layer_index : type_layer) { for (int width = 0; width < Type->width; ++width) { for (int height = 0; height < Type->height; ++height) { - for (e_side side : SIDES) { + for (e_side side : TOTAL_2D_SIDES) { if (Type->pinloc[width][height][side][pin] == 1) { for (auto i = 0; i < (int)get_layers_connected_to_pin(Type, type_layer_index, pin).size(); i++) { dir_list[width][height][type_layer_index][side][num_dir[width][height][type_layer_index][side]] = pin; @@ -3494,7 +3494,7 @@ static vtr::NdMatrix alloc_and_load_pin_to_seg_type(const e_pin_type pin int num_phys_pins = 0; for (int width = 0; width < Type->width; ++width) { for (int height = 0; height < Type->height; ++height) { - for (e_side side : SIDES) { + for (e_side side : TOTAL_2D_SIDES) { num_phys_pins += num_dir[width][height][layer][side]; /* Num. physical pins per type */ } } @@ -4576,7 +4576,7 @@ static RRNodeId pick_best_direct_connect_target_rr_node(const RRGraphView& rr_gr float best_dist = std::numeric_limits::infinity(); RRNodeId best_rr = RRNodeId::INVALID(); - for (const e_side& from_side : SIDES) { + for (const e_side& from_side : TOTAL_2D_SIDES) { /* Bypass those side where the node does not appear */ if (!rr_graph.is_node_on_specific_side(from_rr, from_side)) { continue; @@ -4587,7 +4587,7 @@ static RRNodeId pick_best_direct_connect_target_rr_node(const RRGraphView& rr_gr float to_dist = std::abs(rr_graph.node_xlow(from_rr) - rr_graph.node_xlow(to_rr)) + std::abs(rr_graph.node_ylow(from_rr) - rr_graph.node_ylow(to_rr)); - for (const e_side& to_side : SIDES) { + for (const e_side& to_side : TOTAL_2D_SIDES) { /* Bypass those side where the node does not appear */ if (!rr_graph.is_node_on_specific_side(to_rr, to_side)) { continue; diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index e88455994d2..e7786058fa3 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -710,7 +710,7 @@ int get_bidir_opin_connections(RRGraphBuilder& rr_graph_builder, num_conn = 0; /* [0..device_ctx.num_block_types-1][0..num_pins-1][0..width][0..height][0..3][0..Fc-1] */ - for (e_side side : SIDES) { + for (e_side side : TOTAL_2D_SIDES) { /* Figure out coords of channel segment based on side */ tr_i = ((side == LEFT) ? (i - 1) : i); tr_j = ((side == BOTTOM) ? (j - 1) : j); @@ -1153,8 +1153,8 @@ vtr::NdMatrix get_number_track_to_track_inter_die_conn(vtr::NdMatrix(root_x, root_y), vtr::Point(curr_x, curr_y), SOURCE, - SIDES[0]); + TOTAL_2D_SIDES[0]); rr_graph_builder.node_lookup().mirror_nodes(layer, vtr::Point(root_x, root_y), vtr::Point(curr_x, curr_y), SINK, - SIDES[0]); + TOTAL_2D_SIDES[0]); } } } @@ -1662,8 +1662,8 @@ bool verify_rr_node_indices(const DeviceGrid& grid, * This check code should be invalid * if (rr_node.side() != side) { * VPR_ERROR(VPR_ERROR_ROUTE, "RR node xlow does not match between rr_nodes and rr_node_indices (%s/%s): %s", - * SIDE_STRING[rr_node.side()], - * SIDE_STRING[side], + * TOTAL_2D_SIDE_STRINGS[rr_node.side()], + * TOTAL_2D_SIDE_STRINGS[side], * describe_rr_node(rr_graph, grid, rr_indexed_data, inode).c_str()); * } else { * VTR_ASSERT(rr_node.side() == side); @@ -2668,7 +2668,7 @@ void load_sblock_pattern_lookup(const int i, int num_wire_muxes[NUM_2D_SIDES]; /* "Label" the wires around the switch block by connectivity. */ - for (e_side side : SIDES) { + for (e_side side : TOTAL_2D_SIDES) { /* Assume the channel segment doesn't exist. */ wire_mux_on_track[side].clear(); incoming_wire_label[side].clear(); @@ -2742,7 +2742,7 @@ void load_sblock_pattern_lookup(const int i, false, wire_mux_on_track[side], &num_wire_muxes[side], &dummy); } - for (e_side to_side : SIDES) { + for (e_side to_side : TOTAL_2D_SIDES) { /* Can't do anything if no muxes on this side. */ if (num_wire_muxes[to_side] == 0) continue; diff --git a/vpr/src/route/rr_graph_sbox.cpp b/vpr/src/route/rr_graph_sbox.cpp index cba5a04e4e0..6e4a09476d7 100644 --- a/vpr/src/route/rr_graph_sbox.cpp +++ b/vpr/src/route/rr_graph_sbox.cpp @@ -40,8 +40,8 @@ vtr::NdMatrix, 3> alloc_and_load_switch_block_conn(t_chan_width vtr::NdMatrix, 3> switch_block_conn({4, 4, (size_t)nodes_per_chan->max}); - for (e_side from_side : SIDES) { - for (e_side to_side : SIDES) { + for (e_side from_side : TOTAL_2D_SIDES) { + for (e_side to_side : TOTAL_2D_SIDES) { int from_chan_width = (from_side == TOP || from_side == BOTTOM) ? nodes_per_chan->y_max : nodes_per_chan->x_max; int to_chan_width = (to_side == TOP || to_side == BOTTOM) ? nodes_per_chan->y_max : nodes_per_chan->x_max; for (int from_track = 0; from_track < from_chan_width; from_track++) { diff --git a/vpr/src/util/vpr_utils.cpp b/vpr/src/util/vpr_utils.cpp index b200a06ba7f..777cf7ae704 100644 --- a/vpr/src/util/vpr_utils.cpp +++ b/vpr/src/util/vpr_utils.cpp @@ -2321,7 +2321,7 @@ RRNodeId get_pin_rr_node_id(const RRSpatialLookup& rr_spatial_lookup, std::vector x_offset; std::vector y_offset; std::vector pin_sides; - std::tie(x_offset, y_offset, pin_sides) = get_pin_coordinates(physical_tile, pin_physical_num, std::vector(SIDES.begin(), SIDES.end())); + std::tie(x_offset, y_offset, pin_sides) = get_pin_coordinates(physical_tile, pin_physical_num, std::vector(TOTAL_2D_SIDES.begin(), TOTAL_2D_SIDES.end())); VTR_ASSERT(!x_offset.empty()); RRNodeId node_id = RRNodeId::INVALID(); for (int coord_idx = 0; coord_idx < (int)pin_sides.size(); coord_idx++) { From 31e75dd152b0bffb79434398053455abfb6cd18c Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Thu, 30 Nov 2023 12:13:34 -0500 Subject: [PATCH 40/83] commented custom 3d switchblocks structs --- vpr/src/draw/draw_rr_edges.cpp | 4 ++-- vpr/src/route/build_switchblocks.h | 27 +++++++++++++++++++++------ vpr/src/route/rr_graph2.cpp | 16 ++++++++-------- vpr/src/route/rr_graph_sbox.cpp | 6 +++--- 4 files changed, 34 insertions(+), 19 deletions(-) diff --git a/vpr/src/draw/draw_rr_edges.cpp b/vpr/src/draw/draw_rr_edges.cpp index af344cd49ab..274e02e0fb3 100644 --- a/vpr/src/draw/draw_rr_edges.cpp +++ b/vpr/src/draw/draw_rr_edges.cpp @@ -103,7 +103,7 @@ void draw_chany_to_chany_edge(RRNodeId from_node, RRNodeId to_node, short switch if (rr_graph.node_direction(to_node) == Direction::INC) { /* INC wire starts at bottom edge */ y2 = to_chan.bottom(); - /* since no U-turns from_track must be INC as well */ + /* since no U-turns from_tracks must be INC as well */ y1 = draw_coords->tile_y[to_ylow - 1] + draw_coords->get_tile_width(); } else { /* DEC wire starts at top edge */ @@ -194,7 +194,7 @@ void draw_chanx_to_chanx_edge(RRNodeId from_node, RRNodeId to_node, short switch if (rr_graph.node_direction(to_node) == Direction::INC) { /* INC wire starts at leftmost edge */ VTR_ASSERT(from_xlow < to_xlow); x2 = to_chan.left(); - /* since no U-turns from_track must be INC as well */ + /* since no U-turns from_tracks must be INC as well */ x1 = draw_coords->tile_x[to_xlow - 1] + draw_coords->get_tile_width(); } else { /* DEC wire starts at rightmost edge */ diff --git a/vpr/src/route/build_switchblocks.h b/vpr/src/route/build_switchblocks.h index e6e2a64f300..e3c7b3fea99 100644 --- a/vpr/src/route/build_switchblocks.h +++ b/vpr/src/route/build_switchblocks.h @@ -72,8 +72,16 @@ struct t_hash_Switchblock_Lookup { } }; -/* contains the index of the destination wire segment within a channel - * and the index of the switch used to connect to it */ +/** + * @brief contains the required information to build an RR graph edge for a switch block connection + * + * @from_wire source wire ptc_num index in a channel + * @to_wire destination wire ptc_num index in a channel + * @switch_ind RR graph switch index that connects the source wire to the destination wire + * @from_wire_layer the layer index that the source wire is located at + * @to_wire_layer the layer index that the destination wire is located at + * + */ struct t_switchblock_edge { short from_wire; short to_wire; @@ -82,11 +90,18 @@ struct t_switchblock_edge { short to_wire_layer; }; -/** @brief Contain required information to create track-to-track connection in switchblocks in multi-die FPGAs **/ +/** + * @brief contains the required information to create extra length-0 RR nodes to model 3D custom switch blocks connections within the RR graph + * + * @from_tracks a vector containing source tracks ptc_num indices that are connected to the same destination track in above or below layer in multi-die FPGAs + * @offset_to_extra_chanx_node index (max_chan_width + "offset_to_extra_chanx_node") to the correct length-0 RR node that all tracks in "from_tracks" should be connected to in RR graph. + * @connected_to_dest this flag is used to avoid edge duplications while adding edges for all "from_tracks" RR nodes to the same node (length-0 RR node) in the destination layer + * + */ struct t_inter_die_switchblock_edge{ - std::vector from_track; // keeps the tracks that should connect to the same track in another layer - short offset_to_extra_chanx_node = -1; //index to length-0 extra node available in the switchblock - bool connected_to_des = false; + std::vector from_tracks; + short offset_to_extra_chanx_node = -1; + bool connected_to_dest = false; }; /* Switchblock connections are made as [x][y][from_side][to_side][from_wire_ind]. diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index e7786058fa3..b4861520833 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -1178,7 +1178,7 @@ vtr::NdMatrix get_number_track_to_track_inter_die_conn(vtr::NdMatrix get_number_track_to_track_inter_die_conn(vtr::NdMatrix 0); - if(multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type-CHANX)].from_track[0] == from_wire) { + VTR_ASSERT(multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type-CHANX)].from_tracks.size() > 0); + if(multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type-CHANX)].from_tracks[0] == from_wire) { rr_edges_to_create.emplace_back(diff_layer_chanx_node, chanx_to_track_node, src_switch, false); ++edge_count; } @@ -3005,7 +3005,7 @@ static void label_incoming_wires(const int chan_num, static int find_label_of_track(const std::vector& wire_mux_on_track, int num_wire_muxes, int from_track) { - /* Returns the index/label in array wire_mux_on_track whose entry equals from_track. If none are + /* Returns the index/label in array wire_mux_on_track whose entry equals from_tracks. If none are * found, then returns the index of the entry whose value is the largest */ int i_label = -1; int max_track = -1; diff --git a/vpr/src/route/rr_graph_sbox.cpp b/vpr/src/route/rr_graph_sbox.cpp index 6e4a09476d7..0e57727f056 100644 --- a/vpr/src/route/rr_graph_sbox.cpp +++ b/vpr/src/route/rr_graph_sbox.cpp @@ -24,8 +24,8 @@ * BOTTOM (CHANY) */ /* [0..3][0..3][0..nodes_per_chan-1]. Structure below is indexed as: * - * [from_side][to_side][from_track]. That yields an integer vector (ivec) * - * of the tracks to which from_track connects in the proper to_location. * + * [from_side][to_side][from_tracks]. That yields an integer vector (ivec) * + * of the tracks to which from_tracks connects in the proper to_location. * * For simple switch boxes this is overkill, but it will allow complicated * * switch boxes with Fs > 3, etc. without trouble. */ @@ -95,7 +95,7 @@ int get_simple_switch_block_track(const enum e_side from_side, const enum e_switch_block_type switch_block_type, const int from_chan_width, const int to_chan_width) { - /* This routine returns the track number to which the from_track should * + /* This routine returns the track number to which the from_tracks should * * connect. It supports three simple, Fs = 3, switch blocks. */ int to_track = SBOX_ERROR; /* Can check to see if it's not set later. */ From a68257aa3b2e2bce9ba58ad383785d1f22911f48 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Thu, 30 Nov 2023 12:33:56 -0500 Subject: [PATCH 41/83] changed the function argument from pass by value to pass by ref const --- vpr/src/route/build_switchblocks.cpp | 4 ++-- vpr/src/route/build_switchblocks.h | 23 ++++++++++++++++++++--- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/vpr/src/route/build_switchblocks.cpp b/vpr/src/route/build_switchblocks.cpp index 942c6f297b8..286217639ee 100644 --- a/vpr/src/route/build_switchblocks.cpp +++ b/vpr/src/route/build_switchblocks.cpp @@ -365,12 +365,12 @@ static bool is_prog_routing_avail(const DeviceGrid& grid, const std::vector& inter_cluster_rr, - std::vector switchblocks, + const std::vector& switchblocks, t_chan_width* nodes_per_chan, e_directionality directionality, vtr::RandState& rand_state) { diff --git a/vpr/src/route/build_switchblocks.h b/vpr/src/route/build_switchblocks.h index e3c7b3fea99..a015c0426c2 100644 --- a/vpr/src/route/build_switchblocks.h +++ b/vpr/src/route/build_switchblocks.h @@ -114,10 +114,27 @@ typedef std::unordered_map, /************ Functions ************/ -/* allocate and build switch block permutation map */ -t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, const DeviceGrid& grid, const std::vector& inter_cluster_rr, std::vector switchblocks, t_chan_width* nodes_per_chan, enum e_directionality directionality, vtr::RandState& rand_state); +/** + * @brief allocates and builds switch block permutation map + * + * @param chan_details_x channel-x details (length, start and end points, ...) + * @param chan_details_y channel-y details (length, start and end points, ...) + * @param grid device grid + * @param inter_cluster_rr used to check if a certain layer contain inter-cluster programmable routing resources (wires and switch blocks) + * @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) + * + * @return creates a map between switch blocks (key) and their corresponding edges (value). + */ +t_sb_connection_map* alloc_and_load_switchblock_permutations(const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, const DeviceGrid& grid, const std::vector& inter_cluster_rr, const std::vector& switchblocks, t_chan_width* nodes_per_chan, enum e_directionality directionality, vtr::RandState& rand_state); -/* deallocates switch block connections sparse array */ +/** + * @brief deallocates switch block connections sparse array + * + * @param sb_conns switch block permutation map + */ void free_switchblock_permutations(t_sb_connection_map* sb_conns); #endif From 626824d41efd0b0da622818aa98b6b882661fe1c Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Thu, 30 Nov 2023 16:09:29 -0500 Subject: [PATCH 42/83] commented rrgraph functions and extra nodes for 3D custom switchblocks --- vpr/src/route/rr_graph.cpp | 51 ++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index 3bbadda4e9f..57572db34dd 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -484,6 +484,16 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, const int wire_to_pin_between_dice_switch, const enum e_directionality directionality); +/** + * @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 max 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 layer, const int x_coord, @@ -1079,14 +1089,6 @@ static void build_rr_graph(const t_graph_type graph_type, } /* END CHAN_DETAILS */ - /* START A SEG DETAIL WITH LENGTH 0 */ - //define a channel segment with length 0 to support 3d custom switchblocks - - t_chan_seg_details seg_detail_layer; - seg_detail_layer.set_length(0); - - /* END A SEG DETAILS WITH LENGTH 0 */ - /* START FC */ /* Determine the actual value of Fc */ std::vector> Fc_in; /* [0..device_ctx.num_block_types-1][0..num_pins-1][0..num_segments-1] */ @@ -1262,11 +1264,20 @@ static void build_rr_graph(const t_graph_type graph_type, } /* END SB LOOKUP */ - /* Add extra nodes to switch blocks for multi-layer FPGAs with custom switch blocks that define track-to_track connections */ - vtr::NdMatrix multi_layer_track_conn; //keeps the extra nodes offset and drivers for each destination track + /* Add extra nodes to RR graph to support 3D custom switch blocks for multi-layer FPGAs + * For each connection in 3D custom switch blocks, multiple drivers can drive the same sink in another layer, + * this matrix keeps the drivers and the offset to extra length-0 node index in RR graph for each destination track + * based on its coordinate (layer, x, y), track ptc_num, channel type + * Access pattern: [0..grid.layer-1][0..grid.width-1][0..grid.height-1][0..max_chan_width-1][CHANX or CHANY] + */ + vtr::NdMatrix multi_layer_track_conn; auto& grid_ctx = device_ctx.grid; multi_layer_track_conn.resize(std::array{(size_t)grid_ctx.get_num_layers(), grid.width(), grid.height(), (size_t) max_chan_width, 2}); + /* 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 auto extra_nodes_per_switchblock = get_number_track_to_track_inter_die_conn(multi_layer_track_conn, sb_conn_map, device_ctx.rr_graph_builder); @@ -2158,7 +2169,10 @@ 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 connection between layers, we need to load newly added CHANX nodes + /* In multi-die FPGAs with track-to-track connections between layers, we need to load newly added length-0 CHANX nodes + * These extra nodes can be driven from many tracks in the source layer and can drive multiple tracks in the destination layer, + * since these die-crossing connections have more delays. + */ if (grid.get_num_layers() > 1 && sb_conn_map != nullptr) { //custom switch block defined in the architecture VTR_ASSERT(sblock_pattern.empty() && switch_block_conn.empty()); @@ -3270,11 +3284,22 @@ static void build_inter_die_custom_sb_rr_chan(RRGraphBuilder& rr_graph_builder, auto& mutable_device_ctx = g_vpr_ctx.mutable_device(); const t_chan_seg_details* seg_details = chan_details_x[x_coord][y_coord].data(); - /* Loads up all the extra routing resource nodes required to support multi-die custom switch blocks */ + /* 3D connections within the switch blocks use some extra length-0 CHANX node to allow a single 3D connection to be driven + * by multiple tracks in the source layer, and drives multiple tracks in the destination layer. + * These nodes has already been added to RRGraph builder, this function will go through all added nodes + * with specific location (layer, x_coord, y_coord) and sets their attributes. + * + * The extra length-0 nodes have the following attributes to make them distinigushable form normal chanx wires (e.g., length-4): + * 1) type: CHANX (could have used either CHANX or CHANY, we used CHANX) + * 2) ptc_num: [max_chan_width : max_chan_width + num_of_3d_connections - 1] + * 3) length: 0 + * 4) xhigh=xlow, yhigh=ylow + * 5) directionality: NONE (neither incremental nor decremental in 2D space) + */ int start_track = nodes_per_chan.max; int offset = 0; - while (true) { + while (true) { //going through allocated nodes until no nodes are found within the RRGraph builder RRNodeId node = rr_graph_builder.node_lookup().find_node(layer, x_coord, y_coord, CHANX, start_track + offset); if (node) { rr_graph_builder.set_node_layer(node, layer); From bf4f1c2daf7eb80a552b1d599d4e99aab5bc80b3 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Thu, 30 Nov 2023 16:58:15 -0500 Subject: [PATCH 43/83] comment 3d custom switch block rrgraph-related functions --- vpr/src/route/rr_graph.cpp | 2 +- vpr/src/route/rr_graph2.cpp | 47 +++++++++++++++++++++++++++++++++---- vpr/src/route/rr_graph2.h | 21 +++++++++++++++-- 3 files changed, 62 insertions(+), 8 deletions(-) diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index 57572db34dd..b1e4c3e88f0 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -491,7 +491,7 @@ static void build_rr_chan(RRGraphBuilder& rr_graph_builder, * @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 max tracks per channel (x, y) + * @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, diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index b4861520833..16c0cb98153 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -93,6 +93,27 @@ static int get_unidir_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, RRNodeId from_rr_node, t_rr_edge_info_set& rr_edges_to_create); +/** + * @brief creates the RR graph edges corresponding to switch blocks permutation map + * + * @param rr_graph_builder RRGraphBuilder data structure which allows data modification on a routing resource graph + * @param tile_x x-coordinate of the switch block + * @param tile_y y-coordinate of the switch block + * @param layer layer-coordinate of the switch block + * @param max_chan_width number of available tracks within the channel + * @param from_side switch block connection source side + * @param from_wire switch block connection source wire index (ptc_num) within the channel + * @param from_rr_node switch block connection source wire RRNode index + * @param to_side switch block connection destination side + * @param to_x switch block connection destination x-coordinate + * @param to_y switch block connection destination y-coordinate + * @param to_chan_type switch block connection destination channel type (CHANX or CHANY) + * @param multi_layer_track_conn 3D custom switch block information (offset to correct extra CHANX nodes, source tracks, ..) + * @param switch_override used to set the correct switch index for the RR graph edge + * @param sb_conn_map switch block permutation map + * @param rr_edges_to_create Total RR edges count + * @param edge_count number of RR edges that this function creates + */ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, const int tile_x, const int tile_y, @@ -111,6 +132,27 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, t_rr_edge_info_set& 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 + * @param layer the channel segment layer-coordinate + * @param max_chan_width number of tracks per channel + * @param from_track source track index (ptc_num) within the channel + * @param to_chan destination coordinate (x or y) based on chan type + * @param to_seg destination segment coordinate (x or y) based on chan type + * @param to_chan_type destination wire segment channel type (CHANX or CHANY) + * @param from_side swtich block connection source side + * @param to_side swtich block connection destination side + * @param multi_layer_track_conn 3D custom switch block information (offset to correct extra CHANX nodes, source tracks, ..) + * @param swtich_override used to set the correct switch index for the RR graph edge + * @param sb_conn_map switch block permutation map, created based on the architecture file + * @param from_rr_node the source wire segment RRNodeID + * @param rr_edges_to_create keeps the created edges + * + * @return the number of edges added to 'rr_edge_to_create' + */ + static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, const int layer, const int max_chan_width, @@ -2259,11 +2301,6 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, } } -/* Figures out the edges that should connect the given wire segment to the given - * channel segment, adds these edges to 'edge_list' and returns the number of - * edges added . - * See route/build_switchblocks.c for a detailed description of how the switch block - * connection map sb_conn_map is generated. */ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, const int layer, const int max_chan_width, diff --git a/vpr/src/route/rr_graph2.h b/vpr/src/route/rr_graph2.h index bece376f2a2..a0835e6bf13 100644 --- a/vpr/src/route/rr_graph2.h +++ b/vpr/src/route/rr_graph2.h @@ -29,6 +29,16 @@ void alloc_and_load_rr_node_indices(RRGraphBuilder& rr_graph_builder, const t_chan_details& chan_details_y, bool is_flat); +/** + * @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 device grid + * @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 RRNodeId that should be assigned to add a new RR node to the RR graph + */ void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, const t_chan_width* nodes_per_chan, const DeviceGrid& grid, @@ -68,8 +78,15 @@ int get_rr_node_index(const t_rr_node_indices& L_rr_node_indices, t_rr_type rr_type, int ptc, e_side side = NUM_2D_SIDES); - -//Return how many connection inside switch blocks located at each grid location are going to a different layer +/** + * @brief goes through 3D custom switch blocks and counts how many connections are crossing dice for each switch block. + * + * @param multi_layer_track_conn 3D custom switch block information (offset to correct extra CHANX nodes, source tracks, ..), extracted from the architecture file + * @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(vtr::NdMatrix& multi_layer_track_conn, t_sb_connection_map* sb_conn_map, RRGraphBuilder& rr_graph_builder); From f7e6620d9d1bf1956cdd0454479b9f5c8c456084 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Thu, 30 Nov 2023 16:59:07 -0500 Subject: [PATCH 44/83] make format --- libs/libarchfpga/src/physical_types.h | 4 +-- vpr/src/route/build_switchblocks.cpp | 4 +-- vpr/src/route/build_switchblocks.h | 2 +- vpr/src/route/rr_graph.cpp | 21 ++++++++------- vpr/src/route/rr_graph2.cpp | 37 ++++++++++++--------------- vpr/src/route/rr_graph2.h | 8 +++--- 6 files changed, 36 insertions(+), 40 deletions(-) diff --git a/libs/libarchfpga/src/physical_types.h b/libs/libarchfpga/src/physical_types.h index fd34e6855ca..250976a771d 100644 --- a/libs/libarchfpga/src/physical_types.h +++ b/libs/libarchfpga/src/physical_types.h @@ -181,10 +181,10 @@ enum e_side : unsigned char { NUM_3D_SIDES, }; -constexpr std::array TOTAL_2D_SIDES = {{TOP, RIGHT, BOTTOM, LEFT}}; //Set of all side orientations +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_SIDES = {{TOP, RIGHT, BOTTOM, LEFT, ABOVE, UNDER}}; //Set of all side orientations including different layers constexpr std::array TOTAL_3D_SIDE_STRINGS = {{"TOP", "RIGHT", "BOTTOM", "LEFT", "ABOVE", "UNDER"}}; //String versions of side orientations including different layers /* pin location distributions */ diff --git a/vpr/src/route/build_switchblocks.cpp b/vpr/src/route/build_switchblocks.cpp index 286217639ee..774990bd1d5 100644 --- a/vpr/src/route/build_switchblocks.cpp +++ b/vpr/src/route/build_switchblocks.cpp @@ -755,7 +755,7 @@ static void compute_wireconn_connections( &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(grid, to_chan_details[to_x][to_y].data(), to_chan_type, to_x, to_y, to_side, wireconn_ptr->to_switchpoint_set, wire_type_sizes_to, true, wireconn_ptr->to_switchpoint_order, rand_state, &scratchpad->potential_dest_wires, &scratchpad->scratch_wires); @@ -986,7 +986,7 @@ static const std::vector index_into_correct_chan(int tile_x, int return chan_details; //Unreachable, return empty vector } -static bool coords_out_of_bounds(const DeviceGrid& grid, int x_coord, int y_coord, int layer_coord, e_rr_type chan_type) { +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 = false; /* the layer that channel is located at must be legal regardless of chan_type*/ diff --git a/vpr/src/route/build_switchblocks.h b/vpr/src/route/build_switchblocks.h index a015c0426c2..aa7aed3cff6 100644 --- a/vpr/src/route/build_switchblocks.h +++ b/vpr/src/route/build_switchblocks.h @@ -98,7 +98,7 @@ struct t_switchblock_edge { * @connected_to_dest this flag is used to avoid edge duplications while adding edges for all "from_tracks" RR nodes to the same node (length-0 RR node) in the destination layer * */ -struct t_inter_die_switchblock_edge{ +struct t_inter_die_switchblock_edge { std::vector from_tracks; short offset_to_extra_chanx_node = -1; bool connected_to_dest = false; diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index b1e4c3e88f0..d3618a2a827 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -1272,7 +1272,7 @@ static void build_rr_graph(const t_graph_type graph_type, */ vtr::NdMatrix multi_layer_track_conn; auto& grid_ctx = device_ctx.grid; - multi_layer_track_conn.resize(std::array{(size_t)grid_ctx.get_num_layers(), grid.width(), grid.height(), (size_t) max_chan_width, 2}); + multi_layer_track_conn.resize(std::array{(size_t)grid_ctx.get_num_layers(), grid.width(), grid.height(), (size_t)max_chan_width, 2}); /* 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 @@ -3317,8 +3317,7 @@ static void build_inter_die_custom_sb_rr_chan(RRGraphBuilder& rr_graph_builder, rr_graph_builder.set_node_direction(node, Direction::NONE); offset++; - } - else{ + } else { break; } } @@ -3443,11 +3442,11 @@ static vtr::NdMatrix alloc_and_load_pin_to_seg_type(const e_pin_type pin } auto tracks_connected_to_pin = vtr::NdMatrix({ - size_t(Type->num_pins), //[0..num_pins-1] + size_t(Type->num_pins), //[0..num_pins-1] size_t(Type->width), //[0..width-1] size_t(Type->height), //[0..height-1] size_t(grid.get_num_layers()), //[0..layer-1] - NUM_2D_SIDES, //[0..NUM_2D_SIDES-1] + NUM_2D_SIDES, //[0..NUM_2D_SIDES-1] size_t(Fc) //[0..Fc-1] }, OPEN); //Unconnected @@ -3457,10 +3456,10 @@ static vtr::NdMatrix alloc_and_load_pin_to_seg_type(const e_pin_type pin //Type->num_pins) if a logical pin has multiple specified physical //pinlocations (i.e. appears on multiple sides of the block) auto num_dir = vtr::NdMatrix({ - size_t(Type->width), //[0..width-1] + size_t(Type->width), //[0..width-1] size_t(Type->height), //[0..height-1] size_t(grid.get_num_layers()), //[0..layer-1] - NUM_2D_SIDES //[0..NUM_2D_SIDES-1] + NUM_2D_SIDES //[0..NUM_2D_SIDES-1] }, 0); @@ -3470,20 +3469,20 @@ static vtr::NdMatrix alloc_and_load_pin_to_seg_type(const e_pin_type pin // //Max possible space alloced for simplicity auto dir_list = vtr::NdMatrix({ - size_t(Type->width), //[0..width-1] + size_t(Type->width), //[0..width-1] size_t(Type->height), //[0..height-1] size_t(grid.get_num_layers()), //[0..layer-1] - NUM_2D_SIDES, //[0..NUM_2D_SIDES-1] + NUM_2D_SIDES, //[0..NUM_2D_SIDES-1] size_t(Type->num_pins) * size_t(grid.get_num_layers()) //[0..num_pins * num_layers-1] }, -1); //Defensive coding: Initialize to invalid //Number of currently assigned physical pins auto num_done_per_dir = vtr::NdMatrix({ - size_t(Type->width), //[0..width-1] + size_t(Type->width), //[0..width-1] size_t(Type->height), //[0..height-1] size_t(grid.get_num_layers()), //[0..layer-1] - NUM_2D_SIDES //[0..NUM_2D_SIDES-1] + NUM_2D_SIDES //[0..NUM_2D_SIDES-1] }, 0); diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index 16c0cb98153..3c3664a84b6 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -1183,18 +1183,17 @@ static void load_chan_rr_indices(const int max_chan_width, } } -vtr::NdMatrix get_number_track_to_track_inter_die_conn(vtr::NdMatrix& multi_layer_track_conn, - t_sb_connection_map* sb_conn_map, - RRGraphBuilder& rr_graph_builder) { - +vtr::NdMatrix get_number_track_to_track_inter_die_conn(vtr::NdMatrix& multi_layer_track_conn, + t_sb_connection_map* sb_conn_map, + RRGraphBuilder& rr_graph_builder) { auto& grid_ctx = g_vpr_ctx.device().grid; vtr::NdMatrix extra_nodes_per_switchblocks; extra_nodes_per_switchblocks.resize(std::array{grid_ctx.width(), grid_ctx.height()}); for (size_t y = 0; y < grid_ctx.height(); y++) { for (size_t x = 0; x < grid_ctx.width(); x++) { - int curr_switchblocks_offset =0; - for (auto layer = 0; layer < grid_ctx.get_num_layers(); layer++){ + int curr_switchblocks_offset = 0; + for (auto layer = 0; layer < grid_ctx.get_num_layers(); layer++) { for (auto from_side : TOTAL_3D_SIDES) { for (auto to_side : TOTAL_3D_SIDES) { if (from_side < NUM_2D_SIDES && to_side < NUM_2D_SIDES) { //this connection is not crossing any layer @@ -1215,20 +1214,19 @@ vtr::NdMatrix get_number_track_to_track_inter_die_conn(vtr::NdMatrix CHANX connection RRNodeId from_inode = rr_graph_builder.node_lookup().find_node(conn_vector[iconn].from_wire_layer, x, y, CHANY, conn_vector[iconn].from_wire_layer); RRNodeId to_inode = rr_graph_builder.node_lookup().find_node(conn_vector[iconn].to_wire_layer, x, y, CHANX, conn_vector[iconn].to_wire); - if(from_inode && to_inode){ - if(multi_layer_track_conn[conn_vector[iconn].to_wire_layer][x][y][conn_vector[iconn].to_wire][1].offset_to_extra_chanx_node == -1){ + if (from_inode && to_inode) { + if (multi_layer_track_conn[conn_vector[iconn].to_wire_layer][x][y][conn_vector[iconn].to_wire][1].offset_to_extra_chanx_node == -1) { multi_layer_track_conn[conn_vector[iconn].to_wire_layer][x][y][conn_vector[iconn].to_wire][1].offset_to_extra_chanx_node = curr_switchblocks_offset; curr_switchblocks_offset++; } multi_layer_track_conn[conn_vector[iconn].to_wire_layer][x][y][conn_vector[iconn].to_wire][1].from_tracks.push_back(conn_vector[iconn].from_wire); - } //CHANX -> CHANY connection from_inode = rr_graph_builder.node_lookup().find_node(conn_vector[iconn].from_wire_layer, x, y, CHANX, conn_vector[iconn].from_wire_layer); to_inode = rr_graph_builder.node_lookup().find_node(conn_vector[iconn].to_wire_layer, x, y, CHANY, conn_vector[iconn].to_wire); - if(from_inode && to_inode){ - if(multi_layer_track_conn[conn_vector[iconn].to_wire_layer][x][y][conn_vector[iconn].to_wire][0].offset_to_extra_chanx_node == -1){ + if (from_inode && to_inode) { + if (multi_layer_track_conn[conn_vector[iconn].to_wire_layer][x][y][conn_vector[iconn].to_wire][0].offset_to_extra_chanx_node == -1) { multi_layer_track_conn[conn_vector[iconn].to_wire_layer][x][y][conn_vector[iconn].to_wire][0].offset_to_extra_chanx_node = curr_switchblocks_offset; curr_switchblocks_offset++; } @@ -1250,7 +1248,7 @@ vtr::NdMatrix get_number_track_to_track_inter_die_conn(vtr::NdMatrix& extra_nodes_per_switchblock, + const vtr::NdMatrix& extra_nodes_per_switchblock, int* index) { /* * In case of multi-die FPGAs, we add extra nodes (can be either CHANX OR CHANY, used CHANX) to @@ -1269,7 +1267,6 @@ void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, } for (size_t y = 0; y < grid.height() - 1; ++y) { for (size_t x = 1; x < grid.width() - 1; ++x) { - //count how many track-to-track connection go from current layer to other layers int conn_count = extra_nodes_per_switchblock[x][y]; @@ -2244,12 +2241,12 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, continue; } - if(multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type-CHANX)].offset_to_extra_chanx_node == -1){ + if (multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type - CHANX)].offset_to_extra_chanx_node == -1) { //either source track or destination track doesn't exist continue; } - if(tile_x != to_x || tile_y != to_y){ + if (tile_x != to_x || tile_y != to_y) { continue; } @@ -2259,7 +2256,7 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, * 2) connect extra "chanx" node located in from_layer to another extra "chanx" node located in to_layer * 3) connect "chanx" node located in to_layer to "to_track" * */ - int offset = multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type-CHANX)].offset_to_extra_chanx_node; + int offset = multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type - CHANX)].offset_to_extra_chanx_node; RRNodeId track_to_chanx_node = rr_graph_builder.node_lookup().find_node(layer, tile_x, tile_y, CHANX, max_chan_width + offset); RRNodeId diff_layer_chanx_node = rr_graph_builder.node_lookup().find_node(to_layer, tile_x, tile_y, CHANX, max_chan_width + offset); RRNodeId chanx_to_track_node = rr_graph_builder.node_lookup().find_node(to_layer, to_x, to_y, to_chan_type, to_wire); @@ -2277,8 +2274,8 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, ++edge_count; //we only add the following edge once for the first driver, otherwise we are adding the same edge multiple times - if(!multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type-CHANX)].connected_to_dest) { - multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type-CHANX)].connected_to_dest = true; + if (!multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type - CHANX)].connected_to_dest) { + multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type - CHANX)].connected_to_dest = true; rr_edges_to_create.emplace_back(track_to_chanx_node, diff_layer_chanx_node, src_switch, false); ++edge_count; @@ -2290,8 +2287,8 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, //Add reverse edge since bi-directional rr_edges_to_create.emplace_back(track_to_chanx_node, from_rr_node, src_switch, false); ++edge_count; - VTR_ASSERT(multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type-CHANX)].from_tracks.size() > 0); - if(multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type-CHANX)].from_tracks[0] == from_wire) { + VTR_ASSERT(multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type - CHANX)].from_tracks.size() > 0); + if (multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type - CHANX)].from_tracks[0] == from_wire) { rr_edges_to_create.emplace_back(diff_layer_chanx_node, chanx_to_track_node, src_switch, false); ++edge_count; } diff --git a/vpr/src/route/rr_graph2.h b/vpr/src/route/rr_graph2.h index a0835e6bf13..e3b082e0895 100644 --- a/vpr/src/route/rr_graph2.h +++ b/vpr/src/route/rr_graph2.h @@ -42,7 +42,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 t_chan_width* nodes_per_chan, const DeviceGrid& grid, - const vtr::NdMatrix& extra_nodes_per_switchblock, + const vtr::NdMatrix& extra_nodes_per_switchblock, int* index); void alloc_and_load_tile_rr_node_indices(RRGraphBuilder& rr_graph_builder, @@ -87,9 +87,9 @@ int get_rr_node_index(const t_rr_node_indices& L_rr_node_indices, * * @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(vtr::NdMatrix& multi_layer_track_conn, - t_sb_connection_map* sb_conn_map, - RRGraphBuilder& rr_graph_builder); +vtr::NdMatrix get_number_track_to_track_inter_die_conn(vtr::NdMatrix& multi_layer_track_conn, + t_sb_connection_map* sb_conn_map, + RRGraphBuilder& rr_graph_builder); int find_average_rr_node_index(int device_width, int device_height, From 56c9fd52c42e9bec615235e2f95ca38fbe6ec48b Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Mon, 4 Dec 2023 17:42:26 -0500 Subject: [PATCH 45/83] minor debug: total 3d array length and coords_out_of_bounds was incorrect --- libs/libarchfpga/src/physical_types.h | 4 ++-- vpr/src/route/build_switchblocks.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/libarchfpga/src/physical_types.h b/libs/libarchfpga/src/physical_types.h index 250976a771d..3588922a816 100644 --- a/libs/libarchfpga/src/physical_types.h +++ b/libs/libarchfpga/src/physical_types.h @@ -184,8 +184,8 @@ enum e_side : unsigned char { 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 +constexpr std::array TOTAL_3D_SIDES = {{TOP, RIGHT, BOTTOM, LEFT, ABOVE, UNDER}}; //Set of all side orientations including different layers +constexpr std::array TOTAL_3D_SIDE_STRINGS = {{"TOP", "RIGHT", "BOTTOM", "LEFT", "ABOVE", "UNDER"}}; //String versions of side orientations including different layers /* pin location distributions */ enum e_pin_location_distr { diff --git a/vpr/src/route/build_switchblocks.cpp b/vpr/src/route/build_switchblocks.cpp index 774990bd1d5..1675fc25db5 100644 --- a/vpr/src/route/build_switchblocks.cpp +++ b/vpr/src/route/build_switchblocks.cpp @@ -987,7 +987,7 @@ static const std::vector index_into_correct_chan(int tile_x, int } 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 = false; + bool result = true; /* the layer that channel is located at must be legal regardless of chan_type*/ if (layer_coord < 0 || layer_coord > grid.get_num_layers()) { From 59f5bd56c3bedf98d5497f0e3f92839f65c02ccf Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Mon, 4 Dec 2023 17:58:07 -0500 Subject: [PATCH 46/83] revert back index_into_correct_chan to return a single chanx/chany for above and under sides --- vpr/src/route/build_switchblocks.cpp | 98 ++++++++++++---------------- 1 file changed, 41 insertions(+), 57 deletions(-) diff --git a/vpr/src/route/build_switchblocks.cpp b/vpr/src/route/build_switchblocks.cpp index 1675fc25db5..a40717b9a20 100644 --- a/vpr/src/route/build_switchblocks.cpp +++ b/vpr/src/route/build_switchblocks.cpp @@ -273,7 +273,7 @@ static void get_switchpoint_wires( std::vector* output_wires, std::vector* scratch_wires); -static const std::vector index_into_correct_chan(int tile_x, int tile_y, int tile_layer, enum e_side side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int& chan_x, int& chan_y, int& chan_layer, std::vector& chan_type); +static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, int tile_layer, enum e_side side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int& chan_x, int& chan_y, int& chan_layer, t_rr_type& chan_type); /** * @brief check whether a specific track location is valid within the device grid @@ -654,7 +654,7 @@ static void get_switchpoint_wires( static void compute_wire_connections(int x_coord, int y_coord, int layer_coord, enum e_side from_side, enum e_side to_side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, t_switchblock_inf* sb, const DeviceGrid& grid, const t_wire_type_sizes* wire_type_sizes_x, const t_wire_type_sizes* wire_type_sizes_y, e_directionality directionality, t_sb_connection_map* sb_conns, vtr::RandState& rand_state, 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 */ - std::vector from_chan_type, to_chan_type; /* the type of channel - i.e. CHANX or CHANY */ + t_rr_type from_chan_type, to_chan_type; /* the type of channel - i.e. CHANX or CHANY */ from_x = from_y = to_x = to_y = from_layer = to_layer = UNDEFINED; SB_Side_Connection side_conn(from_side, to_side); /* for indexing into this switchblock's permutation funcs */ @@ -674,46 +674,40 @@ static void compute_wire_connections(int x_coord, int y_coord, int layer_coord, * destination channels. also return the channel type (ie chanx/chany/both) into which we are * indexing */ /* details for source channel */ - const std::vector from_chan_details = index_into_correct_chan(x_coord, y_coord, layer_coord, from_side, chan_details_x, chan_details_y, + const t_chan_details from_chan_details = index_into_correct_chan(x_coord, y_coord, layer_coord, from_side, chan_details_x, chan_details_y, from_x, from_y, from_layer, from_chan_type); /* details for destination channel */ - const std::vector to_chan_details = index_into_correct_chan(x_coord, y_coord, layer_coord, to_side, chan_details_x, chan_details_y, + const t_chan_details to_chan_details = index_into_correct_chan(x_coord, y_coord, layer_coord, to_side, chan_details_x, chan_details_y, to_x, to_y, to_layer, to_chan_type); - //check from/to_chan_details size matches the from/to_chan_type size - VTR_ASSERT(from_chan_details.size() == from_chan_type.size()); - VTR_ASSERT(to_chan_details.size() == to_chan_type.size()); - for (size_t from_chan_index = 0; from_chan_index < from_chan_details.size(); from_chan_index++) { - for (size_t to_chan_index = 0; to_chan_index < to_chan_details.size(); to_chan_index++) { - /* 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.at(to_chan_index)) || coords_out_of_bounds(grid, from_x, from_y, from_layer, from_chan_type.at(from_chan_index))) { - return; - } + /* make sure from_x/y and to_x/y aren't out of bounds */ + if (coords_out_of_bounds(grid, to_x, to_y, to_layer, to_chan_type) || coords_out_of_bounds(grid, from_x, from_y, from_layer, from_chan_type)) { + return; + } - const t_wire_type_sizes* wire_type_sizes_from = wire_type_sizes_x; - const t_wire_type_sizes* wire_type_sizes_to = wire_type_sizes_x; - if (from_chan_type.at(from_chan_index) == CHANY) { - wire_type_sizes_from = wire_type_sizes_y; - } - if (to_chan_type.at(to_chan_index) == CHANY) { - wire_type_sizes_to = wire_type_sizes_y; - } + const t_wire_type_sizes* wire_type_sizes_from = wire_type_sizes_x; + const t_wire_type_sizes* wire_type_sizes_to = wire_type_sizes_x; + if (from_chan_type == CHANY) { + wire_type_sizes_from = wire_type_sizes_y; + } + if (to_chan_type == CHANY) { + wire_type_sizes_to = wire_type_sizes_y; + } - /* iterate over all the wire connections specified for this switch block */ - for (int iconn = 0; iconn < (int)sb->wireconns.size(); iconn++) { - /* pointer to a connection specification between wire types/subsegment_nums */ - t_wireconn_inf* wireconn_ptr = &sb->wireconns[iconn]; + /* iterate over all the wire connections specified for this switch block */ + for (int iconn = 0; iconn < (int)sb->wireconns.size(); iconn++) { + /* pointer to a connection specification between wire types/subsegment_nums */ + t_wireconn_inf* wireconn_ptr = &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.at(from_chan_index), to_chan_details.at(to_chan_index), - sb_conn, from_x, from_y, from_layer, to_x, to_y, to_layer, from_chan_type.at(from_chan_index), to_chan_type.at(to_chan_index), wire_type_sizes_from, - wire_type_sizes_to, sb, wireconn_ptr, sb_conns, rand_state, scratchpad); - } - } + /* compute the destination wire segments to which the source wire segment should connect based on the + * current wireconn */ + compute_wireconn_connections(grid, directionality, from_chan_details, to_chan_details, + sb_conn, from_x, from_y, from_layer, to_x, to_y, to_layer, from_chan_type, to_chan_type, wire_type_sizes_from, + wire_type_sizes_to, sb, wireconn_ptr, sb_conns, rand_state, scratchpad); } + return; } @@ -915,8 +909,8 @@ static int evaluate_num_conns_formula(t_wireconn_scratchpad* scratchpad, std::st /* Here we find the correct channel (x or y or both), and the coordinates to index into it based on the * specified tile coordinates (x,y,layer) and the switchblock side. Also returns the type of channel * that we are indexing into (ie, CHANX or CHANY) */ -static const std::vector index_into_correct_chan(int tile_x, int tile_y, int tile_layer, enum e_side side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int& chan_x, int& chan_y, int& chan_layer, std::vector& chan_type) { - std::vector chan_details; +static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, int tile_layer, enum e_side side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int& chan_x, int& chan_y, int& chan_layer, t_rr_type& chan_type){ + chan_type = CHANX; /* here we use the VPR convention that a tile 'owns' the channels directly to the right * and above it */ switch (side) { @@ -925,65 +919,55 @@ static const std::vector index_into_correct_chan(int tile_x, int chan_x = tile_x; chan_y = tile_y + 1; chan_layer = tile_layer; - chan_type.push_back(CHANY); - chan_details.push_back(chan_details_y); - return chan_details; + chan_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_type.push_back(CHANX); - chan_details.push_back(chan_details_x); - return chan_details; + chan_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_type.push_back(CHANY); + chan_type = CHANY; chan_layer = tile_layer; - chan_details.push_back(chan_details_y); - return chan_details; + 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_type.push_back(CHANX); + chan_type = CHANX; chan_layer = tile_layer; - chan_details.push_back(chan_details_x); - return chan_details; + 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_type.push_back(CHANX); - chan_type.push_back(CHANY); - chan_details.push_back(chan_details_x); - chan_details.push_back(chan_details_y); - return chan_details; + chan_type = CHANX; + return chan_details_x; 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_type.push_back(CHANX); - chan_type.push_back(CHANY); - chan_details.push_back(chan_details_x); - chan_details.push_back(chan_details_y); - return chan_details; + chan_type = CHANX; + return chan_details_x; break; default: VPR_FATAL_ERROR(VPR_ERROR_ARCH, "index_into_correct_chan: unknown side specified: %d\n", side); break; } VTR_ASSERT(false); - return chan_details; //Unreachable, return empty vector + 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) { From cf52ff250794ed3e9e1fb84a67237828430c07bd Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Mon, 4 Dec 2023 18:08:33 -0500 Subject: [PATCH 47/83] modified index_into_correct_chan to use chanx/chany based on src side for ABOVE and UNDER sides --- vpr/src/route/build_switchblocks.cpp | 41 +++++++++++++++++++--------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/vpr/src/route/build_switchblocks.cpp b/vpr/src/route/build_switchblocks.cpp index a40717b9a20..579bc81a568 100644 --- a/vpr/src/route/build_switchblocks.cpp +++ b/vpr/src/route/build_switchblocks.cpp @@ -273,7 +273,25 @@ static void get_switchpoint_wires( std::vector* output_wires, std::vector* scratch_wires); -static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, int tile_layer, enum e_side side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int& chan_x, int& chan_y, int& chan_layer, t_rr_type& chan_type); +/** + * @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 src_side switch block source side + * @param dest_side swtich 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) + */ +static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, int tile_layer, enum e_side src_side, enum e_side dest_side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int& chan_x, int& chan_y, int& chan_layer, t_rr_type& chan_type); /** * @brief check whether a specific track location is valid within the device grid @@ -674,11 +692,11 @@ static void compute_wire_connections(int x_coord, int y_coord, int layer_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, chan_details_x, chan_details_y, + const t_chan_details from_chan_details = index_into_correct_chan(x_coord, y_coord, layer_coord, from_side, to_side, chan_details_x, chan_details_y, from_x, from_y, from_layer, from_chan_type); /* details for destination channel */ - const t_chan_details to_chan_details = index_into_correct_chan(x_coord, y_coord, layer_coord, to_side, chan_details_x, chan_details_y, + const t_chan_details to_chan_details = index_into_correct_chan(x_coord, y_coord, layer_coord, to_side, from_side, chan_details_x, chan_details_y, to_x, to_y, to_layer, to_chan_type); @@ -906,14 +924,11 @@ static int evaluate_num_conns_formula(t_wireconn_scratchpad* scratchpad, std::st return scratchpad->formula_parser.parse_formula(num_conns_formula, vars); } -/* Here we find the correct channel (x or y or both), and the coordinates to index into it based on the - * specified tile coordinates (x,y,layer) and the switchblock side. Also returns the type of channel - * that we are indexing into (ie, CHANX or CHANY) */ -static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, int tile_layer, enum e_side side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int& chan_x, int& chan_y, int& chan_layer, t_rr_type& chan_type){ +static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, int tile_layer, enum e_side src_side, enum e_side dest_side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int& chan_x, int& chan_y, int& chan_layer, t_rr_type& chan_type){ chan_type = CHANX; /* here we use the VPR convention that a tile 'owns' the channels directly to the right * and above it */ - switch (side) { + switch (src_side) { case TOP: /* this is y-channel belonging to tile above in the same layer */ chan_x = tile_x; @@ -951,19 +966,19 @@ static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, int chan_x = tile_x; chan_y = tile_y; chan_layer = tile_layer + 1; - chan_type = CHANX; - return chan_details_x; + chan_type = (dest_side == RIGHT || dest_side == LEFT) ? CHANX : 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_type = CHANX; - return chan_details_x; + chan_type = (dest_side == RIGHT || dest_side == LEFT) ? CHANX : 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", side); + VPR_FATAL_ERROR(VPR_ERROR_ARCH, "index_into_correct_chan: unknown side specified: %d\n", src_side); break; } VTR_ASSERT(false); From e7f062952e7ee02b0c2dfe9fcfbd0191389cc37d Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Mon, 4 Dec 2023 18:19:13 -0500 Subject: [PATCH 48/83] added a new 3D architecture file with only inter-die connections in SBs --- .../3d_SB_inter_die_stratixiv_arch.timing.xml | 48420 ++++++++++++++++ 1 file changed, 48420 insertions(+) create mode 100644 vtr_flow/arch/multi_die/stratixiv_3d/3d_SB_inter_die_stratixiv_arch.timing.xml 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 new file mode 100644 index 00000000000..ecae1edded7 --- /dev/null +++ b/vtr_flow/arch/multi_die/stratixiv_3d/3d_SB_inter_die_stratixiv_arch.timing.xml @@ -0,0 +1,48420 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + io.core_out[0:19] + io.core_in[0:24] io.clk[0:2] + io.core_out[20:39] + io.core_in[24:49] io.clk[3:4] + io.core_out[0:19] + io.core_in[0:24] io.clk[0:2] + io.core_out[20:39] + io.core_in[24:49] io.clk[3:4] + + + + + + + + + + + + + + + PLL.out_clock PLL.out_signal + PLL.in_signal PLL.in_clock + PLL.out_clock PLL.out_signal + PLL.in_signal PLL.in_clock + PLL.out_clock PLL.out_signal + PLL.in_signal PLL.in_clock + PLL.out_clock PLL.out_signal + PLL.in_signal PLL.in_clock + + + + + + + + + + + + + + + + + + + + + + + + + + + LAB.data_out[0:19] + LAB.data_in[0:39] LAB.control_in[0:3] LAB.clk[0] + LAB.data_out[20:39] + LAB.data_in[40:79] LAB.control_in[4:6] LAB.clk[1] + LAB.data_out + LAB.data_in LAB.control_in LAB.clk LAB.cin LAB.sharein + LAB.cout LAB.shareout + + + + + + + + + + + + + + + + + + + + + + + + + + + DSP.data_out_top[17:0] DSP.scan_a_out[1:0] + DSP.data_in[35:0] DSP.control_in[2:0] DSP.scan_a_in[1:0] DSP.clk[0] + DSP.data_out_top[35:18] DSP.scan_a_out[3:2] DSP.signal_out[0:0] + DSP.data_in[71:36] DSP.control_in[4:3] DSP.scan_a_in[4:2] + DSP.data_out_top[53:36] DSP.scan_a_out[5:4] DSP.signal_out[1:1] + DSP.data_in[107:72] DSP.control_in[6:5] DSP.scan_a_in[6:5] DSP.clk[1] + DSP.data_out_top[71:54] DSP.scan_a_out[7:6] DSP.signal_out[2:2] + DSP.data_in[144:108] DSP.control_in[8:6] DSP.scan_a_in[8:7] + DSP.data_out_top[35:0] DSP.scan_a_out[3:0] DSP.signal_out[0:0] + DSP.data_in[143:72] DSP.control_in[3:0] DSP.scan_a_in[3:0] DSP.clk[0] DSP.chain_in + DSP.data_out_top[71:36] DSP.scan_a_out[9:4] DSP.signal_out[2:1] + DSP.data_in[71:0] DSP.control_in[8:4] DSP.scan_a_in[8:4] DSP.clk[1] + + + + DSP.data_out_bot[17:0] DSP.scan_a_out[9:8] + DSP.data_in[179:145] DSP.control_in[11:9] DSP.scan_a_in[10:9] DSP.clk[2] + DSP.data_out_bot[35:18] DSP.scan_a_out[11:10] DSP.signal_out[3:3] + DSP.data_in[215:180] DSP.control_in[13:12] DSP.scan_a_in[12:11] + DSP.data_out_bot[53:36] DSP.scan_a_out[13:12] DSP.signal_out[4:4] + DSP.data_in[251:216] DSP.control_in[15:14] DSP.scan_a_in[14:13] + DSP.data_out_bot[71:54] DSP.scan_a_out[15:14] DSP.signal_out[5:5] + DSP.data_in[287:252] DSP.control_in[20:16] DSP.scan_a_in[17:15] DSP.clk[3] + DSP.data_out_bot[35:0] DSP.scan_a_out[12:10] DSP.signal_out[3:3] + DSP.data_in[287:215] DSP.control_in[13:9] DSP.scan_a_in[13:9] DSP.clk[2] + DSP.data_out_bot[71:36] DSP.scan_a_out[17:13] DSP.signal_out[5:4] + DSP.data_in[214:144] DSP.control_in[20:16] DSP.scan_a_in[17:14] DSP.clk[3] + + DSP.chain_out + + + + + + + + + + + + + + + + + + M9K.data_out[17:0] M9K.control_out[1:0] + M9K.data_addr_control_in[51:0] M9K.clk_in[0] + M9K.data_out[35:18] M9K.control_out[2:2] + M9K.data_addr_control_in[103:52] M9K.clk_in[1] + M9K.data_out M9K.control_out + M9K.data_addr_control_in M9K.clk_in + + + + + + + + + + + + + + + + + + + M144K.data_out[7:0] + M144K.data_addr_control_in[24:0] + M144K.data_out[15:8] + M144K.data_addr_control_in[50:25] + M144K.data_out[22:16] + M144K.data_addr_control_in[76:51] + M144K.data_out[29:23] + M144K.data_addr_control_in[102:77] + M144K.data_out[36:30] M144K.control_out[0] + M144K.data_addr_control_in[128:103] M144K.clk_in[0] + M144K.data_out[43:37] M144K.control_out[1] + M144K.data_addr_control_in[154:129] + M144K.data_out[51:44] + M144K.data_addr_control_in[180:155] + M144K.data_out[59:52] + M144K.data_addr_control_in[206:181] + M144K.data_out[67:60] + M144K.data_addr_control_in[232:207] + M144K.data_out[75:68] + M144K.data_addr_control_in[258:233] + M144K.data_out[82:76] + M144K.data_addr_control_in[284:259] + M144K.data_out[89:83] M144K.control_out[2] + M144K.data_addr_control_in[310:285] + M144K.data_out[96:90] + M144K.data_addr_control_in[336:311] M144K.clk_in[1] + M144K.data_out[103:97] + M144K.data_addr_control_in[362:337] + M144K.data_out[111:104] + M144K.data_addr_control_in[388:363] + M144K.data_out[119:112] + M144K.data_addr_control_in[415:389] + M144K.data_out[14:0] + M144K.data_addr_control_in[51:0] + M144K.data_out[29:15] + M144K.data_addr_control_in[103:52] + M144K.data_out[44:30] M144K.control_out[0] + M144K.data_addr_control_in[155:104] + M144K.data_out[59:45] M144K.control_out[1] + M144K.data_addr_control_in[207:156] M144K.clk_in[0] + M144K.data_addr_control_in[259:208] M144K.clk_in[1] + M144K.data_out[74:60] M144K.control_out[2] + M144K.data_out[89:75] + M144K.data_addr_control_in[311:260] + M144K.data_out[104:90] + M144K.data_addr_control_in[363:312] + M144K.data_out[119:105] + M144K.data_addr_control_in[415:364] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 1 1 1 1 + 1 1 1 1 + + + + + + + 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 261e-12 + 261e-12 + 261e-12 + 261e-12 + 261e-12 + 261e-12 + + + 193e-12 + 193e-12 + 193e-12 + 193e-12 + 193e-12 + 193e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From c78fc923ad17ec1b704c26651a8990471d82ba59 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Mon, 4 Dec 2023 18:42:38 -0500 Subject: [PATCH 49/83] removed extra pinlocations tag within the 3D SB arch file --- vpr/src/route/build_switchblocks.cpp | 2 +- .../3d_SB_inter_die_stratixiv_arch.timing.xml | 150 ++++++------------ 2 files changed, 51 insertions(+), 101 deletions(-) diff --git a/vpr/src/route/build_switchblocks.cpp b/vpr/src/route/build_switchblocks.cpp index 579bc81a568..b51c4893265 100644 --- a/vpr/src/route/build_switchblocks.cpp +++ b/vpr/src/route/build_switchblocks.cpp @@ -289,7 +289,7 @@ static void get_switchpoint_wires( * @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) + * @return returns the type of channel that we are indexing into (ie, CHANX or CHANY) and channel coordinates and type */ static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, int tile_layer, enum e_side src_side, enum e_side dest_side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int& chan_x, int& chan_y, int& chan_layer, t_rr_type& chan_type); 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 ecae1edded7..415240a8a0b 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 @@ -4437,14 +4437,10 @@ to each side of the IO block. This means that each pin is accessible from one vertical and one horizontal channel. Like the LAB below the Fc values have been adjusted to account for this. --> - io.core_out[0:19] - io.core_in[0:24] io.clk[0:2] - io.core_out[20:39] - io.core_in[24:49] io.clk[3:4] - io.core_out[0:19] - io.core_in[0:24] io.clk[0:2] - io.core_out[20:39] - io.core_in[24:49] io.clk[3:4] + io.core_out[0:19] io.core_in[0:24] io.clk[0:2] + io.core_out[20:39] io.core_in[24:49] io.clk[3:4] + io.core_out[0:19] io.core_in[0:24] io.clk[0:2] + io.core_in[24:49] io.clk[3:4] io.core_out[20:39] @@ -4459,14 +4455,10 @@ - PLL.out_clock PLL.out_signal - PLL.in_signal PLL.in_clock - PLL.out_clock PLL.out_signal - PLL.in_signal PLL.in_clock - PLL.out_clock PLL.out_signal - PLL.in_signal PLL.in_clock - PLL.out_clock PLL.out_signal - PLL.in_signal PLL.in_clock + PLL.out_clock PLL.out_signal PLL.in_signal PLL.in_clock + PLL.out_clock PLL.out_signal PLL.in_signal PLL.in_clock + PLL.out_clock PLL.out_signal PLL.in_signal PLL.in_clock + PLL.out_clock PLL.out_signal PLL.in_signal PLL.in_clock @@ -4528,12 +4520,9 @@ each block pin can connect to some Vertical and some Horizontal wires in Stratix IV. Note that Fc_in/Fc_out have been scaled to account for this. --> - LAB.data_out[0:19] - LAB.data_in[0:39] LAB.control_in[0:3] LAB.clk[0] - LAB.data_out[20:39] - LAB.data_in[40:79] LAB.control_in[4:6] LAB.clk[1] - LAB.data_out - LAB.data_in LAB.control_in LAB.clk LAB.cin LAB.sharein + LAB.data_out[0:19] LAB.data_in[0:39] LAB.control_in[0:3] LAB.clk[0] + LAB.data_out[20:39] LAB.data_in[40:79] LAB.control_in[4:6] LAB.clk[1] + LAB.data_out LAB.data_in LAB.control_in LAB.clk LAB.cin LAB.sharein LAB.cout LAB.shareout @@ -4611,33 +4600,21 @@ routing hot-spots. --> - DSP.data_out_top[17:0] DSP.scan_a_out[1:0] - DSP.data_in[35:0] DSP.control_in[2:0] DSP.scan_a_in[1:0] DSP.clk[0] - DSP.data_out_top[35:18] DSP.scan_a_out[3:2] DSP.signal_out[0:0] - DSP.data_in[71:36] DSP.control_in[4:3] DSP.scan_a_in[4:2] - DSP.data_out_top[53:36] DSP.scan_a_out[5:4] DSP.signal_out[1:1] - DSP.data_in[107:72] DSP.control_in[6:5] DSP.scan_a_in[6:5] DSP.clk[1] - DSP.data_out_top[71:54] DSP.scan_a_out[7:6] DSP.signal_out[2:2] - DSP.data_in[144:108] DSP.control_in[8:6] DSP.scan_a_in[8:7] - DSP.data_out_top[35:0] DSP.scan_a_out[3:0] DSP.signal_out[0:0] - DSP.data_in[143:72] DSP.control_in[3:0] DSP.scan_a_in[3:0] DSP.clk[0] DSP.chain_in - DSP.data_out_top[71:36] DSP.scan_a_out[9:4] DSP.signal_out[2:1] - DSP.data_in[71:0] DSP.control_in[8:4] DSP.scan_a_in[8:4] DSP.clk[1] + DSP.data_out_top[17:0] DSP.scan_a_out[1:0] DSP.data_in[35:0] DSP.control_in[2:0] DSP.scan_a_in[1:0] DSP.clk[0] + DSP.data_out_top[35:18] DSP.scan_a_out[3:2] DSP.signal_out[0:0] DSP.data_in[71:36] DSP.control_in[4:3] DSP.scan_a_in[4:2] + DSP.data_out_top[53:36] DSP.scan_a_out[5:4] DSP.signal_out[1:1] DSP.data_in[107:72] DSP.control_in[6:5] DSP.scan_a_in[6:5] DSP.clk[1] + DSP.data_out_top[71:54] DSP.scan_a_out[7:6] DSP.signal_out[2:2] DSP.data_in[144:108] DSP.control_in[8:6] DSP.scan_a_in[8:7] + DSP.data_out_top[35:0] DSP.scan_a_out[3:0] DSP.signal_out[0:0] DSP.data_in[143:72] DSP.control_in[3:0] DSP.scan_a_in[3:0] DSP.clk[0] DSP.chain_in + DSP.data_out_top[71:36] DSP.scan_a_out[9:4] DSP.signal_out[2:1] DSP.data_in[71:0] DSP.control_in[8:4] DSP.scan_a_in[8:4] DSP.clk[1] - DSP.data_out_bot[17:0] DSP.scan_a_out[9:8] - DSP.data_in[179:145] DSP.control_in[11:9] DSP.scan_a_in[10:9] DSP.clk[2] - DSP.data_out_bot[35:18] DSP.scan_a_out[11:10] DSP.signal_out[3:3] - DSP.data_in[215:180] DSP.control_in[13:12] DSP.scan_a_in[12:11] - DSP.data_out_bot[53:36] DSP.scan_a_out[13:12] DSP.signal_out[4:4] - DSP.data_in[251:216] DSP.control_in[15:14] DSP.scan_a_in[14:13] - DSP.data_out_bot[71:54] DSP.scan_a_out[15:14] DSP.signal_out[5:5] - DSP.data_in[287:252] DSP.control_in[20:16] DSP.scan_a_in[17:15] DSP.clk[3] - DSP.data_out_bot[35:0] DSP.scan_a_out[12:10] DSP.signal_out[3:3] - DSP.data_in[287:215] DSP.control_in[13:9] DSP.scan_a_in[13:9] DSP.clk[2] - DSP.data_out_bot[71:36] DSP.scan_a_out[17:13] DSP.signal_out[5:4] - DSP.data_in[214:144] DSP.control_in[20:16] DSP.scan_a_in[17:14] DSP.clk[3] + DSP.data_out_bot[17:0] DSP.scan_a_out[9:8] DSP.data_in[179:145] DSP.control_in[11:9] DSP.scan_a_in[10:9] DSP.clk[2] + DSP.data_out_bot[35:18] DSP.scan_a_out[11:10] DSP.signal_out[3:3] DSP.data_in[215:180] DSP.control_in[13:12] DSP.scan_a_in[12:11] + DSP.data_in[251:216] DSP.control_in[15:14] DSP.scan_a_in[14:13] DSP.data_out_bot[53:36] DSP.scan_a_out[13:12] DSP.signal_out[4:4] + DSP.data_in[287:252] DSP.control_in[20:16] DSP.scan_a_in[17:15] DSP.clk[3] DSP.data_out_bot[71:54] DSP.scan_a_out[15:14] DSP.signal_out[5:5] + DSP.data_in[287:215] DSP.control_in[13:9] DSP.scan_a_in[13:9] DSP.clk[2] DSP.data_out_bot[35:0] DSP.scan_a_out[12:10] DSP.signal_out[3:3] + DSP.data_in[214:144] DSP.control_in[20:16] DSP.scan_a_in[17:14] DSP.clk[3] DSP.data_out_bot[71:36] DSP.scan_a_out[17:13] DSP.signal_out[5:4] DSP.chain_out @@ -4676,12 +4653,9 @@ each block pin can connect to some Vertical and some Horizontal wires in Stratix IV. Note that Fc_in/Fc_out have been scaled to account for this. --> - M9K.data_out[17:0] M9K.control_out[1:0] - M9K.data_addr_control_in[51:0] M9K.clk_in[0] - M9K.data_out[35:18] M9K.control_out[2:2] - M9K.data_addr_control_in[103:52] M9K.clk_in[1] - M9K.data_out M9K.control_out - M9K.data_addr_control_in M9K.clk_in + M9K.data_out[17:0] M9K.control_out[1:0] M9K.data_addr_control_in[51:0] M9K.clk_in[0] + M9K.data_out[35:18] M9K.control_out[2:2] M9K.data_addr_control_in[103:52] M9K.clk_in[1] + M9K.data_out M9K.control_out M9K.data_addr_control_in M9K.clk_in @@ -4719,54 +4693,30 @@ each block pin can connect to some Vertical and some Horizontal wires in Stratix IV. Note that Fc_in/Fc_out have been scaled to account for this. --> - M144K.data_out[7:0] - M144K.data_addr_control_in[24:0] - M144K.data_out[15:8] - M144K.data_addr_control_in[50:25] - M144K.data_out[22:16] - M144K.data_addr_control_in[76:51] - M144K.data_out[29:23] - M144K.data_addr_control_in[102:77] - M144K.data_out[36:30] M144K.control_out[0] - M144K.data_addr_control_in[128:103] M144K.clk_in[0] - M144K.data_out[43:37] M144K.control_out[1] - M144K.data_addr_control_in[154:129] - M144K.data_out[51:44] - M144K.data_addr_control_in[180:155] - M144K.data_out[59:52] - M144K.data_addr_control_in[206:181] - M144K.data_out[67:60] - M144K.data_addr_control_in[232:207] - M144K.data_out[75:68] - M144K.data_addr_control_in[258:233] - M144K.data_out[82:76] - M144K.data_addr_control_in[284:259] - M144K.data_out[89:83] M144K.control_out[2] - M144K.data_addr_control_in[310:285] - M144K.data_out[96:90] - M144K.data_addr_control_in[336:311] M144K.clk_in[1] - M144K.data_out[103:97] - M144K.data_addr_control_in[362:337] - M144K.data_out[111:104] - M144K.data_addr_control_in[388:363] - M144K.data_out[119:112] - M144K.data_addr_control_in[415:389] - M144K.data_out[14:0] - M144K.data_addr_control_in[51:0] - M144K.data_out[29:15] - M144K.data_addr_control_in[103:52] - M144K.data_out[44:30] M144K.control_out[0] - M144K.data_addr_control_in[155:104] - M144K.data_out[59:45] M144K.control_out[1] - M144K.data_addr_control_in[207:156] M144K.clk_in[0] - M144K.data_addr_control_in[259:208] M144K.clk_in[1] - M144K.data_out[74:60] M144K.control_out[2] - M144K.data_out[89:75] - M144K.data_addr_control_in[311:260] - M144K.data_out[104:90] - M144K.data_addr_control_in[363:312] - M144K.data_out[119:105] - M144K.data_addr_control_in[415:364] + M144K.data_out[7:0] M144K.data_addr_control_in[24:0] + M144K.data_out[15:8] M144K.data_addr_control_in[50:25] + M144K.data_out[22:16] M144K.data_addr_control_in[76:51] + M144K.data_out[29:23] + M144K.data_out[36:30] M144K.control_out[0] M144K.data_addr_control_in[128:103] M144K.clk_in[0] + M144K.data_out[43:37] M144K.control_out[1] M144K.data_addr_control_in[154:129] + M144K.data_out[51:44] M144K.data_addr_control_in[180:155] + M144K.data_out[59:52] M144K.data_addr_control_in[206:181] + M144K.data_out[67:60] M144K.data_addr_control_in[232:207] + M144K.data_out[75:68] M144K.data_addr_control_in[258:233] + M144K.data_out[82:76] M144K.data_addr_control_in[284:259] + M144K.data_out[89:83] M144K.control_out[2] M144K.data_addr_control_in[310:285] + M144K.data_out[96:90] M144K.data_addr_control_in[336:311] M144K.clk_in[1] + M144K.data_out[103:97] M144K.data_addr_control_in[362:337] + M144K.data_out[111:104] M144K.data_addr_control_in[388:363] + M144K.data_out[119:112] M144K.data_addr_control_in[415:389] + M144K.data_out[14:0] M144K.data_addr_control_in[51:0] + M144K.data_out[29:15] M144K.data_addr_control_in[103:52] + M144K.data_out[44:30] M144K.control_out[0] M144K.data_addr_control_in[155:104] + M144K.data_out[59:45] M144K.control_out[1] M144K.data_addr_control_in[207:156] M144K.clk_in[0] + M144K.data_addr_control_in[259:208] M144K.clk_in[1] M144K.data_out[74:60] M144K.control_out[2] + M144K.data_out[89:75] M144K.data_addr_control_in[311:260] + M144K.data_out[104:90] M144K.data_addr_control_in[363:312] + M144K.data_out[119:105] M144K.data_addr_control_in[415:364] From f274fbcaceb60b25dc9052b69997e6977d25e620 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Mon, 4 Dec 2023 18:44:58 -0500 Subject: [PATCH 50/83] make format --- libs/libarchfpga/src/physical_types.h | 4 ++-- vpr/src/route/build_switchblocks.cpp | 11 +++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/libs/libarchfpga/src/physical_types.h b/libs/libarchfpga/src/physical_types.h index 3588922a816..ffd1aee8ea2 100644 --- a/libs/libarchfpga/src/physical_types.h +++ b/libs/libarchfpga/src/physical_types.h @@ -184,8 +184,8 @@ enum e_side : unsigned char { 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 +constexpr std::array TOTAL_3D_SIDES = {{TOP, RIGHT, BOTTOM, LEFT, ABOVE, UNDER}}; //Set of all side orientations including different layers +constexpr std::array TOTAL_3D_SIDE_STRINGS = {{"TOP", "RIGHT", "BOTTOM", "LEFT", "ABOVE", "UNDER"}}; //String versions of side orientations including different layers /* pin location distributions */ enum e_pin_location_distr { diff --git a/vpr/src/route/build_switchblocks.cpp b/vpr/src/route/build_switchblocks.cpp index b51c4893265..1b25ef7dadb 100644 --- a/vpr/src/route/build_switchblocks.cpp +++ b/vpr/src/route/build_switchblocks.cpp @@ -670,8 +670,8 @@ static void get_switchpoint_wires( } static void compute_wire_connections(int x_coord, int y_coord, int layer_coord, enum e_side from_side, enum e_side to_side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, t_switchblock_inf* sb, const DeviceGrid& grid, const t_wire_type_sizes* wire_type_sizes_x, const t_wire_type_sizes* wire_type_sizes_y, e_directionality directionality, t_sb_connection_map* sb_conns, vtr::RandState& rand_state, 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 */ + int from_x, from_y, from_layer; /* index into source channel */ + int to_x, to_y, to_layer; /* index into destination channel */ t_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; @@ -693,12 +693,11 @@ static void compute_wire_connections(int x_coord, int y_coord, int layer_coord, * 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, - from_x, from_y, from_layer, from_chan_type); + 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, - to_x, to_y, to_layer, to_chan_type); - + to_x, to_y, to_layer, to_chan_type); /* make sure from_x/y and to_x/y aren't out of bounds */ if (coords_out_of_bounds(grid, to_x, to_y, to_layer, to_chan_type) || coords_out_of_bounds(grid, from_x, from_y, from_layer, from_chan_type)) { @@ -924,7 +923,7 @@ static int evaluate_num_conns_formula(t_wireconn_scratchpad* scratchpad, std::st return scratchpad->formula_parser.parse_formula(num_conns_formula, vars); } -static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, int tile_layer, enum e_side src_side, enum e_side dest_side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int& chan_x, int& chan_y, int& chan_layer, t_rr_type& chan_type){ +static const t_chan_details& index_into_correct_chan(int tile_x, int tile_y, int tile_layer, enum e_side src_side, enum e_side dest_side, const t_chan_details& chan_details_x, const t_chan_details& chan_details_y, int& chan_x, int& chan_y, int& chan_layer, t_rr_type& chan_type) { chan_type = CHANX; /* here we use the VPR convention that a tile 'owns' the channels directly to the right * and above it */ From c46aec0a66b594f79d75f30ff18c264beae6b58c Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Mon, 4 Dec 2023 20:26:16 -0500 Subject: [PATCH 51/83] removed duplicated code by making a helper function --- vpr/src/route/build_switchblocks.cpp | 4 +- vpr/src/route/rr_graph2.cpp | 112 +++++++++++++++++++-------- 2 files changed, 80 insertions(+), 36 deletions(-) diff --git a/vpr/src/route/build_switchblocks.cpp b/vpr/src/route/build_switchblocks.cpp index 1b25ef7dadb..c14eea50788 100644 --- a/vpr/src/route/build_switchblocks.cpp +++ b/vpr/src/route/build_switchblocks.cpp @@ -692,11 +692,11 @@ static void compute_wire_connections(int x_coord, int y_coord, int layer_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(x_coord, y_coord, layer_coord, from_side, to_side, chan_details_x, chan_details_y, from_x, from_y, from_layer, from_chan_type); /* details for destination channel */ - 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(x_coord, y_coord, layer_coord, to_side, from_side, chan_details_x, chan_details_y, to_x, to_y, to_layer, to_chan_type); /* make sure from_x/y and to_x/y aren't out of bounds */ diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index 3c3664a84b6..8db3e824d18 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -168,6 +168,44 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, RRNodeId from_rr_node, t_rr_edge_info_set& 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(enum e_side src_side, enum e_side dest_side); + +/** + * @brief finds crossponding 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 multi_layer_track_conn 3D custom switch block information (offset to correct extra CHANX nodes, source tracks, ..) + * @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 + * + */ +static void set_multi_layer_track_conn(RRGraphBuilder& rr_graph_builder, + vtr::NdMatrix& multi_layer_track_conn, + 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, + int& curr_switchblocks_offset); + static int vpr_to_phy_track(const int itrack, const int chan_num, const int seg_num, @@ -1183,6 +1221,35 @@ static void load_chan_rr_indices(const int max_chan_width, } } +static bool is_sb_conn_layer_crossing(enum e_side src_side, enum 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 void set_multi_layer_track_conn(RRGraphBuilder& rr_graph_builder, vtr::NdMatrix& multi_layer_track_conn, 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, int& curr_switchblocks_offset){ + 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); + + int rr_node_type_index = (from_wire_type == CHANX) ? 1 : 0; + + if (from_inode && to_inode) { + if (multi_layer_track_conn[to_wire_layer][x][y][to_wire][rr_node_type_index].offset_to_extra_chanx_node == -1) { + multi_layer_track_conn[to_wire_layer][x][y][to_wire][rr_node_type_index].offset_to_extra_chanx_node = curr_switchblocks_offset; + curr_switchblocks_offset++; + } + multi_layer_track_conn[to_wire_layer][x][y][to_wire][rr_node_type_index].from_tracks.push_back(from_wire); + } +} + + vtr::NdMatrix get_number_track_to_track_inter_die_conn(vtr::NdMatrix& multi_layer_track_conn, t_sb_connection_map* sb_conn_map, RRGraphBuilder& rr_graph_builder) { @@ -1196,43 +1263,20 @@ vtr::NdMatrix get_number_track_to_track_inter_die_conn(vtr::NdMatrixcount(sb_coord) > 0) { std::vector& conn_vector = (*sb_conn_map)[sb_coord]; for (int iconn = 0; iconn < (int)conn_vector.size(); ++iconn) { - if (conn_vector[iconn].to_wire_layer == conn_vector[iconn].from_wire_layer) { - //this connection doesn't cross any layer, no new node is required - continue; - } else { - //check if both from_node and to_node exists in the rr-graph - - //CHANY -> CHANX connection - RRNodeId from_inode = rr_graph_builder.node_lookup().find_node(conn_vector[iconn].from_wire_layer, x, y, CHANY, conn_vector[iconn].from_wire_layer); - RRNodeId to_inode = rr_graph_builder.node_lookup().find_node(conn_vector[iconn].to_wire_layer, x, y, CHANX, conn_vector[iconn].to_wire); - if (from_inode && to_inode) { - if (multi_layer_track_conn[conn_vector[iconn].to_wire_layer][x][y][conn_vector[iconn].to_wire][1].offset_to_extra_chanx_node == -1) { - multi_layer_track_conn[conn_vector[iconn].to_wire_layer][x][y][conn_vector[iconn].to_wire][1].offset_to_extra_chanx_node = curr_switchblocks_offset; - curr_switchblocks_offset++; - } - multi_layer_track_conn[conn_vector[iconn].to_wire_layer][x][y][conn_vector[iconn].to_wire][1].from_tracks.push_back(conn_vector[iconn].from_wire); - } - - //CHANX -> CHANY connection - from_inode = rr_graph_builder.node_lookup().find_node(conn_vector[iconn].from_wire_layer, x, y, CHANX, conn_vector[iconn].from_wire_layer); - to_inode = rr_graph_builder.node_lookup().find_node(conn_vector[iconn].to_wire_layer, x, y, CHANY, conn_vector[iconn].to_wire); - if (from_inode && to_inode) { - if (multi_layer_track_conn[conn_vector[iconn].to_wire_layer][x][y][conn_vector[iconn].to_wire][0].offset_to_extra_chanx_node == -1) { - multi_layer_track_conn[conn_vector[iconn].to_wire_layer][x][y][conn_vector[iconn].to_wire][0].offset_to_extra_chanx_node = curr_switchblocks_offset; - curr_switchblocks_offset++; - } - multi_layer_track_conn[conn_vector[iconn].to_wire_layer][x][y][conn_vector[iconn].to_wire][0].from_tracks.push_back(conn_vector[iconn].from_wire); - } - } + //check if both from_node and to_node exists in the rr-graph + //CHANY -> CHANX connection + set_multi_layer_track_conn(rr_graph_builder, multi_layer_track_conn, x, y, conn_vector[iconn].from_wire, conn_vector[iconn].from_wire_layer, CHANY, + conn_vector[iconn].to_wire, conn_vector[iconn].to_wire_layer, CHANX, curr_switchblocks_offset); + //CHANX -> CHANY connection + set_multi_layer_track_conn(rr_graph_builder, multi_layer_track_conn, x, y, conn_vector[iconn].from_wire, conn_vector[iconn].from_wire_layer, CHANX, + conn_vector[iconn].to_wire, conn_vector[iconn].to_wire_layer, CHANY, curr_switchblocks_offset); } } } @@ -1251,17 +1295,17 @@ void alloc_and_load_inter_die_rr_node_indices(RRGraphBuilder& rr_graph_builder, const vtr::NdMatrix& extra_nodes_per_switchblock, int* index) { /* - * In case of multi-die FPGAs, we add extra nodes (can be either CHANX OR CHANY, used CHANX) to + * In case of multi-die FPGAs, we add extra nodes (could have used either CHANX or CHANY; we chose to use all CHANX) to * support inter-die communication coming from switch blocks (connection between two tracks in different layers) * The extra nodes have the following attribute: * 1) type = CHANX * 2) length = 0 (xhigh = xlow, yhigh = ylow) - * 3) ptc = [max_chanx_width:max_chanx_width+number_of_connection] + * 3) ptc = [max_chanx_width:max_chanx_width+number_of_connection-1] */ auto& device_ctx = g_vpr_ctx.device(); for (int layer = 0; layer < grid.get_num_layers(); layer++) { - /* Skip the current die if architecture file specifies that it doesn't require global resource routing */ + /* 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; } From 18b2c5c478dc0acab13ff6910727945131922487 Mon Sep 17 00:00:00 2001 From: saaramahmoudi Date: Mon, 4 Dec 2023 21:34:55 -0500 Subject: [PATCH 52/83] fixed switch id between 3D SB edges --- libs/libarchfpga/src/physical_types.h | 8 +++--- vpr/src/route/build_switchblocks.cpp | 4 ++- vpr/src/route/build_switchblocks.h | 4 ++- vpr/src/route/rr_graph2.cpp | 27 +++++++++---------- .../3d_SB_inter_die_stratixiv_arch.timing.xml | 4 +-- 5 files changed, 24 insertions(+), 23 deletions(-) diff --git a/libs/libarchfpga/src/physical_types.h b/libs/libarchfpga/src/physical_types.h index ffd1aee8ea2..6142c58f78d 100644 --- a/libs/libarchfpga/src/physical_types.h +++ b/libs/libarchfpga/src/physical_types.h @@ -177,15 +177,15 @@ enum e_side : unsigned char { LEFT = 3, NUM_2D_SIDES = 4, ABOVE = 5, - UNDER = 6, - NUM_3D_SIDES, + UNDER = 7, + NUM_3D_SIDES =6, }; constexpr std::array TOTAL_2D_SIDES = {{TOP, RIGHT, BOTTOM, LEFT}}; //Set of all side orientations constexpr std::array TOTAL_2D_SIDE_STRINGS = {{"TOP", "RIGHT", "BOTTOM", "LEFT"}}; //String versions of side orientations -constexpr std::array TOTAL_3D_SIDES = {{TOP, RIGHT, BOTTOM, LEFT, ABOVE, UNDER}}; //Set of all side orientations including different layers -constexpr std::array TOTAL_3D_SIDE_STRINGS = {{"TOP", "RIGHT", "BOTTOM", "LEFT", "ABOVE", "UNDER"}}; //String versions of side orientations including different layers +constexpr std::array TOTAL_3D_SIDES = {{TOP, RIGHT, BOTTOM, LEFT, ABOVE, UNDER}}; //Set of all side orientations including different layers +constexpr std::array TOTAL_3D_SIDE_STRINGS = {{"TOP", "RIGHT", "BOTTOM", "LEFT", "ABOVE", "UNDER"}}; //String versions of side orientations including different layers /* pin location distributions */ enum e_pin_location_distr { diff --git a/vpr/src/route/build_switchblocks.cpp b/vpr/src/route/build_switchblocks.cpp index c14eea50788..0681d8d6340 100644 --- a/vpr/src/route/build_switchblocks.cpp +++ b/vpr/src/route/build_switchblocks.cpp @@ -889,9 +889,11 @@ static void compute_wireconn_connections( sb_edge.switch_ind = wireconn_ptr->switch_override_indx; } else if (from_layer == to_layer) { sb_edge.switch_ind = to_chan_details[to_x][to_y][to_wire].arch_wire_switch(); + sb_edge.switch_ind_between_layers = -1; //the connection does not cross any layers } else { VTR_ASSERT(from_layer != to_layer); - sb_edge.switch_ind = to_chan_details[to_x][to_y][to_wire].arch_opin_between_dice_switch(); + 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_opin_between_dice_switch(); } 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/build_switchblocks.h b/vpr/src/route/build_switchblocks.h index aa7aed3cff6..8c6fa386804 100644 --- a/vpr/src/route/build_switchblocks.h +++ b/vpr/src/route/build_switchblocks.h @@ -77,7 +77,8 @@ struct t_hash_Switchblock_Lookup { * * @from_wire source wire ptc_num index in a channel * @to_wire destination wire ptc_num index in a channel - * @switch_ind RR graph switch index that connects the source wire to the destination wire + * @switch_ind RR graph switch index that connects the source wire to the destination wire that connect two tracks in same layer + * @switch_ind_between_layers RR graph switch index that connects two tracks in different layers * @from_wire_layer the layer index that the source wire is located at * @to_wire_layer the layer index that the destination wire is located at * @@ -86,6 +87,7 @@ struct t_switchblock_edge { short from_wire; short to_wire; short switch_ind; + short switch_ind_between_layers; short from_wire_layer; short to_wire_layer; }; diff --git a/vpr/src/route/rr_graph2.cpp b/vpr/src/route/rr_graph2.cpp index 8db3e824d18..6c97fed80f0 100644 --- a/vpr/src/route/rr_graph2.cpp +++ b/vpr/src/route/rr_graph2.cpp @@ -179,7 +179,7 @@ static int get_track_to_chan_seg(RRGraphBuilder& rr_graph_builder, static bool is_sb_conn_layer_crossing(enum e_side src_side, enum e_side dest_side); /** - * @brief finds crossponding RR nodes for a 3D SB edge and fill 3D custom switch block information (offset to correct extra CHANX nodes, source tracks, ..) + * @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 multi_layer_track_conn 3D custom switch block information (offset to correct extra CHANX nodes, source tracks, ..) @@ -2257,6 +2257,8 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, int to_layer = conn_vector.at(iconn).to_wire_layer; /* Get the index of the switch connecting the two wires */ int src_switch = conn_vector[iconn].switch_ind; + /* Get the index of the switch connecting the two wires in two layers */ + int src_switch_betwen_layers = conn_vector[iconn].switch_ind_between_layers; if (to_layer == layer) { //track-to-track connection within the same layer RRNodeId to_node = rr_graph_builder.node_lookup().find_node(to_layer, to_x, to_y, to_chan_type, to_wire); @@ -2279,7 +2281,7 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, } } else { //track-to_track connection crossing layer VTR_ASSERT(to_layer != layer); - //check if current connection is valid, since switchblock pattern is very general, + //check if current connection is valid, since switch block pattern is very general, //we might see invalid layer in connection, so we just skip those if ((layer < 0 || layer >= device_ctx.grid.get_num_layers()) || (to_layer < 0 || to_layer >= device_ctx.grid.get_num_layers())) { continue; @@ -2296,9 +2298,15 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, /* * In order to connect two tracks in different layers, we need to follow these three steps: - * 1) connect "from_tracks" to extra "chanx" node in the same switchblocks + * 1) connect "from_tracks" to extra "chanx" node in the same switch blocks * 2) connect extra "chanx" node located in from_layer to another extra "chanx" node located in to_layer * 3) connect "chanx" node located in to_layer to "to_track" + * + * +-------------+ +-------------+ +--------------+ +--------------+ + * | from_wire | -----> | extra_chanx | ------> | extra_chanx | ------> | to_wire | + * | (src_layer) | | (src_layer) | | (dest_layer) | | (dest_layer) | + * +-------------+ +-------------+ +--------------+ +--------------+ + * * */ int offset = multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type - CHANX)].offset_to_extra_chanx_node; RRNodeId track_to_chanx_node = rr_graph_builder.node_lookup().find_node(layer, tile_x, tile_y, CHANX, max_chan_width + offset); @@ -2320,23 +2328,12 @@ static void get_switchblocks_edges(RRGraphBuilder& rr_graph_builder, //we only add the following edge once for the first driver, otherwise we are adding the same edge multiple times if (!multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type - CHANX)].connected_to_dest) { multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type - CHANX)].connected_to_dest = true; - rr_edges_to_create.emplace_back(track_to_chanx_node, diff_layer_chanx_node, src_switch, false); + rr_edges_to_create.emplace_back(track_to_chanx_node, diff_layer_chanx_node, src_switch_betwen_layers, false); ++edge_count; rr_edges_to_create.emplace_back(diff_layer_chanx_node, chanx_to_track_node, src_switch, false); ++edge_count; } - - if (device_ctx.arch_switch_inf[src_switch].directionality() == BI_DIRECTIONAL) { - //Add reverse edge since bi-directional - rr_edges_to_create.emplace_back(track_to_chanx_node, from_rr_node, src_switch, false); - ++edge_count; - VTR_ASSERT(multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type - CHANX)].from_tracks.size() > 0); - if (multi_layer_track_conn[to_layer][to_x][to_y][to_wire][((int)to_chan_type - CHANX)].from_tracks[0] == from_wire) { - rr_edges_to_create.emplace_back(diff_layer_chanx_node, chanx_to_track_node, src_switch, false); - ++edge_count; - } - } } } } 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 415240a8a0b..d671996b6f4 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 @@ -5165,14 +5165,14 @@ --> - + 1 1 1 1 1 1 1 1 1 - +