diff --git a/docs/changelog.rst b/docs/changelog.rst index 23da2f431..4ec7520da 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -16,7 +16,7 @@ v0.1 (not yet released) - LUT mapping (`lut_mapping`) `#7 `_ - Akers synthesis (`akers_synthesis`) `#9 `_ - Create LUT network from mapped network (`collapse_mapped_network`) `#13 `_ - - MIG algebraic depth rewriting (`mig_algebraic_depth_rewriting`) `#16 `_ + - MIG algebraic depth rewriting (`mig_algebraic_depth_rewriting`) `#16 `_ `#58 `_ - Cleanup dangling nodes (`cleanup_dangling`) `#16 `_ - Node resynthesis (`node_resynthesis`) `#17 `_ - Reconvergency-driven cut computation (`reconv_cut`) `#24 `_ diff --git a/include/mockturtle/algorithms/mig_algebraic_rewriting.hpp b/include/mockturtle/algorithms/mig_algebraic_rewriting.hpp index 0dc1f3051..84e1afcf2 100644 --- a/include/mockturtle/algorithms/mig_algebraic_rewriting.hpp +++ b/include/mockturtle/algorithms/mig_algebraic_rewriting.hpp @@ -78,6 +78,9 @@ struct mig_algebraic_depth_rewriting_params * number of dangling nodes are taken into account. */ float overhead{2.0f}; + + /*! \brief Allow area increase while optimizing depth. */ + bool allow_area_increase{true}; }; namespace detail @@ -192,6 +195,10 @@ class mig_algebraic_depth_rewriting_impl if ( ntk.level( ntk.get_node( ocs[2] ) ) <= ntk.level( ntk.get_node( ocs[1] ) ) + 1 ) return false; + /* child must have single fanout, if no area overhead is allowed */ + if ( !ps.allow_area_increase && ntk.fanout_size( ntk.get_node( ocs[2] ) ) != 1 ) + return false; + /* get children of last child */ auto ocs2 = ordered_children( ntk.get_node( ocs[2] ) ); @@ -218,11 +225,14 @@ class mig_algebraic_depth_rewriting_impl } /* distributivity */ - auto opt = ntk.create_maj( ocs2[2], - ntk.create_maj( ocs[0], ocs[1], ocs2[0] ), - ntk.create_maj( ocs[0], ocs[1], ocs2[1] ) ); - ntk.substitute_node( n, opt ); - ntk.update(); + if ( ps.allow_area_increase ) + { + auto opt = ntk.create_maj( ocs2[2], + ntk.create_maj( ocs[0], ocs[1], ocs2[0] ), + ntk.create_maj( ocs[0], ocs[1], ocs2[1] ) ); + ntk.substitute_node( n, opt ); + ntk.update(); + } return true; } diff --git a/test/algorithms/quality.cpp b/test/algorithms/quality.cpp index c6e58ff55..308f270c6 100644 --- a/test/algorithms/quality.cpp +++ b/test/algorithms/quality.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -163,4 +164,36 @@ TEST_CASE( "Test quality of MIG resubstitution", "[quality]" ) CHECK( v == std::vector{{6, 208, 398, 317, 502, 333, 704, 1007, 1741, 2322, 1460}} ); } +TEST_CASE( "Test quality of MIG algebraic depth rewriting", "[quality]" ) +{ + const auto v = foreach_benchmark( []( auto& ntk, auto ) { + depth_view depth_ntk{ntk}; + const auto before = depth_ntk.depth(); + mig_algebraic_depth_rewriting( depth_ntk ); + ntk = cleanup_dangling( ntk ); + depth_ntk.update(); + return before - depth_ntk.depth(); + } ); + + CHECK( v == std::vector{{0, 4, 1, 8, 2, 4, 3, 11, 6, 35, 7}} ); +} + +TEST_CASE( "Test quality of MIG algebraic depth rewriting without area increase", "[quality]" ) +{ + const auto v = foreach_benchmark( []( auto& ntk, auto ) { + depth_view depth_ntk{ntk}; + const auto size_before = ntk.num_gates(); + const auto before = depth_ntk.depth(); + mig_algebraic_depth_rewriting_params ps; + ps.allow_area_increase = false; + mig_algebraic_depth_rewriting( depth_ntk, ps ); + ntk = cleanup_dangling( ntk ); + depth_ntk.update(); + CHECK( ntk.num_gates() <= size_before ); + return before - depth_ntk.depth(); + } ); + + CHECK( v == std::vector{{0, 1, 0, 5, 0, 0, 2, 6, 3, 0, 6}} ); +} + #endif