Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🐛 Multi-output nodes #451

Merged
merged 26 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
6209f55
handle multi-output nodes
simon1hofmann Jun 4, 2024
5f997e0
:memo: Update pyfiction docstrings
actions-user Jun 4, 2024
7080ae7
Merge branch 'main' into fix_ortho_multiple_po_bug
simon1hofmann Jun 4, 2024
78f7fa8
Place POs in main loop
simon1hofmann Jun 5, 2024
618a4fc
:memo: Update pyfiction docstrings
actions-user Jun 5, 2024
94ef430
restore old version
simon1hofmann Jun 5, 2024
aca77e5
:memo: Update pyfiction docstrings
actions-user Jun 5, 2024
a95a233
handle multi-output po corner case separately
simon1hofmann Jun 6, 2024
1d30773
Merge remote-tracking branch 'origin/fix_ortho_multiple_po_bug' into …
simon1hofmann Jun 6, 2024
227b2d9
:memo: Update pyfiction docstrings
actions-user Jun 6, 2024
e1568a2
check for ordering
simon1hofmann Jun 6, 2024
719ca4c
Merge branch 'main' into fix_ortho_multiple_po_bug
marcelwa Jun 28, 2024
2e93390
Merge branch 'main' into fix_ortho_multiple_po_bug
simon1hofmann Jul 4, 2024
f6d156a
:art: Code cleanup and consistency
marcelwa Jul 5, 2024
4560b7d
Update orthogonal.hpp
simon1hofmann Jul 15, 2024
d01a1ef
:memo: Update pyfiction docstrings
actions-user Jul 15, 2024
1654191
Merge branch 'main' into fix_ortho_multiple_po_bug
simon1hofmann Jul 15, 2024
b9e3cd5
Update orthogonal.hpp
simon1hofmann Jul 15, 2024
8173702
Update orthogonal.hpp
simon1hofmann Jul 16, 2024
37383e8
:memo: Update pyfiction docstrings
actions-user Jul 16, 2024
68a0058
Update orthogonal.hpp
simon1hofmann Jul 16, 2024
d9d8802
Update orthogonal.hpp
simon1hofmann Jul 16, 2024
fabe401
🎨 Incorporated pre-commit fixes
pre-commit-ci[bot] Jul 16, 2024
07f7463
Update orthogonal.hpp
simon1hofmann Jul 16, 2024
bbcbdb8
Update orthogonal.hpp
simon1hofmann Jul 16, 2024
b287f35
Update orthogonal.hpp
simon1hofmann Jul 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6046,6 +6046,39 @@ static const char *__doc_fiction_detail_orthogonal_impl_pst = R"doc()doc";

static const char *__doc_fiction_detail_orthogonal_impl_run = R"doc()doc";

static const char *__doc_fiction_detail_place_outputs =
R"doc(Places the primary outputs (POs) in the layout.

This function positions the POs within the provided layout. If a PO is
a multi-output node (a fanout with two POs connected to it), the
second PO is automatically placed and connected below the first
output.

The positioning of multi-output nodes will follow this structure:

F→=→...→O ↓ =→=→...→O

Template parameter ``Lyt``:
Desired gate-level layout type.

Template parameter ``Ntk``:
Network type that acts as specification.

Parameter ``layout``:
Current gate-level layout.

Parameter ``ctn``:
Contains the colored network.

Parameter ``po_counter``:
Counter for POs.

Parameter ``node2pos``:
Mapping from network nodes to layout signals, i.e., a pointer to
their position in the layout. The map is used to fetch location of
the fanins. The `mockturtle::node_map` is not updated by this
function.)doc";

static const char *__doc_fiction_detail_post_layout_optimization_impl = R"doc()doc";

static const char *__doc_fiction_detail_post_layout_optimization_impl_plyt = R"doc(2DDWave-clocked Cartesian gate-level layout to optimize.)doc";
Expand Down
147 changes: 104 additions & 43 deletions include/fiction/algorithms/physical_design/orthogonal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,8 @@ uint32_t is_eastern_po_orientation_available(const coloring_container<Ntk>& ctn,
}

