diff --git a/libs/librrgraph/CMakeLists.txt b/libs/librrgraph/CMakeLists.txt
index 949bb02790a..0ae8db838ff 100644
--- a/libs/librrgraph/CMakeLists.txt
+++ b/libs/librrgraph/CMakeLists.txt
@@ -34,14 +34,19 @@ endif()
target_compile_definitions(librrgraph PUBLIC ${INTERCHANGE_SCHEMA_HEADERS})
# Unit tests
-#file(GLOB_RECURSE TEST_SOURCES test/*.cpp)
-#add_executable(test_rr_graph ${TEST_SOURCES})
-#target_link_libraries(test_rr_graph
-# librrgraph)
+file(GLOB_RECURSE TEST_SOURCES test/*.cpp)
+add_executable(test_rr_graph ${TEST_SOURCES})
+target_link_libraries(test_rr_graph
+ Catch2::Catch2WithMain
+ librrgraph)
# Run unit tests: comment out for now
-#add_test(NAME test_rr_graph COMMAND test_rr_graph --use-colour=yes)
+add_test(NAME test_rr_graph
+ COMMAND test_rr_graph --use-colour=yes
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/test
+ )
+#uxsdcxx generate
add_custom_target(
generate_rr_graph_serializers
COMMAND ${CMAKE_COMMAND} -E remove_directory rr_graph_generate
@@ -58,4 +63,4 @@ add_custom_target(
COMMAND ${CMAKE_COMMAND} -E copy rr_graph_generate/rr_graph_uxsdcxx.capnp ${CMAKE_CURRENT_SOURCE_DIR}/../libvtrcapnproto/gen
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/base/rr_graph.xsd
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- )
\ No newline at end of file
+ )
diff --git a/libs/librrgraph/test/main.cpp b/libs/librrgraph/test/main.cpp
new file mode 100644
index 00000000000..2a2e12d62b2
--- /dev/null
+++ b/libs/librrgraph/test/main.cpp
@@ -0,0 +1,2 @@
+#define CATCH_CONFIG_MAIN
+#include "catch2/catch_test_macros.hpp"
\ No newline at end of file
diff --git a/libs/librrgraph/test/test_arch.xml b/libs/librrgraph/test/test_arch.xml
new file mode 100644
index 00000000000..48c09f7cf5e
--- /dev/null
+++ b/libs/librrgraph/test/test_arch.xml
@@ -0,0 +1,193 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ io.outpad io.inpad io.clock
+ io.outpad io.inpad io.clock
+ io.outpad io.inpad io.clock
+ io.outpad io.inpad io.clock
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1 1
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2.253000e-10
+ 2.253000e-10
+ 2.253000e-10
+ 2.253000e-10
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libs/librrgraph/test/test_arch_base.xml b/libs/librrgraph/test/test_arch_base.xml
new file mode 100644
index 00000000000..99eb54c1c1f
--- /dev/null
+++ b/libs/librrgraph/test/test_arch_base.xml
@@ -0,0 +1,191 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ io.outpad io.inpad io.clock
+ io.outpad io.inpad io.clock
+ io.outpad io.inpad io.clock
+ io.outpad io.inpad io.clock
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1 1
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2.253000e-10
+ 2.253000e-10
+ 2.253000e-10
+ 2.253000e-10
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libs/librrgraph/test/test_rr_graph.cpp b/libs/librrgraph/test/test_rr_graph.cpp
new file mode 100644
index 00000000000..3398bc0de64
--- /dev/null
+++ b/libs/librrgraph/test/test_rr_graph.cpp
@@ -0,0 +1,783 @@
+// test framework
+#include "catch2/catch_test_macros.hpp"
+
+#include "rr_rc_data.h"
+#include "read_xml_arch_file.h"
+#include "vtr_expr_eval.h"
+#include "vpr_error.h"
+#include "get_parallel_segs.h"
+#include "alloc_and_load_rr_indexed_data.h"
+
+#include "test_utils.cpp"
+
+using vtr::FormulaParser;
+using vtr::t_formula_data;
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+DeviceGrid create_device_grid(const std::vector& grid_layouts,
+ const size_t width,
+ const size_t height,
+ const std::vector& physical_tile_types);
+
+t_chan_width init_channel(DeviceGrid grid, int chan_width_max, int x_max, int x_min, int y_max, int y_min, int info);
+
+t_rr_switch_inf create_rr_switches(t_arch_switch_inf* arch_switch_inf, int arch_switch_idx);
+
+void create_rr_nodes(RRGraphBuilder* rr_graph_builder,
+ std::vector& rr_rc_data,
+ t_rr_edge_info_set* rr_edges_to_create,
+ const std::vector& physical_tile_types,
+ const DeviceGrid& grid);
+
+void create_rr_chan(RRGraphBuilder* rr_graph_builder,
+ std::vector& rr_rc_data,
+ t_chan_width& nodes_per_chan,
+ DeviceGrid& grid);
+
+RRNodeId create_sink_src_node(RRGraphBuilder* rr_graph_builder,
+ std::vector& rr_rc_data,
+ const e_rr_type node_type,
+ const e_cost_indices node_cost,
+ const int ptc,
+ const int x_coord,
+ const int y_coord);
+
+RRNodeId create_pin_node(RRGraphBuilder* rr_graph_builder,
+ std::vector& rr_rc_data,
+ const e_rr_type node_type,
+ const e_cost_indices node_cost,
+ const e_side node_side,
+ const int ptc,
+ const int x_coord,
+ const int y_coord);
+
+RRNodeId create_chan_node(RRGraphBuilder* rr_graph_builder,
+ std::vector& rr_rc_data,
+ const e_rr_type node_type,
+ const e_cost_indices node_cost,
+ const Direction direction,
+ const int track,
+ const int x_coord,
+ const int y_coord,
+ const int x_offset,
+ const int y_offset);
+
+void create_rr_edges(RRGraphBuilder* rr_graph_builder, t_rr_edge_info_set* rr_edges_to_create);
+
+void create_rr_indexed_data(RRGraphView* rr_graph,
+ vtr::vector& rr_indexed_data,
+ const DeviceGrid& grid,
+ const std::vector& segment_inf,
+ const int wire_to_ipin_switch);
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+TEST_CASE("I/O Test_Base_10N", "[librrgraph]"){
+ static constexpr const char kArchFile[] = "test_arch_base.xml";
+ static constexpr const char kRrGraphFile1[] = "test_read_rrgraph_base.xml";
+ static constexpr const char kRrGraphFile2[] = "test_write_rrgraph_base.xml";
+
+ t_arch arch;
+ std::vector physical_tile_types;
+ std::vector logical_block_types;
+
+ XmlReadArch(kArchFile, /*timing_enabled=*/false,
+ &arch, physical_tile_types, logical_block_types);
+
+ std::vector& segment_inf = arch.Segments;
+ enum e_base_cost_type base_cost_type;
+
+ size_t num_arch_switches = arch.num_switches;
+ t_arch_switch_inf* arch_switch_inf = arch.Switches;
+ t_arch_switch_fanin arch_switch_fanins(num_arch_switches);
+ std::vector> switch_fanin_remap;
+
+ int virtual_clock_network_root_idx{};
+ int wire_to_rr_ipin_switch = -1;
+
+ std::string read_rr_graph_filename = kRrGraphFile1;
+ char echo_file_name[] = "rr_indexed_data.echo";
+
+ bool echo_enabled = 1;
+ bool read_edge_metadata = 1;
+ bool do_check_rr_graph = 0;
+
+ t_graph_type graph_type = GRAPH_UNIDIR;
+
+ vtr::vector rr_indexed_data;
+ std::vector rr_rc_data;
+
+ vtr::vector seg_index;
+
+ RRGraphBuilder rr_graph_builder {};
+ RRGraphView rr_graph {rr_graph_builder.rr_nodes(), rr_graph_builder.node_lookup(), rr_graph_builder.rr_node_metadata(), rr_graph_builder.rr_edge_metadata(), rr_indexed_data, rr_rc_data, rr_graph_builder.rr_segments(), rr_graph_builder.rr_switch()};
+
+ //Create Grid
+ DeviceGrid grid = create_device_grid(arch.grid_layouts, arch.grid_layouts[0].width, arch.grid_layouts[0].height, physical_tile_types);
+
+ //Init Chan_Width
+ t_chan_width chan_width = init_channel(grid, 2, 2, 2, 2, 2, 5);
+
+ //Create Segment
+ size_t num_segments = segment_inf.size();
+ rr_graph_builder.reserve_segments(num_segments);
+ for (size_t iseg = 0; iseg < num_segments; ++iseg) {
+ rr_graph_builder.add_rr_segment(segment_inf[iseg]);
+ }
+
+ //Create Switches
+ rr_graph_builder.reserve_switches(num_arch_switches);
+ for (size_t iswitch = 0; iswitch < num_arch_switches; ++iswitch) {
+ const t_rr_switch_inf& temp_rr_switch = create_rr_switches(arch_switch_inf, iswitch);
+ rr_graph_builder.add_rr_switch(temp_rr_switch);
+ }
+
+ //Create Nodes
+ create_sink_src_node(&rr_graph_builder, rr_rc_data, SOURCE, SOURCE_COST_INDEX, 0, 0, 1);
+ create_sink_src_node(&rr_graph_builder, rr_rc_data, SINK, SINK_COST_INDEX, 1, 0, 1);
+ create_pin_node(&rr_graph_builder, rr_rc_data, OPIN, OPIN_COST_INDEX, RIGHT, 0, 0, 1);
+ create_pin_node(&rr_graph_builder, rr_rc_data, IPIN, IPIN_COST_INDEX, RIGHT, 1, 0, 1);
+ create_sink_src_node(&rr_graph_builder, rr_rc_data, SOURCE, SOURCE_COST_INDEX, 0, 1, 0);
+ create_sink_src_node(&rr_graph_builder, rr_rc_data, SINK, SINK_COST_INDEX, 1, 1, 0);
+ create_pin_node(&rr_graph_builder, rr_rc_data, OPIN, OPIN_COST_INDEX, TOP, 0, 1, 0);
+ create_pin_node(&rr_graph_builder, rr_rc_data, IPIN, IPIN_COST_INDEX, TOP, 1, 1, 0);
+ create_chan_node(&rr_graph_builder, rr_rc_data, CHANX, CHANX_COST_INDEX_START, Direction::INC, 0, 1, 0, 0, 0);
+ create_chan_node(&rr_graph_builder, rr_rc_data, CHANX, CHANX_COST_INDEX_START, Direction::DEC, 1, 1, 0, 0, 0);
+ create_chan_node(&rr_graph_builder, rr_rc_data, CHANY, CHANX_COST_INDEX_START, Direction::INC, 0, 0, 1, 0, 0);
+ create_chan_node(&rr_graph_builder, rr_rc_data, CHANY, CHANX_COST_INDEX_START, Direction::DEC, 1, 0, 1, 0, 0);
+
+ //Create Edges
+ t_rr_edge_info_set rr_edges_to_create;
+ rr_edges_to_create.emplace_back(RRNodeId(0), RRNodeId(2), 0);
+ rr_edges_to_create.emplace_back(RRNodeId(2), RRNodeId(11), 0);
+ rr_edges_to_create.emplace_back(RRNodeId(11), RRNodeId(8), 0);
+ rr_edges_to_create.emplace_back(RRNodeId(8), RRNodeId(7), 0);
+ rr_edges_to_create.emplace_back(RRNodeId(7), RRNodeId(5), 0);
+
+ rr_edges_to_create.emplace_back(RRNodeId(4), RRNodeId(6), 0);
+ rr_edges_to_create.emplace_back(RRNodeId(6), RRNodeId(9), 0);
+ rr_edges_to_create.emplace_back(RRNodeId(9), RRNodeId(10), 0);
+ rr_edges_to_create.emplace_back(RRNodeId(10), RRNodeId(3), 0);
+ rr_edges_to_create.emplace_back(RRNodeId(3), RRNodeId(1), 0);
+
+ uniquify_edges(rr_edges_to_create);
+ create_rr_edges(&rr_graph_builder, &rr_edges_to_create);
+
+ //Create Fanin
+ rr_graph_builder.init_fan_in();
+ size_t num_rr_switches = rr_graph_builder.count_rr_switches(num_arch_switches, arch_switch_inf, arch_switch_fanins);
+ rr_graph_builder.resize_switches(num_rr_switches);
+
+ //Edge/Switch Remap
+ rr_graph_builder.remap_rr_node_switch_indices(arch_switch_fanins);
+
+ //Edge Partition
+ rr_graph_builder.partition_edges();
+
+ //Create Indexed Data
+ create_rr_indexed_data(&rr_graph, rr_indexed_data, grid, segment_inf, wire_to_rr_ipin_switch);
+
+ //Write drafted rrgraph test case
+ write_rr_graph(&rr_graph_builder,
+ &rr_graph,
+ physical_tile_types,
+ &rr_indexed_data,
+ &rr_rc_data,
+ grid,
+ arch_switch_inf,
+ &arch,
+ &chan_width,
+ num_arch_switches,
+ kRrGraphFile1,
+ virtual_clock_network_root_idx,
+ echo_enabled,
+ echo_file_name,
+ true);
+
+ //New rr_graph_builder for I/O test
+ RRGraphBuilder rr_graph_builder2 {};
+ RRGraphView rr_graph2 {rr_graph_builder2.rr_nodes(), rr_graph_builder2.node_lookup(), rr_graph_builder2.rr_node_metadata(), rr_graph_builder2.rr_edge_metadata(), rr_indexed_data, rr_rc_data, rr_graph_builder2.rr_segments(), rr_graph_builder2.rr_switch()};
+
+ //Read drafted rrgraph
+ load_rr_file(&rr_graph_builder2,
+ &rr_graph2,
+ physical_tile_types,
+ segment_inf,
+ &rr_indexed_data,
+ &rr_rc_data,
+ grid,
+ arch_switch_inf,
+ graph_type,
+ &arch,
+ &chan_width,
+ base_cost_type,
+ num_arch_switches,
+ virtual_clock_network_root_idx,
+ &wire_to_rr_ipin_switch,
+ read_rr_graph_filename.c_str(),
+ &read_rr_graph_filename,
+ read_edge_metadata,
+ do_check_rr_graph,
+ echo_enabled,
+ echo_file_name,
+ true);
+
+ //Write rrgraph
+ write_rr_graph(&rr_graph_builder,
+ &rr_graph,
+ physical_tile_types,
+ &rr_indexed_data,
+ &rr_rc_data,
+ grid,
+ arch_switch_inf,
+ &arch,
+ &chan_width,
+ num_arch_switches,
+ kRrGraphFile2,
+ virtual_clock_network_root_idx,
+ echo_enabled,
+ echo_file_name,
+ true);
+}
+
+TEST_CASE("I/O Test_mult", "[librrgraph]"){
+ static constexpr const char kArchFile[] = "test_arch.xml";
+ static constexpr const char kRrGraphFile1[] = "test_read_rrgraph.xml";
+ static constexpr const char kRrGraphFile2[] = "test_write_rrgraph.xml";
+
+ t_arch arch;
+ std::vector physical_tile_types;
+ std::vector logical_block_types;
+
+ XmlReadArch(kArchFile, /*timing_enabled=*/false,
+ &arch, physical_tile_types, logical_block_types);
+
+ std::vector& segment_inf = arch.Segments;
+ enum e_base_cost_type base_cost_type;
+
+ size_t num_arch_switches = arch.num_switches;
+ t_arch_switch_inf* arch_switch_inf = arch.Switches;
+ t_arch_switch_fanin arch_switch_fanins(num_arch_switches);
+ std::vector> switch_fanin_remap;
+
+ int virtual_clock_network_root_idx{};
+ int wire_to_rr_ipin_switch = -1;
+
+ std::string read_rr_graph_filename = kRrGraphFile1;
+ char echo_file_name[] = "rr_indexed_data.echo";
+
+ bool echo_enabled = 1;
+ bool read_edge_metadata = 1;
+ bool do_check_rr_graph = 0;
+
+ t_graph_type graph_type = GRAPH_UNIDIR;
+
+ vtr::vector rr_indexed_data;
+ std::vector rr_rc_data;
+
+ vtr::vector seg_index;
+
+ RRGraphBuilder rr_graph_builder {};
+ RRGraphView rr_graph {rr_graph_builder.rr_nodes(), rr_graph_builder.node_lookup(), rr_graph_builder.rr_node_metadata(), rr_graph_builder.rr_edge_metadata(), rr_indexed_data, rr_rc_data, rr_graph_builder.rr_segments(), rr_graph_builder.rr_switch()};
+
+ //Create Grid
+ DeviceGrid grid = create_device_grid(arch.grid_layouts, arch.grid_layouts[0].width, arch.grid_layouts[0].height, physical_tile_types);
+
+ //Init Chan_Width
+ t_chan_width chan_width = init_channel(grid, 4, 4, 4, 4, 4, 4);
+
+ //Create Segment
+ size_t num_segments = segment_inf.size();
+ rr_graph_builder.reserve_segments(num_segments);
+ for (size_t iseg = 0; iseg < num_segments; ++iseg) {
+ rr_graph_builder.add_rr_segment(segment_inf[iseg]);
+ }
+
+ //Create Switches
+ rr_graph_builder.reserve_switches(num_arch_switches);
+ // Create the switches
+ for (size_t iswitch = 0; iswitch < num_arch_switches; ++iswitch) {
+ const t_rr_switch_inf& temp_rr_switch = create_rr_switches(arch_switch_inf, iswitch);
+ rr_graph_builder.add_rr_switch(temp_rr_switch);
+ }
+
+ //Create Nodes (SOURCE/SINK/IPIN/OPIN)
+ t_rr_edge_info_set rr_edges_to_create;
+ create_rr_nodes(&rr_graph_builder, rr_rc_data, &rr_edges_to_create, physical_tile_types, grid);
+
+ //Create Chan Nodes
+ create_rr_chan(&rr_graph_builder, rr_rc_data, chan_width, grid);
+
+ /*TODO: add edges to rr_edges_to_create for linking of opin_to_track, track_to_track, ipin_to_track.
+ May Need to modify create_rr_nodes and create_rr_chan.*/
+
+ //Create Edges
+ uniquify_edges(rr_edges_to_create);
+ create_rr_edges(&rr_graph_builder, &rr_edges_to_create);
+
+ //Create Fan_in
+ rr_graph_builder.init_fan_in();
+ size_t num_rr_switches = rr_graph_builder.count_rr_switches(num_arch_switches, arch_switch_inf, arch_switch_fanins);
+ rr_graph_builder.resize_switches(num_rr_switches);
+
+ //Edge/Switch Remap
+ rr_graph_builder.remap_rr_node_switch_indices(arch_switch_fanins);
+
+ //Edge Partition
+ rr_graph_builder.partition_edges();
+
+ //Create Indexed Data
+ create_rr_indexed_data(&rr_graph, rr_indexed_data, grid, segment_inf, wire_to_rr_ipin_switch);
+
+ //Write drafted rrgraph test case
+ write_rr_graph(&rr_graph_builder,
+ &rr_graph,
+ physical_tile_types,
+ &rr_indexed_data,
+ &rr_rc_data,
+ grid,
+ arch_switch_inf,
+ &arch,
+ &chan_width,
+ num_arch_switches,
+ kRrGraphFile1,
+ virtual_clock_network_root_idx,
+ echo_enabled,
+ echo_file_name,
+ true);
+
+ //New rr_graph_builder for I/O test
+ RRGraphBuilder rr_graph_builder2 {};
+ RRGraphView rr_graph2 {rr_graph_builder2.rr_nodes(), rr_graph_builder2.node_lookup(), rr_graph_builder2.rr_node_metadata(), rr_graph_builder2.rr_edge_metadata(), rr_indexed_data, rr_rc_data, rr_graph_builder2.rr_segments(), rr_graph_builder2.rr_switch()};
+
+ //Read drafted rrgraph
+ load_rr_file(&rr_graph_builder2,
+ &rr_graph2,
+ physical_tile_types,
+ segment_inf,
+ &rr_indexed_data,
+ &rr_rc_data,
+ grid,
+ arch_switch_inf,
+ graph_type,
+ &arch,
+ &chan_width,
+ base_cost_type,
+ num_arch_switches,
+ virtual_clock_network_root_idx,
+ &wire_to_rr_ipin_switch,
+ read_rr_graph_filename.c_str(),
+ &read_rr_graph_filename,
+ read_edge_metadata,
+ do_check_rr_graph,
+ echo_enabled,
+ echo_file_name,
+ true);
+
+ //Write rrgraph
+ write_rr_graph(&rr_graph_builder,
+ &rr_graph,
+ physical_tile_types,
+ &rr_indexed_data,
+ &rr_rc_data,
+ grid,
+ arch_switch_inf,
+ &arch,
+ &chan_width,
+ num_arch_switches,
+ kRrGraphFile2,
+ virtual_clock_network_root_idx,
+ echo_enabled,
+ echo_file_name,
+ true);
+}
+////////////////////////////////////////////////////////////////////////////////////////////////////
+DeviceGrid create_device_grid(const std::vector& grid_layouts,
+ const size_t width,
+ const size_t height,
+ const std::vector& physical_tile_types){
+
+ FormulaParser p;
+ auto grid = vtr::Matrix({width, height});
+ auto grid_priorities = vtr::Matrix({width, height}, std::numeric_limits::lowest());
+ const auto& grid_def = grid_layouts[0];
+
+ //Initialize all blocks in device to empty blocks
+ t_physical_tile_type type_ = get_empty_physical_type();
+ t_physical_tile_type_ptr empty_type = &type_;
+ VTR_ASSERT(empty_type != nullptr);
+
+ for (size_t x = 0; x < width; ++x) {
+ for (size_t y = 0; y < height; ++y) {
+ set_grid_block_type(std::numeric_limits::lowest() + 1, //+1 so it overrides without warning
+ empty_type, x, y, grid, grid_priorities, /*meta=*/nullptr);
+ }
+ }
+
+ //Fill in non-empty blocks
+ for (const auto& grid_loc_def : grid_def.loc_defs) {
+ for (const auto& tile_type : physical_tile_types) {
+ if (tile_type.name == grid_loc_def.block_type) {
+ auto type = &tile_type;
+ t_formula_data vars;
+ vars.set_var_value("W", width);
+ vars.set_var_value("H", height);
+ vars.set_var_value("w", type->width);
+ vars.set_var_value("h", type->height);
+
+ //Load the x specification
+ auto& xspec = grid_loc_def.x;
+
+ size_t startx = p.parse_formula(xspec.start_expr, vars);
+ size_t endx = p.parse_formula(xspec.end_expr, vars);
+ size_t incrx = p.parse_formula(xspec.incr_expr, vars);
+ size_t repeatx = p.parse_formula(xspec.repeat_expr, vars);
+
+ //Load the y specification
+ auto& yspec = grid_loc_def.y;
+ size_t starty = p.parse_formula(yspec.start_expr, vars);
+ size_t endy = p.parse_formula(yspec.end_expr, vars);
+ size_t incry = p.parse_formula(yspec.incr_expr, vars);
+ size_t repeaty = p.parse_formula(yspec.repeat_expr, vars);
+
+ size_t x_end = 0;
+ for (size_t kx = 0; x_end < width; ++kx) { //Repeat in x direction
+ size_t x_start = startx + kx * repeatx;
+ x_end = endx + kx * repeatx;
+
+ size_t y_end = 0;
+ for (size_t ky = 0; y_end < height; ++ky) { //Repeat in y direction
+ size_t y_start = starty + ky * repeaty;
+ y_end = endy + ky * repeaty;
+
+ size_t x_max = std::min(x_end, width - 1);
+ size_t y_max = std::min(y_end, height - 1);
+
+ //Fill in the region
+ for (size_t x = x_start; x + (type->width - 1) <= x_max; x += incrx) {
+ for (size_t y = y_start; y + (type->height - 1) <= y_max; y += incry) {
+ set_grid_block_type(grid_loc_def.priority, type, x, y, grid, grid_priorities, grid_loc_def.meta);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return DeviceGrid(grid_def.name, grid);
+}
+
+t_chan_width init_channel(DeviceGrid grid, int chan_width_max, int x_max, int x_min, int y_max, int y_min, int info){
+ t_chan_width chan_width;
+
+ chan_width.max = chan_width_max;
+ chan_width.max = x_min;
+ chan_width.x_min = x_min;
+ chan_width.y_min = y_min;
+ chan_width.x_max = x_max;
+ chan_width.y_max = y_max;
+ chan_width.x_list.resize(grid.height());
+ chan_width.y_list.resize(grid.width());
+
+ for(size_t x=0; x< chan_width.x_list.size(); ++x){
+ chan_width.x_list[x] = info;
+ }
+ for(size_t y=0; y< chan_width.y_list.size(); ++y){
+ chan_width.y_list[y] = info;
+ }
+
+ return chan_width;
+}
+
+t_rr_switch_inf create_rr_switches(t_arch_switch_inf* arch_switch_inf, int arch_switch_idx){
+ t_rr_switch_inf rr_switch_inf;
+
+ /* figure out, by looking at the arch switch's Tdel map, what the delay of the new
+ * rr switch should be */
+ double rr_switch_Tdel = arch_switch_inf[arch_switch_idx].Tdel(0);
+
+ /* copy over the arch switch to rr_switch_inf[rr_switch_idx], but with the changed Tdel value */
+ rr_switch_inf.set_type(arch_switch_inf[arch_switch_idx].type());
+ rr_switch_inf.R = arch_switch_inf[arch_switch_idx].R;
+ rr_switch_inf.Cin = arch_switch_inf[arch_switch_idx].Cin;
+ rr_switch_inf.Cinternal = arch_switch_inf[arch_switch_idx].Cinternal;
+ rr_switch_inf.Cout = arch_switch_inf[arch_switch_idx].Cout;
+ rr_switch_inf.Tdel = rr_switch_Tdel;
+ rr_switch_inf.mux_trans_size = arch_switch_inf[arch_switch_idx].mux_trans_size;
+
+ rr_switch_inf.buf_size = arch_switch_inf[arch_switch_idx].buf_size;
+
+ rr_switch_inf.name = arch_switch_inf[arch_switch_idx].name;
+ rr_switch_inf.power_buffer_type = arch_switch_inf[arch_switch_idx].power_buffer_type;
+ rr_switch_inf.power_buffer_size = arch_switch_inf[arch_switch_idx].power_buffer_size;
+
+ return rr_switch_inf;
+}
+
+RRNodeId create_sink_src_node(RRGraphBuilder* rr_graph_builder,
+ std::vector& rr_rc_data,
+ const e_rr_type node_type,
+ const e_cost_indices node_cost,
+ const int ptc,
+ const int x_coord,
+ const int y_coord){
+
+ rr_graph_builder->emplace_back();
+ auto node_id = RRNodeId(rr_graph_builder->rr_nodes().size() - 1);
+
+ rr_graph_builder->set_node_cost_index(node_id, RRIndexedDataId(node_cost));
+ rr_graph_builder->set_node_type(node_id, node_type);
+ rr_graph_builder->set_node_capacity(node_id, 1);
+ rr_graph_builder->set_node_coordinates(node_id, x_coord, y_coord, x_coord, y_coord);
+ rr_graph_builder->set_node_rc_index(node_id, NodeRCIndex(find_create_rr_rc_data(0.,0.,rr_rc_data)));
+ rr_graph_builder->set_node_class_num(node_id, ptc);
+
+ rr_graph_builder->node_lookup().add_node(node_id, x_coord, y_coord, node_type, ptc);
+
+ VTR_ASSERT(rr_graph_builder->node_lookup().find_node(x_coord, y_coord, node_type, ptc));
+
+ return node_id;
+}
+
+RRNodeId create_pin_node(RRGraphBuilder* rr_graph_builder,
+ std::vector& rr_rc_data,
+ const e_rr_type node_type,
+ const e_cost_indices node_cost,
+ const e_side node_side,
+ const int ptc,
+ const int x_coord,
+ const int y_coord){
+
+ rr_graph_builder->emplace_back();
+ auto node_id = RRNodeId(rr_graph_builder->rr_nodes().size() - 1);
+
+ rr_graph_builder->set_node_cost_index(node_id, RRIndexedDataId(node_cost));
+ rr_graph_builder->set_node_type(node_id, node_type);
+ rr_graph_builder->set_node_capacity(node_id, 1);
+ rr_graph_builder->set_node_coordinates(node_id, x_coord, y_coord, x_coord, y_coord);
+ rr_graph_builder->set_node_rc_index(node_id, NodeRCIndex(find_create_rr_rc_data(0.,0.,rr_rc_data)));
+
+ rr_graph_builder->set_node_pin_num(node_id, ptc);
+ rr_graph_builder->add_node_side(node_id, node_side);
+
+ rr_graph_builder->node_lookup().add_node(node_id, x_coord, y_coord, node_type, ptc, node_side);
+
+ VTR_ASSERT(rr_graph_builder->node_lookup().find_node(x_coord, y_coord, node_type, ptc, node_side));
+
+ return node_id;
+}
+
+RRNodeId create_chan_node(RRGraphBuilder* rr_graph_builder,
+ std::vector& rr_rc_data,
+ const e_rr_type node_type,
+ const e_cost_indices node_cost,
+ const Direction direction,
+ const int track,
+ const int x_coord,
+ const int y_coord,
+ const int x_offset,
+ const int y_offset){
+
+ rr_graph_builder->emplace_back();
+ auto node_id = RRNodeId(rr_graph_builder->rr_nodes().size() - 1);
+
+ if (node_type == CHANX) {
+ rr_graph_builder->set_node_cost_index(node_id, RRIndexedDataId(node_cost));
+ rr_graph_builder->set_node_capacity(node_id, 1);
+ rr_graph_builder->set_node_coordinates(node_id, x_coord, y_coord, x_coord + x_offset, y_coord);
+ } else {
+ VTR_ASSERT(node_type == CHANY);
+ rr_graph_builder->set_node_cost_index(node_id, RRIndexedDataId(node_cost+1));
+ rr_graph_builder->set_node_capacity(node_id, 1);
+ rr_graph_builder->set_node_coordinates(node_id, x_coord, y_coord, x_coord, y_coord + y_offset);
+ }
+
+ rr_graph_builder->set_node_rc_index(node_id, NodeRCIndex(find_create_rr_rc_data(0.,0.,rr_rc_data)));
+
+ rr_graph_builder->set_node_type(node_id, node_type);
+ rr_graph_builder->set_node_track_num(node_id, track);
+ rr_graph_builder->set_node_direction(node_id, direction);
+
+ rr_graph_builder->node_lookup().add_node(node_id, x_coord, y_coord, node_type, track);
+
+ if (node_type == CHANX)
+ VTR_ASSERT(rr_graph_builder->node_lookup().find_node(y_coord, x_coord, node_type, track));
+ else
+ VTR_ASSERT(rr_graph_builder->node_lookup().find_node(x_coord, y_coord, node_type, track));
+
+ return node_id;
+}
+
+void create_rr_nodes(RRGraphBuilder* rr_graph_builder,
+ std::vector& rr_rc_data,
+ t_rr_edge_info_set* rr_edges_to_create,
+ const std::vector& physical_tile_types,
+ const DeviceGrid& grid){
+
+ for(size_t x=0; xname == tile_type.name){
+ e_side side;
+ if(x == 0){
+ side = RIGHT;
+ } else if(x == grid.height()-1){
+ side = LEFT;
+ } else if(y == 0){
+ side = TOP;
+ } else {
+ side = BOTTOM;
+ }
+
+ if(tile_type.name != std::string("EMPTY")){
+ std::vector> pin_list;
+ RRNodeId inode = RRNodeId::INVALID();
+ rr_graph_builder->node_lookup().reserve_nodes(x,y,SINK,2*tile_type.capacity);
+ rr_graph_builder->node_lookup().reserve_nodes(x,y,SOURCE,tile_type.num_output_pins);
+
+ for(int i=0; i>::size_type ptc = 0; ptc(pin_list[ptc]);
+ if(node_type == SINK){
+ dir_ipin[ptc%4]++;
+ } else if(node_type == SOURCE){
+ dir_opin[ptc%4]++;
+ }
+ }
+ for(int i=0; inode_lookup().reserve_nodes(x, y, IPIN, dir_ipin[i], SIDES[i]);
+ rr_graph_builder->node_lookup().reserve_nodes(x, y, OPIN, dir_ipin[i], SIDES[i]);
+ }
+ } else if(tile_type.name == std::string("io")){
+ rr_graph_builder->node_lookup().reserve_nodes(x,y,IPIN,tile_type.num_input_pins+tile_type.num_clock_pins, side);
+ rr_graph_builder->node_lookup().reserve_nodes(x,y,OPIN,tile_type.num_output_pins, side);
+ }
+
+ for(std::vector>::size_type ptc = 0; ptc(pin_list[ptc]);
+ auto& node_id = std::get<1>(pin_list[ptc]);
+ if(node_type == SINK){
+ rr_edges_to_create->emplace_back(create_pin_node(rr_graph_builder, rr_rc_data, IPIN, IPIN_COST_INDEX, (tile_type.name == std::string("io") ? side : SIDES[ptc%4]), ptc, x, y), node_id, 0);
+ } else if(node_type == SOURCE)
+ rr_edges_to_create->emplace_back(node_id, create_pin_node(rr_graph_builder, rr_rc_data, OPIN, OPIN_COST_INDEX, (tile_type.name == std::string("io") ? side : SIDES[ptc%4]), ptc, x, y), 0);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void create_rr_chan(RRGraphBuilder* rr_graph_builder,
+ std::vector& rr_rc_data,
+ t_chan_width& nodes_per_chan,
+ DeviceGrid& grid){
+
+ for(size_t x=0; xnode_lookup().reserve_nodes(x, y, CHANX, nodes_per_chan.x_max);
+ for(int track=0;tracknode_lookup().reserve_nodes(x, y, CHANY, nodes_per_chan.y_max);
+ for(int track=0;trackalloc_and_load_edges(rr_edges_to_create);
+}
+
+void create_rr_indexed_data(RRGraphView* rr_graph,
+ vtr::vector& rr_indexed_data,
+ const DeviceGrid& grid,
+ const std::vector& segment_inf,
+ const int wire_to_ipin_switch
+ ){
+ int i, length, index;
+
+ t_unified_to_parallel_seg_index segment_index_map;
+ std::vector segment_inf_x = get_parallel_segs(segment_inf, segment_index_map, X_AXIS);
+ std::vector segment_inf_y = get_parallel_segs(segment_inf, segment_index_map, Y_AXIS);\
+ int total_num_segment = segment_inf_x.size() + segment_inf_y.size();
+
+ int num_rr_indexed_data = CHANX_COST_INDEX_START + total_num_segment;
+ rr_indexed_data.resize(num_rr_indexed_data);
+
+ constexpr float nan = std::numeric_limits::quiet_NaN();
+ for (i = SOURCE_COST_INDEX; i <= IPIN_COST_INDEX; i++) {
+ rr_indexed_data[RRIndexedDataId(i)].ortho_cost_index = OPEN;
+ rr_indexed_data[RRIndexedDataId(i)].seg_index = OPEN;
+ rr_indexed_data[RRIndexedDataId(i)].inv_length = nan;
+ rr_indexed_data[RRIndexedDataId(i)].T_linear = 0.;
+ rr_indexed_data[RRIndexedDataId(i)].T_quadratic = 0.;
+ rr_indexed_data[RRIndexedDataId(i)].C_load = 0.;
+ }
+ rr_indexed_data[RRIndexedDataId(IPIN_COST_INDEX)].T_linear = rr_graph->rr_switch_inf(RRSwitchId(wire_to_ipin_switch)).Tdel;
+
+ std::vector ortho_costs;
+ ortho_costs = find_ortho_cost_index(*rr_graph, segment_inf_x, segment_inf_y, X_AXIS);
+
+ /* X-directed segments*/
+ for (size_t iseg = 0; iseg < segment_inf_x.size(); ++iseg) {
+ index = iseg + CHANX_COST_INDEX_START;
+ rr_indexed_data[RRIndexedDataId(index)].ortho_cost_index = ortho_costs[iseg];
+
+ if (segment_inf_x[iseg].longline)
+ length = grid.width();
+ else
+ length = std::min(segment_inf_x[iseg].length, grid.width());
+
+ rr_indexed_data[RRIndexedDataId(index)].inv_length = 1. / length;
+ /*We use the index for the segment in the **unified** seg_inf vector not iseg which is relative
+ * to parallel axis segments vector */
+ rr_indexed_data[RRIndexedDataId(index)].seg_index = segment_inf_x[iseg].seg_index;
+
+ rr_indexed_data[RRIndexedDataId(index)].T_linear = 0.;
+ rr_indexed_data[RRIndexedDataId(index)].T_quadratic = 0.;
+ rr_indexed_data[RRIndexedDataId(index)].C_load = 0.;
+ }
+
+ /* Y-directed segments*/
+ for (size_t iseg = segment_inf_x.size(); iseg < ortho_costs.size(); ++iseg) {
+ index = iseg + CHANX_COST_INDEX_START;
+ rr_indexed_data[RRIndexedDataId(index)].ortho_cost_index = ortho_costs[iseg];
+
+ if (segment_inf_x[iseg - segment_inf_x.size()].longline)
+ length = grid.width();
+ else
+ length = std::min(segment_inf_y[iseg - segment_inf_x.size()].length, grid.width());
+
+ rr_indexed_data[RRIndexedDataId(index)].inv_length = 1. / length;
+ /*We use the index for the segment in the **unified** seg_inf vector not iseg which is relative
+ * to parallel axis segments vector */
+ rr_indexed_data[RRIndexedDataId(index)].seg_index = segment_inf_y[iseg - segment_inf_x.size()].seg_index;
+
+ rr_indexed_data[RRIndexedDataId(index)].T_linear = 0.;
+ rr_indexed_data[RRIndexedDataId(index)].T_quadratic = 0.;
+ rr_indexed_data[RRIndexedDataId(index)].C_load = 0.;
+ }
+}
diff --git a/libs/librrgraph/test/test_utils.cpp b/libs/librrgraph/test/test_utils.cpp
new file mode 100644
index 00000000000..05eedc844c7
--- /dev/null
+++ b/libs/librrgraph/test/test_utils.cpp
@@ -0,0 +1,235 @@
+#include "vpr_error.h"
+#include "rr_graph_reader.h"
+#include "rr_graph_writer.h"
+#include "arch_util.h"
+#include
+
+struct t_seg_details {
+ int length = 0;
+ int start = 0;
+ bool longline = 0;
+ std::unique_ptr sb;
+ std::unique_ptr cb;
+ short arch_wire_switch = 0;
+ short arch_opin_switch = 0;
+ float Rmetal = 0;
+ float Cmetal = 0;
+ bool twisted = 0;
+ enum Direction direction = Direction::NONE;
+ int group_start = 0;
+ int group_size = 0;
+ int seg_start = 0;
+ int seg_end = 0;
+ int index = 0;
+ int abs_index = 0;
+ float Cmetal_per_m = 0; ///length)
+ , seg_detail_(init_seg_details) {}
+
+ public:
+ int length() const { return length_; }
+ int seg_start() const { return seg_start_; }
+ int seg_end() const { return seg_end_; }
+
+ int start() const { return seg_detail_->start; }
+ bool longline() const { return seg_detail_->longline; }
+
+ int group_start() const { return seg_detail_->group_start; }
+ int group_size() const { return seg_detail_->group_size; }
+
+ bool cb(int pos) const { return seg_detail_->cb[pos]; }
+ bool sb(int pos) const { return seg_detail_->sb[pos]; }
+
+ float Rmetal() const { return seg_detail_->Rmetal; }
+ float Cmetal() const { return seg_detail_->Cmetal; }
+ float Cmetal_per_m() const { return seg_detail_->Cmetal_per_m; }
+
+ short arch_wire_switch() const { return seg_detail_->arch_wire_switch; }
+ short arch_opin_switch() const { return seg_detail_->arch_opin_switch; }
+
+ Direction direction() const { return seg_detail_->direction; }
+
+ int index() const { return seg_detail_->index; }
+ int abs_index() const { return seg_detail_->abs_index; }
+
+ const vtr::string_view type_name() const {
+ return vtr::string_view(
+ seg_detail_->type_name.data(),
+ seg_detail_->type_name.size());
+ }
+
+ public: //Modifiers
+ void set_length(int new_len) { length_ = new_len; }
+ void set_seg_start(int new_start) { seg_start_ = new_start; }
+ void set_seg_end(int new_end) { seg_end_ = new_end; }
+
+ private:
+ //The only unique information about a channel segment is it's start/end
+ //and length. All other information is shared accross segment types,
+ //so we use a flyweight to the t_seg_details which defines that info.
+ //
+ //To preserve the illusion of uniqueness we wrap all t_seg_details members
+ //so it appears transparent -- client code of this class doesn't need to
+ //know about t_seg_details.
+ int length_ = -1;
+ int seg_start_ = -1;
+ int seg_end_ = -1;
+ const t_seg_details* seg_detail_ = nullptr;
+};
+
+typedef vtr::NdMatrix t_chan_details;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+static void uniquify_edges(t_rr_edge_info_set& rr_edges_to_create);
+
+static void set_grid_block_type(int priority,
+ const t_physical_tile_type* type,
+ size_t x_root, size_t y_root,
+ vtr::Matrix& grid,
+ vtr::Matrix& grid_priorities,
+ const t_metadata_dict* meta);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static void uniquify_edges(t_rr_edge_info_set& rr_edges_to_create) {
+ std::sort(rr_edges_to_create.begin(), rr_edges_to_create.end());
+ rr_edges_to_create.erase(std::unique(rr_edges_to_create.begin(), rr_edges_to_create.end()), rr_edges_to_create.end());
+}
+
+static void set_grid_block_type(int priority, const t_physical_tile_type* type, size_t x_root, size_t y_root, vtr::Matrix& grid, vtr::Matrix& grid_priorities, const t_metadata_dict* meta) {
+ t_physical_tile_type empty_type = get_empty_physical_type();
+ t_physical_tile_type_ptr EMPTY_PHYSICAL_TILE_TYPE = &empty_type;
+
+ struct TypeLocation {
+ TypeLocation(size_t x_val, size_t y_val, const t_physical_tile_type* type_val, int priority_val)
+ : x(x_val)
+ , y(y_val)
+ , type(type_val)
+ , priority(priority_val) {}
+ size_t x;
+ size_t y;
+ const t_physical_tile_type* type;
+ int priority;
+
+ bool operator<(const TypeLocation& rhs) const {
+ return x < rhs.x || y < rhs.y || type < rhs.type;
+ }
+ };
+
+ //Collect locations effected by this block
+ std::set target_locations;
+ for (size_t x = x_root; x < x_root + type->width; ++x) {
+ for (size_t y = y_root; y < y_root + type->height; ++y) {
+ target_locations.insert(TypeLocation(x, y, grid[x][y].type, grid_priorities[x][y]));
+ }
+ }
+
+ //Record the highest priority of all effected locations
+ auto iter = target_locations.begin();
+ TypeLocation max_priority_type_loc = *iter;
+ for (; iter != target_locations.end(); ++iter) {
+ if (iter->priority > max_priority_type_loc.priority) {
+ max_priority_type_loc = *iter;
+ }
+ }
+
+ if (priority < max_priority_type_loc.priority) {
+ //Lower priority, do not override
+#ifdef VERBOSE
+ VTR_LOG("Not creating block '%s' at (%zu,%zu) since overlaps block '%s' at (%zu,%zu) with higher priority (%d > %d)\n",
+ type->name, x_root, y_root, max_priority_type_loc.type->name, max_priority_type_loc.x, max_priority_type_loc.y,
+ max_priority_type_loc.priority, priority);
+#endif
+ return;
+ }
+
+ if (priority == max_priority_type_loc.priority) {
+ //Ambiguous case where current grid block and new specification have equal priority
+ //
+ //We arbitrarily decide to take the 'last applied' wins approach, and warn the user
+ //about the potential ambiguity
+ VTR_LOG_WARN(
+ "Ambiguous block type specification at grid location (%zu,%zu)."
+ " Existing block type '%s' at (%zu,%zu) has the same priority (%d) as new overlapping type '%s'."
+ " The last specification will apply.\n",
+ x_root, y_root,
+ max_priority_type_loc.type->name, max_priority_type_loc.x, max_priority_type_loc.y,
+ priority, type->name);
+ }
+
+ //Mark all the grid tiles 'covered' by this block with the appropriate type
+ //and width/height offsets
+ std::set root_blocks_to_rip_up;
+
+ for (size_t x = x_root; x < x_root + type->width; ++x) {
+ VTR_ASSERT(x < grid.end_index(0));
+
+ size_t x_offset = x - x_root;
+ for (size_t y = y_root; y < y_root + type->height; ++y) {
+ VTR_ASSERT(y < grid.end_index(1));
+ size_t y_offset = y - y_root;
+
+ auto& grid_tile = grid[x][y];
+ VTR_ASSERT(grid_priorities[x][y] <= priority);
+
+ if (grid_tile.type != nullptr
+ && grid_tile.type != EMPTY_PHYSICAL_TILE_TYPE) {
+ //We are overriding a non-empty block, we need to be careful
+ //to ensure we remove any blocks which will be invalidated when we
+ //overwrite part of their locations
+
+ size_t orig_root_x = x - grid[x][y].width_offset;
+ size_t orig_root_y = y - grid[x][y].height_offset;
+
+ root_blocks_to_rip_up.insert(TypeLocation(orig_root_x, orig_root_y, grid[x][y].type, grid_priorities[x][y]));
+ }
+
+ grid[x][y].type = type;
+ grid[x][y].width_offset = x_offset;
+ grid[x][y].height_offset = y_offset;
+ grid[x][y].meta = meta;
+
+ grid_priorities[x][y] = priority;
+ }
+ }
+
+ //Rip-up any invalidated blocks
+ for (auto invalidated_root : root_blocks_to_rip_up) {
+ //Mark all the grid locations used by this root block as empty
+ for (size_t x = invalidated_root.x; x < invalidated_root.x + invalidated_root.type->width; ++x) {
+ int x_offset = x - invalidated_root.x;
+ for (size_t y = invalidated_root.y; y < invalidated_root.y + invalidated_root.type->height; ++y) {
+ int y_offset = y - invalidated_root.y;
+
+ if (grid[x][y].type == invalidated_root.type
+ && grid[x][y].width_offset == x_offset
+ && grid[x][y].height_offset == y_offset) {
+ //This is a left-over invalidated block, mark as empty
+ // Note: that we explicitly check the type and offsets, since the original block
+ // may have been completely overwritten, and we don't want to change anything
+ // in that case
+ VTR_ASSERT(EMPTY_PHYSICAL_TILE_TYPE->width == 1);
+ VTR_ASSERT(EMPTY_PHYSICAL_TILE_TYPE->height == 1);
+
+#ifdef VERBOSE
+ VTR_LOG("Ripping up block '%s' at (%d,%d) offset (%d,%d). Overlapped by '%s' at (%d,%d)\n",
+ invalidated_root.type->name, invalidated_root.x, invalidated_root.y,
+ x_offset, y_offset,
+ type->name, x_root, y_root);
+#endif
+
+ grid[x][y].type = EMPTY_PHYSICAL_TILE_TYPE;
+ grid[x][y].width_offset = 0;
+ grid[x][y].height_offset = 0;
+
+ grid_priorities[x][y] = std::numeric_limits::lowest();
+ }
+ }
+ }
+ }
+}
\ No newline at end of file