diff --git a/include/fiction/algorithms/physical_design/post_layout_optimization.hpp b/include/fiction/algorithms/physical_design/post_layout_optimization.hpp index b1f52f6b3..027186cf9 100644 --- a/include/fiction/algorithms/physical_design/post_layout_optimization.hpp +++ b/include/fiction/algorithms/physical_design/post_layout_optimization.hpp @@ -279,22 +279,22 @@ template if (fanins_set.find(fanin) == fanins_set.cend()) { - // Add fanin to the respective route + // add fanin to the respective route add_fanin_to_route(op, fanins_set.empty(), ffd); add_fanin_to_route(fanin, fanins_set.empty(), ffd); - // Continue until gate or primary input (PI) is found + // continue until gate or primary input (PI) is found while (lyt.is_wire_tile(fanin) && lyt.fanout_size(lyt.get_node(fanin)) == 1 && !lyt.is_pi_tile(fanin)) { ffd.to_clear.push_back(fanin); fanin = lyt.incoming_data_flow(fanin).front(); - // Add fanin to the respective route + // add fanin to the respective route add_fanin_to_route(fanin, fanins_set.empty(), ffd); } - // Set the respective fanin based on the route + // set the respective fanin based on the route if (fanins_set.empty()) { fanin1 = fanin; @@ -316,22 +316,22 @@ template if (fanouts_set.find(fanout) == fanouts_set.cend()) { - // Add fanout to the respective route + // add fanout to the respective route add_fanout_to_route(op, fanouts_set.empty(), ffd); add_fanout_to_route(fanout, fanouts_set.empty(), ffd); - // Continue until gate or primary output (PO) is found + // continue until gate or primary output (PO) is found while (lyt.is_wire_tile(fanout) && lyt.fanout_size(lyt.get_node(fanout)) != 0 && lyt.fanout_size(lyt.get_node(fanout)) != 2) { ffd.to_clear.push_back(fanout); fanout = lyt.outgoing_data_flow(fanout).front(); - // Add fanout to the respective route + // add fanout to the respective route add_fanout_to_route(fanout, fanouts_set.empty(), ffd); } - // Set the respective fanout based on the route + // set the respective fanout based on the route if (fanouts_set.empty()) { fanout1 = fanout; @@ -387,7 +387,7 @@ layout_coordinate_path get_path_and_obstruct(Lyt& lyt, const tile& sta layout_coordinate_path path = a_star>(lyt, {start, end}, dist(), cost(), params); - // Obstruct the tiles along the computed path. + // obstruct the tiles along the computed path. for (const auto& tile : path) { lyt.obstruct_coordinate(tile); @@ -514,7 +514,7 @@ bool improve_gate_location(Lyt& lyt, const tile& old_pos, const tile& { const uint64_t y = k - x; - if (moved_gate || (num_gate_relocations >= max_gate_relocations)) + if (moved_gate || ((num_gate_relocations >= max_gate_relocations) && !lyt.is_po_tile(current_pos))) { break; } @@ -523,7 +523,7 @@ bool improve_gate_location(Lyt& lyt, const tile& old_pos, const tile& if (lyt.y() >= y && y >= min_y && lyt.x() >= x && x >= min_x && ((x + y) <= max_diagonal) && (((x + y) < max_diagonal) || (y <= max_y)) && ((!lyt.is_pi_tile(current_pos)) || (lyt.is_pi_tile(current_pos) && (x == 0 || y == 0))) && - !(lyt.is_po_tile(current_pos) && (((x <= max_non_po.x) && (y <= max_non_po.y)) || + !(lyt.is_po_tile(current_pos) && (((x < max_non_po.x) && (y < max_non_po.y)) || ((x + y) == static_cast(old_pos.x + old_pos.y))))) { new_pos = tile{x, y}; @@ -540,7 +540,7 @@ bool improve_gate_location(Lyt& lyt, const tile& old_pos, const tile& // get paths for fanins and fanouts layout_coordinate_path new_path_from_fanin_1_to_gate, new_path_from_fanin_2_to_gate, new_path_from_gate_to_fanout_1, new_path_from_gate_to_fanout_2; - // Get paths for fanins and fanouts + // get paths for fanins and fanouts if (!fanins.empty()) { new_path_from_fanin_1_to_gate = get_path_and_obstruct(lyt, fanins[0], new_pos); @@ -636,7 +636,7 @@ bool improve_gate_location(Lyt& lyt, const tile& old_pos, const tile& } } - if (moved_gate || (num_gate_relocations >= max_gate_relocations)) + if (moved_gate || ((num_gate_relocations >= max_gate_relocations) && !lyt.is_po_tile(current_pos))) { break; } @@ -763,6 +763,97 @@ void optimize_output_positions(Lyt& lyt) noexcept } } } + // calculate bounding box + auto bounding_box = bounding_box_2d(lyt); + lyt.resize({bounding_box.get_max().x, bounding_box.get_max().y, lyt.z()}); + + // check for misplaced POs in second last row and move them one row down + for (uint64_t x = 0; x < lyt.x(); ++x) + { + if (lyt.is_po_tile({x, lyt.y() - 1, 0})) + { + // get fanin signal of the PO + std::vector> signals{}; + signals.reserve(lyt.fanin_size(lyt.get_node({x, lyt.y()}))); + lyt.foreach_fanin(lyt.get_node({x, lyt.y() - 1}), + [&signals](const auto& fanin) { signals.push_back(fanin); }); + + // move PO one row down + lyt.move_node(lyt.get_node({x, lyt.y() - 1}), {x, lyt.y(), 0}, {}); + + // create a wire segment at the previous location of the PO and connect it with its fanin + lyt.create_buf(signals[0], {x, lyt.y() - 1}); + + // connect the PO with the new wire segment + lyt.move_node(lyt.get_node({x, lyt.y()}), {x, lyt.y(), 0}, + {lyt.make_signal(lyt.get_node({x, lyt.y() - 1}))}); + } + } + + // check for misplaced POs in second last column and move them one column to the right + for (uint64_t y = 0; y < lyt.y(); ++y) + { + if (lyt.is_po_tile({lyt.x() - 1, y, 0})) + { + // get fanin signal of the PO + std::vector> signals{}; + signals.reserve(lyt.fanin_size(lyt.get_node({lyt.x(), y}))); + lyt.foreach_fanin(lyt.get_node({lyt.x() - 1, y}), + [&signals](const auto& fanin) { signals.push_back(fanin); }); + + // move PO one column to the right + lyt.move_node(lyt.get_node({lyt.x() - 1, y}), {lyt.x(), y, 0}, {}); + + // create a wire segment at the previous location of the PO and connect it with its fanin + lyt.create_buf(signals[0], {lyt.x() - 1, y}); + + // connect the PO with the new wire segment + lyt.move_node(lyt.get_node({lyt.x(), y}), {lyt.x(), y, 0}, + {lyt.make_signal(lyt.get_node({lyt.x() - 1, y}))}); + } + } + + // update bounding box + bounding_box.update_bounding_box(); + lyt.resize({bounding_box.get_max().x, bounding_box.get_max().y, lyt.z()}); + + // check if PO is located in bottom right corner and relocation would save more tiles (only possible for layouts + // with a single PO) + if (lyt.is_po_tile({lyt.x(), lyt.y(), 0}) && (lyt.num_pos() == 1)) + { + // check if relocation would save tiles + if (lyt.has_western_incoming_signal({lyt.x(), lyt.y(), 0}) && + ((lyt.x() * (lyt.y() + 2)) < ((lyt.x() + 1) * (lyt.y() + 1)))) + { + // get fanin signal of the PO + std::vector> signals{}; + signals.reserve(lyt.fanin_size(lyt.get_node({lyt.x(), lyt.y()}))); + lyt.foreach_fanin(lyt.get_node({lyt.x(), lyt.y()}), + [&signals](const auto& fanin) { signals.push_back(fanin); }); + + // resize layout + lyt.resize({lyt.x(), lyt.y() + 1, lyt.z()}); + + // move PO one tile down and to the left + lyt.move_node(lyt.get_node({lyt.x(), lyt.y() - 1}), {lyt.x() - 1, lyt.y(), 0}, signals); + } + // check if relocation would save tiles + else if (lyt.has_northern_incoming_signal({lyt.x(), lyt.y(), 0}) && + (((lyt.x() + 2) * lyt.y()) < ((lyt.x() + 1) * (lyt.y() + 1)))) + { + // get fanin signal of the PO + std::vector> signals{}; + signals.reserve(lyt.fanin_size(lyt.get_node({lyt.x(), lyt.y()}))); + lyt.foreach_fanin(lyt.get_node({lyt.x(), lyt.y()}), + [&signals](const auto& fanin) { signals.push_back(fanin); }); + + // resize layout + lyt.resize({lyt.x() + 1, lyt.y(), lyt.z()}); + + // move PO one tile up and to the right + lyt.move_node(lyt.get_node({lyt.x() - 1, lyt.y()}), {lyt.x(), lyt.y() - 1, 0}, signals); + } + } } /** * Custom comparison function for sorting tiles based on the sum of their coordinates that breaks ties based on the @@ -804,7 +895,7 @@ class post_layout_optimization_impl uint64_t max_gate_relocations = ps.max_gate_relocations.value_or((plyt.x() + 1) * (plyt.y() + 1)); - // Optimization + // optimization auto layout = obstruction_layout(plyt); bool moved_at_least_one_gate = true; bool reduced_wiring = true; @@ -846,15 +937,14 @@ class post_layout_optimization_impl std::sort(gate_tiles.begin(), gate_tiles.end(), detail::compare_gate_tiles); - tile max_non_po; - // Iterate through the vector in reverse - for (auto it = gate_tiles.rbegin(); it != gate_tiles.rend(); ++it) + tile max_non_po{0, 0}; + // determine minimal border for POs + for (const auto& gate_tile : gate_tiles) { - // Stop if a condition based on the element is met - if (!layout.is_po_tile(*it)) + if (!layout.is_po_tile(gate_tile)) { - max_non_po = *it; - break; + max_non_po.x = std::max(max_non_po.x, gate_tile.x); + max_non_po.y = std::max(max_non_po.y, gate_tile.y); } } moved_at_least_one_gate = false; @@ -936,14 +1026,14 @@ void post_layout_optimization(const Lyt& lyt, post_layout_optimization_params ps static_assert(is_gate_level_layout_v, "Lyt is not a gate-level layout"); static_assert(is_cartesian_layout_v, "Lyt is not a Cartesian layout"); - // Check if the clocking scheme is 2DDWave + // check if the clocking scheme is 2DDWave if (!lyt.is_clocking_scheme(clock_name::TWODDWAVE)) { std::cout << "[e] the given layout has to be 2DDWave-clocked\n"; return; } - // Initialize stats for runtime measurement + // initialize stats for runtime measurement post_layout_optimization_stats st{}; detail::post_layout_optimization_impl p{lyt, ps, st}; diff --git a/include/fiction/algorithms/physical_design/wiring_reduction.hpp b/include/fiction/algorithms/physical_design/wiring_reduction.hpp index 0893e0c41..55789779f 100644 --- a/include/fiction/algorithms/physical_design/wiring_reduction.hpp +++ b/include/fiction/algorithms/physical_design/wiring_reduction.hpp @@ -373,125 +373,109 @@ create_wiring_reduction_layout(const Lyt& lyt, const uint64_t x_offset = 0, cons static_assert(is_gate_level_layout_v, "Lyt is not a gate-level layout"); static_assert(is_cartesian_layout_v, "Lyt is not a Cartesian layout"); - // Create a wiring_reduction_layout with specified offsets + // create a wiring_reduction_layout with specified offsets wiring_reduction_layout> obs_wiring_reduction_layout{ {lyt.x() + x_offset + 1, lyt.y() + y_offset + 1, lyt.z()}, direction}; auto wiring_reduction_lyt = wiring_reduction_layout_type>(obs_wiring_reduction_layout); - // Iterate through nodes in the layout + // iterate through nodes in the layout lyt.foreach_node( [&lyt, &wiring_reduction_lyt, &x_offset, &y_offset](const auto& node) { const tile old_coord = lyt.get_tile(node); const tile new_coord{old_coord.x + x_offset, old_coord.y + y_offset, old_coord.z}; - // Skip if the tile is empty + // skip if the tile is empty if (lyt.is_empty_tile(old_coord)) { return; } - // Handle Primary Inputs (PI) and Primary Outputs (PO) + // handle Primary Inputs (PI) and Primary Outputs (PO) if (lyt.is_pi(node) || lyt.is_po(node)) { wiring_reduction_lyt.obstruct_coordinate(new_coord); wiring_reduction_lyt.obstruct_coordinate({new_coord.x, new_coord.y, 1}); } - // Handle single input gates and wires + // utility function to check if a tile hosts a single wire only, which is not a fanout or hosts a + // crossing: + // + // = + auto is_single_wire = [&lyt, &old_coord](const uint64_t x_offset, const uint64_t y_offset) + { + return lyt.is_wire_tile({old_coord.x - x_offset, old_coord.y - y_offset, 0}) && + !lyt.is_fanout(lyt.get_node({old_coord.x - x_offset, old_coord.y - y_offset, 0}) && + lyt.is_empty_tile({old_coord.x - x_offset, old_coord.y - y_offset, 1})); + }; + + // utility function to check for crossings with outgoing wires to the bottom layer: + // + // +→= + // ↓ + // = + auto is_crossing = [&lyt, &old_coord](const uint64_t x_offset, const uint64_t y_offset) + { + return lyt.has_northern_incoming_signal({old_coord.x - x_offset, old_coord.y - y_offset + 1, 0}) && + lyt.has_western_incoming_signal({old_coord.x - x_offset + 1, old_coord.y - y_offset, 0}); + }; + + // utility function to fully obstruct a coordinate + auto obstruct_coordinate = + [&wiring_reduction_lyt, &new_coord](const uint64_t x_offset, const uint64_t y_offset) + { + wiring_reduction_lyt.obstruct_coordinate({new_coord.x - x_offset, new_coord.y - y_offset, 0}); + wiring_reduction_lyt.obstruct_coordinate({new_coord.x - x_offset, new_coord.y - y_offset, 1}); + }; + + // handle single input gates and wires if (const auto signals = lyt.incoming_data_flow(old_coord); signals.size() == 1) { const auto incoming_signal = signals[0]; const tile shifted_tile{incoming_signal.x + x_offset, incoming_signal.y + y_offset, incoming_signal.z}; - // Obstruct the connection between the gate and its incoming signal + // obstruct the connection between the gate and its incoming signal wiring_reduction_lyt.obstruct_connection(shifted_tile, new_coord); - // Obstruct horizontal/vertical wires, non-wire gates (inv) and fanouts + // obstruct horizontal/vertical wires, non-wire gates (inv) and fanouts if (!lyt.is_wire(node) || (lyt.fanout_size(node) != 1) || (old_coord.z != 0) || (lyt.has_western_incoming_signal({old_coord}) && lyt.has_eastern_outgoing_signal({old_coord}) && (wiring_reduction_lyt.get_search_direction() == search_direction::HORIZONTAL)) || (lyt.has_northern_incoming_signal({old_coord}) && lyt.has_southern_outgoing_signal({old_coord}) && (wiring_reduction_lyt.get_search_direction() == search_direction::VERTICAL))) { - wiring_reduction_lyt.obstruct_coordinate({new_coord.x, new_coord.y, 0}); - wiring_reduction_lyt.obstruct_coordinate({new_coord.x, new_coord.y, 1}); - - if (old_coord.z == 0) - { - return; - } - - // special case 1: - // +→= - // ↓ ↓ - // =→+ - // - // special case 2: - // = - // ↓ - // = = - // ↓ ↓ - // =→+ - // - // special case 3: - // - // =→= - // ↓ - // =→=→+ - const auto special_case_1 = lyt.has_northern_incoming_signal({old_coord.x - 1, old_coord.y, 0}) && - lyt.has_western_incoming_signal({old_coord.x, old_coord.y - 1, 0}); - const auto special_case_2 = lyt.has_northern_incoming_signal({old_coord.x - 1, old_coord.y, 0}) && - lyt.has_northern_incoming_signal({old_coord.x, old_coord.y - 1, 0}) && - lyt.is_wire_tile({old_coord.x, old_coord.y - 2, 0}) && - lyt.is_wire_tile({old_coord.x - 1, old_coord.y - 1, 0}); - const auto special_case_3 = lyt.has_western_incoming_signal({old_coord.x - 1, old_coord.y, 0}) && - lyt.has_western_incoming_signal({old_coord.x, old_coord.y - 1, 0}) && - lyt.is_wire_tile({old_coord.x - 2, old_coord.y, 0}) && - lyt.is_wire_tile({old_coord.x - 1, old_coord.y - 1, 0}); - if (!(special_case_1 || special_case_2 || special_case_3)) - { - return; - } - - // -> No crossing between coordinate to the left and coordinate above the gate - if ((wiring_reduction_lyt.get_search_direction() == search_direction::HORIZONTAL) && - (special_case_1 || special_case_2)) - { - wiring_reduction_lyt.obstruct_connection({new_coord.x - 1, new_coord.y, 0}, - {new_coord.x, new_coord.y - 1, 0}); - } - else if ((wiring_reduction_lyt.get_search_direction() == search_direction::VERTICAL) && - (special_case_1 || special_case_3)) - { - wiring_reduction_lyt.obstruct_connection({new_coord.x, new_coord.y - 1, 0}, - {new_coord.x - 1, new_coord.y, 0}); - } + obstruct_coordinate(0, 0); } - // For bent wires from north to east, obstruct the connection between the wire and the + // for bent wires from north to east, obstruct the connection between the wire and the // coordinate to the bottom right/ top left else if (lyt.has_northern_incoming_signal({old_coord}) && lyt.has_eastern_outgoing_signal({old_coord})) { if (wiring_reduction_lyt.get_search_direction() == search_direction::HORIZONTAL) { - wiring_reduction_lyt.obstruct_connection(new_coord, - {new_coord.x + 1, new_coord.y + 1, new_coord.z}); - // special case: - // →= - // ↓ - // =→ - // - // -> Only one wire can be deleted - if (lyt.has_western_incoming_signal({old_coord.x, old_coord.y - 1, old_coord.z}) && - lyt.is_wire(lyt.get_node({old_coord.x, old_coord.y - 1, old_coord.z}))) { - wiring_reduction_lyt.obstruct_coordinate({new_coord.x, new_coord.y - 1, 0}); - wiring_reduction_lyt.obstruct_coordinate({new_coord.x, new_coord.y - 1, 1}); + wiring_reduction_lyt.obstruct_connection(new_coord, + {new_coord.x + 1, new_coord.y + 1, new_coord.z}); + + // special cases: + // →= + // ↓ + // ... + // ↓ + // =→ + for (uint64_t i = 1; is_single_wire(0, i); ++i) + { + if (lyt.has_western_incoming_signal({old_coord.x, old_coord.y - i, old_coord.z})) + { + obstruct_coordinate(0, i); + break; + } + } } } + else { wiring_reduction_lyt.obstruct_connection({new_coord.x - 1, new_coord.y - 1, new_coord.z}, @@ -499,7 +483,7 @@ create_wiring_reduction_layout(const Lyt& lyt, const uint64_t x_offset = 0, cons } } - // For bent wires from west to south, obstruct the connection between the wire and the + // for bent wires from west to south, obstruct the connection between the wire and the // coordinate to the top left/ bottom right else if (lyt.has_western_incoming_signal({old_coord}) && lyt.has_southern_outgoing_signal({old_coord})) { @@ -512,23 +496,24 @@ create_wiring_reduction_layout(const Lyt& lyt, const uint64_t x_offset = 0, cons { wiring_reduction_lyt.obstruct_connection(new_coord, {new_coord.x + 1, new_coord.y + 1, new_coord.z}); - // special case: + + // special cases: // ↓ - // =→= - // ↓ - // - // -> Only one wire can be deleted - if (lyt.has_northern_incoming_signal({old_coord.x - 1, old_coord.y, old_coord.z}) && - lyt.is_wire(lyt.get_node({old_coord.x - 1, old_coord.y, old_coord.z}))) + // =→...→= + // ↓ + for (uint64_t i = 1; is_single_wire(i, 0); ++i) { - wiring_reduction_lyt.obstruct_coordinate({new_coord.x - 1, new_coord.y, 0}); - wiring_reduction_lyt.obstruct_coordinate({new_coord.x - 1, new_coord.y, 1}); + if (lyt.has_northern_incoming_signal({old_coord.x - i, old_coord.y, old_coord.z})) + { + obstruct_coordinate(i, 0); + break; + } } } } } - // Handle double input gates (AND, OR, ...) + // handle double input gates (AND, OR, ...) else if (signals.size() == 2) { const auto signal_a = signals[0]; @@ -540,29 +525,73 @@ create_wiring_reduction_layout(const Lyt& lyt, const uint64_t x_offset = 0, cons wiring_reduction_lyt.obstruct_connection(shifted_tile_a, new_coord); wiring_reduction_lyt.obstruct_connection(shifted_tile_b, new_coord); - wiring_reduction_lyt.obstruct_coordinate(new_coord); - wiring_reduction_lyt.obstruct_coordinate({new_coord.x, new_coord.y, 1}); + obstruct_coordinate(0, 0); + } - // special case: + if (const auto signals = lyt.incoming_data_flow(old_coord); (old_coord.z == 1) || (signals.size() == 2)) + { + // special cases (where the crossing can also be placed further to the left or top): // +→= // ↓ ↓ // =→& // - // -> No crossing between coordinate to the left and coordinate above the gate - if (!(lyt.has_northern_incoming_signal({old_coord.x - 1, old_coord.y, old_coord.z}) && - lyt.has_western_incoming_signal({old_coord.x, old_coord.y - 1, old_coord.z}))) - { - return; - } - if (wiring_reduction_lyt.get_search_direction() == search_direction::HORIZONTAL) - { - wiring_reduction_lyt.obstruct_connection({new_coord.x - 1, new_coord.y, new_coord.z}, - {new_coord.x, new_coord.y - 1, new_coord.z}); - } - else + // or: + // + // +→= + // ↓ ↓ + // =→+ + if (is_single_wire(1, 0) && is_single_wire(0, 1)) { - wiring_reduction_lyt.obstruct_connection({new_coord.x, new_coord.y - 1, new_coord.z}, - {new_coord.x - 1, new_coord.y, new_coord.z}); + bool obstruct = false; + + for (uint64_t i = 1; true; ++i) + { + if (is_crossing(1, 1)) + { + obstruct = true; + break; + } + if (wiring_reduction_lyt.get_search_direction() == search_direction::HORIZONTAL) + { + if (!is_single_wire(1, i) || !is_single_wire(0, i + 1) || + !lyt.has_northern_incoming_signal({old_coord.x - 1, old_coord.y - i + 1, 0}) || + !lyt.has_northern_incoming_signal({old_coord.x, old_coord.y - i, 0})) + { + break; + } + if (is_crossing(1, i + 1)) + { + obstruct = true; + break; + } + } + else + { + if (!is_single_wire(i, 1) || !is_single_wire(i + 1, 0) || + !lyt.has_western_incoming_signal({old_coord.x - i, old_coord.y, 0}) || + !lyt.has_western_incoming_signal({old_coord.x - i + 1, old_coord.y - i, 0})) + { + break; + } + if (is_crossing(i + 1, 1)) + { + obstruct = true; + break; + } + } + } + + if (obstruct) + { + if (wiring_reduction_lyt.get_search_direction() == search_direction::HORIZONTAL) + { + obstruct_coordinate(1, 0); + } + else + { + obstruct_coordinate(0, 1); + } + } } } }); @@ -584,14 +613,14 @@ void add_obstructions(WiringReductionLyt& lyt) noexcept { if (lyt.get_search_direction() == search_direction::HORIZONTAL) { - // Add obstructions to the top edge of the layout + // add obstructions to the top edge of the layout for (uint64_t x = 1; x <= lyt.x(); x++) { lyt.obstruct_coordinate({x, 0, 0}); lyt.obstruct_coordinate({x, 0, 1}); } - // Add obstructions to the bottom edge of the layout + // add obstructions to the bottom edge of the layout for (uint64_t x = 0; x < lyt.x(); x++) { lyt.obstruct_coordinate({x, lyt.y(), 0}); @@ -600,14 +629,14 @@ void add_obstructions(WiringReductionLyt& lyt) noexcept } else { - // Add obstructions to the left edge of the layout + // add obstructions to the left edge of the layout for (uint64_t y = 1; y <= lyt.y(); y++) { lyt.obstruct_coordinate({0, y, 0}); lyt.obstruct_coordinate({0, y, 1}); } - // Add obstructions to the right edge of the layout + // add obstructions to the right edge of the layout for (uint64_t y = 0; y < lyt.y(); y++) { lyt.obstruct_coordinate({lyt.x(), y, 0}); @@ -656,17 +685,17 @@ void update_to_delete_list(WiringReductionLyt& lyt, const layout_coordinate_path { for (const auto& coord : possible_path) { - // Check if the coordinate is not at the leftmost or rightmost position + // check if the coordinate is not at the leftmost or rightmost position if (((lyt.get_search_direction() == search_direction::HORIZONTAL) && coord.x != 0 && coord.x != lyt.x()) || ((lyt.get_search_direction() == search_direction::VERTICAL) && coord.y != 0 && coord.y != lyt.y())) { - // Create the corresponding coordinate on the original layout + // create the corresponding coordinate on the original layout const fiction::coordinate shifted_coord{coord.x - 1, coord.y - 1, 0}; - // Append the corresponding coordinate to the to-delete list + // append the corresponding coordinate to the to-delete list to_delete.append(shifted_coord); - // Obstruct the coordinate in both layers + // obstruct the coordinate in both layers lyt.obstruct_coordinate({coord.x, coord.y, 0}); lyt.obstruct_coordinate({coord.x, coord.y, 1}); } @@ -695,10 +724,10 @@ template calculate_offset_matrix(const WiringReductionLyt& lyt, const layout_coordinate_path& to_delete) noexcept { - // Initialize matrix with zeros + // initialize matrix with zeros offset_matrix matrix(lyt.y() + 1, std::vector(lyt.x() + 1, 0)); - // Update matrix based on coordinates + // update matrix based on coordinates for (const auto& coord : to_delete) { const auto x = coord.x; @@ -780,7 +809,7 @@ void adjust_tile_horizontal_search_dir(Lyt& lyt, const LytCpy& layout_copy, tile { bool traversing_deleted_wires = false; - // Check if traversing through deleted wires + // check if traversing through deleted wires if (offset_mtrx[fanin.y + 1][fanin.x] != offset_mtrx[fanin.y][fanin.x]) { fanin = {fanin.x, fanin.y, 0}; @@ -789,7 +818,7 @@ void adjust_tile_horizontal_search_dir(Lyt& lyt, const LytCpy& layout_copy, tile uint64_t offset_offset = 0; - // If traversing through deleted wires, update the offset + // if traversing through deleted wires, update the offset if (traversing_deleted_wires) { for (uint64_t o = 0; o < offset; ++o) @@ -808,7 +837,7 @@ void adjust_tile_horizontal_search_dir(Lyt& lyt, const LytCpy& layout_copy, tile } } - // Create signals for the new coordinates + // create signals for the new coordinates signals.push_back(lyt.make_signal(lyt.get_node({fanin.x, fanin.y - offset + offset_offset, fanin.z}))); } } @@ -842,7 +871,7 @@ void adjust_tile_vertical_search_dir(Lyt& lyt, const LytCpy& layout_copy, tile old_coord = {x, y, z}; - // Check if the tile is not empty and has an offset + // check if the tile is not empty and has an offset if (!(lyt.is_empty_tile(old_coord)) && (offset != 0)) { const auto new_coord = determine_new_coord(wiring_reduction_lyt, x, y, z, offset); std::vector> signals{}; signals.reserve(layout_copy.fanin_size(layout_copy.get_node(old_coord))); - // Iterate through fanin and create signals for the new coordinates + // iterate through fanins and create signals for the new coordinates layout_copy.foreach_fanin( layout_copy.get_node(old_coord), [&lyt, &signals, &offset, &old_coord, &layout_copy, &offset_mtrx, &wiring_reduction_lyt](const auto& fi) @@ -927,19 +956,21 @@ void adjust_tile(Lyt& lyt, const LytCpy& layout_copy, const WiringReductionLyt& if (lyt.is_po(lyt.get_node(old_coord))) { if ((wiring_reduction_lyt.get_search_direction() == search_direction::HORIZONTAL) && - !lyt.is_empty_tile({new_coord.x + 1, new_coord.y, new_coord.z})) + !lyt.is_empty_tile({new_coord.x + 1, new_coord.y, new_coord.z}) && + lyt.has_western_incoming_signal({new_coord.x + 1, new_coord.y, new_coord.z})) { lyt.move_node(lyt.get_node({new_coord.x + 1, new_coord.y, new_coord.z}), {new_coord.x + 1, new_coord.y, new_coord.z}, {}); } if ((wiring_reduction_lyt.get_search_direction() == search_direction::VERTICAL) && - !lyt.is_empty_tile({new_coord.x, new_coord.y + 1, new_coord.z})) + !lyt.is_empty_tile({new_coord.x, new_coord.y + 1, new_coord.z}) && + lyt.has_northern_incoming_signal({new_coord.x, new_coord.y + 1, new_coord.z})) { lyt.move_node(lyt.get_node({new_coord.x, new_coord.y + 1, new_coord.z}), {new_coord.x, new_coord.y + 1, new_coord.z}, {}); } } - // Move the node to the new coordinates + // move the node to the new coordinates lyt.move_node(lyt.get_node(old_coord), new_coord, signals); } } @@ -964,16 +995,16 @@ void delete_wires(Lyt& lyt, WiringReductionLyt& wiring_reduction_layout, const auto off_mat = calculate_offset_matrix(wiring_reduction_layout, to_delete); - // Create a copy of the original layout for reference + // create a copy of the original layout for reference const auto layout_copy = lyt.clone(); - // Clear tiles based on the to-delete list + // clear tiles based on the to-delete list for (const auto& tile_to_delete : to_delete) { lyt.clear_tile(tile_to_delete); } - // Iterate over the layout to delete wires and adjust the layout + // iterate over the layout to delete wires and adjust the layout for (uint64_t k = 0; k < lyt.x() + lyt.y() + 1; ++k) { for (uint64_t x = 0; x < k + 1; ++x) @@ -989,12 +1020,12 @@ void delete_wires(Lyt& lyt, WiringReductionLyt& wiring_reduction_layout, } } - // Calculate bounding box for optimized layout size + // calculate bounding box for optimized layout size const auto bounding_box = bounding_box_2d(lyt); const auto optimized_layout_width = bounding_box.get_x_size(); const auto optimized_layout_height = bounding_box.get_y_size(); - // Resize the layout to the optimized size + // resize the layout to the optimized size lyt.resize({optimized_layout_width, optimized_layout_height, lyt.z()}); } @@ -1022,10 +1053,10 @@ class wiring_reduction_impl bool found_wires = true; - // Perform wiring reduction iteratively until no further wires can be deleted + // perform wiring reduction iteratively until no further wires can be deleted while (found_wires) { - // Continue until no further wires can be deleted + // continue until no further wires can be deleted found_wires = false; for (const auto direction : {search_direction::HORIZONTAL, search_direction::VERTICAL}) @@ -1034,24 +1065,24 @@ class wiring_reduction_impl add_obstructions(wiring_reduction_lyt); to_delete = {}; - // Get the initial possible path + // get the initial possible path auto possible_path = get_path(wiring_reduction_lyt, {0, 0}, {wiring_reduction_lyt.x(), wiring_reduction_lyt.y()}); - // Iterate while there is a possible path + // iterate while there is a possible path while (!possible_path.empty()) { update_to_delete_list>>(wiring_reduction_lyt, possible_path, to_delete); - // Update possible_path for the next iteration + // update possible_path for the next iteration possible_path = get_path(wiring_reduction_lyt, {0, 0}, {wiring_reduction_lyt.x(), wiring_reduction_lyt.y()}); } if (!to_delete.empty()) { - // Calculate offset matrix and delete wires based on to-delete list + // calculate offset matrix and delete wires based on to-delete list delete_wires(layout, wiring_reduction_lyt, to_delete); found_wires = true; } @@ -1112,14 +1143,14 @@ void wiring_reduction(const Lyt& lyt, wiring_reduction_stats* pst = nullptr) noe static_assert(is_gate_level_layout_v, "Lyt is not a gate-level layout"); static_assert(is_cartesian_layout_v, "Lyt is not a Cartesian layout"); - // Check if the clocking scheme is 2DDWave + // check if the clocking scheme is 2DDWave if (!lyt.is_clocking_scheme(clock_name::TWODDWAVE)) { std::cout << "[e] the given layout has to be 2DDWave-clocked\n"; return; } - // Initialize stats for runtime measurement + // initialize stats for runtime measurement wiring_reduction_stats st{}; detail::wiring_reduction_impl p{lyt, st};