template <typename Lyt, typename Ntk>
aspect_ratio<Lyt> determine_layout_size(const coloring_container<Ntk>& ctn) noexcept
aspect_ratio<Lyt> determine_layout_size(const coloring_container<Ntk>& ctn,
const uint32_t num_multi_output_nodes) noexcept
{
#if (PROGRESS_BARS)
// initialize a progress bar
Expand Down Expand Up @@ -307,6 +308,9 @@ aspect_ratio<Lyt> determine_layout_size(const coloring_container<Ntk>& ctn) noex
#endif
});

// for multi-output nodes, add another row
y += num_multi_output_nodes;

return {x, y, 1};
}

Expand Down Expand Up @@ -379,6 +383,78 @@ mockturtle::signal<Lyt> connect_and_place(Lyt& lyt, const tile<Lyt>& t, const Nt
return {}; // fix -Wreturn-type warning
}

/**
* Places the primary outputs (POs) in the layout.
*
* This function positions the POs within the provided layout. If a PO is a multi-output node (a fanout with two POs
* connected to it), the second PO is automatically placed and connected below the first output.
*
* The positioning of multi-output nodes will follow this structure:
*
* F→=→...→O
* ↓
* =→=→...→O
*
* @tparam Lyt Desired gate-level layout type.
* @tparam Ntk Network type that acts as specification.
* @param layout Current gate-level layout.
* @param ctn Contains the colored network.
* @param po_counter Counter for POs.
* @param node2pos Mapping from network nodes to layout signals, i.e., a pointer to their position in the layout. The
* map is used to fetch location of the fanins. The `mockturtle::node_map` is not updated by this function.
*/
template <typename Ntk, typename Lyt>
void place_outputs(Lyt& layout, const coloring_container<Ntk>& ctn, uint32_t po_counter,
const mockturtle::node_map<mockturtle::signal<Lyt>, decltype(ctn.color_ntk)>& node2pos)
{
std::vector<mockturtle::node<Ntk>> output_nodes{};

ctn.color_ntk.foreach_po(
[&po_counter, &output_nodes, &node2pos, &ctn, &layout](const auto& po)
{
if (!ctn.color_ntk.is_constant(po))
{
const auto n_s = node2pos[po];
auto po_tile = static_cast<tile<Lyt>>(n_s);

const auto multi_output_node =
std::find(output_nodes.cbegin(), output_nodes.cend(), po) != output_nodes.cend();

// determine PO orientation
if (!is_eastern_po_orientation_available(ctn, po) || multi_output_node)
{
po_tile = static_cast<tile<Lyt>>(wire_south(layout, po_tile, {po_tile.x, po_tile.y + 2}));
}

// check if PO position is located at the border
if (layout.is_at_eastern_border({po_tile.x + 1, po_tile.y}) && !multi_output_node)
{
++po_tile.x;
layout.create_po(n_s,
ctn.color_ntk.has_output_name(po_counter) ?
ctn.color_ntk.get_output_name(po_counter++) :
fmt::format("po{}", po_counter++),
po_tile);
}
// place PO at the border and connect it by wire segments
else
{
const tile<Lyt> anker{po_tile};

po_tile = layout.eastern_border_of(po_tile);

layout.create_po(wire_east(layout, anker, po_tile),
ctn.color_ntk.has_output_name(po_counter) ?
ctn.color_ntk.get_output_name(po_counter++) :
fmt::format("po{}", po_counter++),
po_tile);
}

output_nodes.push_back(po);
}
});
}

template <typename Lyt, typename Ntk>
class orthogonal_impl
{
Expand All @@ -398,8 +474,26 @@ class orthogonal_impl

mockturtle::node_map<mockturtle::signal<Lyt>, decltype(ctn.color_ntk)> node2pos{ctn.color_ntk};

// find multi-output nodes
std::vector<mockturtle::node<decltype(ntk)>> output_nodes{};
std::vector<mockturtle::node<decltype(ntk)>> multi_output_nodes{};
uint32_t num_multi_output_nodes{0};

ctn.color_ntk.foreach_po(
[&](const auto& po)
{
if (std::find(output_nodes.cbegin(), output_nodes.cend(), po) != output_nodes.cend())
{
multi_output_nodes.push_back(po);
++num_multi_output_nodes;
}

output_nodes.push_back(po);
});

// instantiate the layout
Lyt layout{determine_layout_size<Lyt>(ctn), twoddwave_clocking<Lyt>(ps.number_of_clock_phases)};
Lyt layout{determine_layout_size<Lyt>(ctn, num_multi_output_nodes),
twoddwave_clocking<Lyt>(ps.number_of_clock_phases)};

// reserve PI nodes without positions
auto pi2node = reserve_input_nodes(layout, ctn.color_ntk);
Expand All @@ -413,7 +507,7 @@ class orthogonal_impl
#endif

ctn.color_ntk.foreach_node(
[&, this](const auto& n, [[maybe_unused]] const auto i)
[&](const auto& n, [[maybe_unused]] const auto i)
{
// do not place constants
if (!ctn.color_ntk.is_constant(n))
Expand Down Expand Up @@ -534,47 +628,11 @@ class orthogonal_impl
node2pos[n] = connect_and_place(layout, t, ctn.color_ntk, n, pre1_t, pre2_t, fc.constant_fanin);
}

// create PO at applicable position
if (ctn.color_ntk.is_po(n))
if (ctn.color_ntk.is_po(n) && (!is_eastern_po_orientation_available(ctn, n) ||
std::find(multi_output_nodes.cbegin(), multi_output_nodes.cend(),
n) != multi_output_nodes.cend()))
{
const auto n_s = node2pos[n];

tile<Lyt> po_tile{};

// determine PO orientation
if (is_eastern_po_orientation_available(ctn, n))
{
po_tile = layout.east(static_cast<tile<Lyt>>(n_s));
++latest_pos.x;
}
else
{
po_tile = layout.south(static_cast<tile<Lyt>>(n_s));
++latest_pos.y;
}

// check if PO position is located at the border
if (layout.is_at_eastern_border(po_tile))
{
layout.create_po(n_s,
ctn.color_ntk.has_output_name(po_counter) ?
ctn.color_ntk.get_output_name(po_counter++) :
fmt::format("po{}", po_counter++),
po_tile);
}
// place PO at the border and connect it by wire segments
else
{
const auto anker = layout.create_buf(n_s, po_tile);

po_tile = layout.eastern_border_of(po_tile);

layout.create_po(wire_east(layout, static_cast<tile<Lyt>>(anker), po_tile),
ctn.color_ntk.has_output_name(po_counter) ?
ctn.color_ntk.get_output_name(po_counter++) :
fmt::format("po{}", po_counter++),
po_tile);
}
++latest_pos.y;
}
}

Expand All @@ -584,6 +642,9 @@ class orthogonal_impl
#endif
});

// place outputs after the main algorithm to handle possible multi-output or unordered nodes
place_outputs(layout, ctn, po_counter, node2pos);

// restore possibly set signal names
restore_names(ctn.color_ntk, layout, node2pos);

Expand Down
3 changes: 3 additions & 0 deletions test/algorithms/physical_design/orthogonal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ void check_ortho_equiv_all()

// constant input network
check_ortho_equiv<Lyt>(blueprints::unbalanced_and_inv_network<mockturtle::mig_network>());

// multi-output network
check_ortho_equiv<Lyt>(blueprints::multi_output_network<technology_network>());
}

TEST_CASE("Layout equivalence", "[algorithms]")
Expand Down
15 changes: 15 additions & 0 deletions test/utils/blueprints/network_blueprints.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,21 @@ mockturtle::names_view<Ntk> topolinano_network()
return ntk;
}

template <typename Ntk>
mockturtle::names_view<Ntk> multi_output_network()
{
mockturtle::names_view<Ntk> ntk{};

const auto x1 = ntk.create_pi("x1");
const auto x2 = ntk.create_pi("x2");

const auto a1 = ntk.create_and(x1, x2);

ntk.create_po(a1, "f1");
ntk.create_po(a1, "f2");

return ntk;
}
} // namespace blueprints

#endif // FICTION_NETWORK_BLUEPRINTS_HPP
Loading