From 82d5c9c4b086194e8938f2e9953016d373f026a7 Mon Sep 17 00:00:00 2001 From: Sonia Date: Mon, 26 Apr 2021 21:15:51 +0200 Subject: [PATCH 1/4] sort fanouts of PIs --- include/mockturtle/views/aqfp_view.hpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/mockturtle/views/aqfp_view.hpp b/include/mockturtle/views/aqfp_view.hpp index 026d76559..74facc27a 100644 --- a/include/mockturtle/views/aqfp_view.hpp +++ b/include/mockturtle/views/aqfp_view.hpp @@ -226,6 +226,11 @@ class aqfp_view : public Ntk count += num_buffers( n ); }); } + else + { + assert( !_ps.balance_pis && "Does not make sense to balance but not branch PIs" ); + } + this->foreach_gate( [&]( auto const& n ){ count += num_buffers( n ); }); @@ -420,6 +425,13 @@ class aqfp_view : public Ntk this->foreach_gate( [&]( auto const& n ){ on_update( n ); }); + + if ( _ps.branch_pis ) + { + this->foreach_pi( [&]( auto const& n ){ + on_update( n ); + }); + } } void on_update( node const& n ) From 6c538828aee93776264a47c6ea287614d3492177 Mon Sep 17 00:00:00 2001 From: Sonia Date: Mon, 26 Apr 2021 22:17:08 +0200 Subject: [PATCH 2/4] tests for fanout_limit_view --- test/views/fanout_limit_view.cpp | 120 +++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 test/views/fanout_limit_view.cpp diff --git a/test/views/fanout_limit_view.cpp b/test/views/fanout_limit_view.cpp new file mode 100644 index 000000000..9c03862a8 --- /dev/null +++ b/test/views/fanout_limit_view.cpp @@ -0,0 +1,120 @@ +#include + +#include +#include +#include + +using namespace mockturtle; + +TEST_CASE( "test node replication", "[fanout_limit_view]" ) +{ + using node = mig_network::node; + using signal = mig_network::signal; + + fanout_limit_view_params ps{4u}; + fanout_limit_view lim_mig{ps}; + + signal const a = lim_mig.create_pi(); + signal const b = lim_mig.create_pi(); + signal const c = lim_mig.create_pi(); + + /* create a node */ + signal const f1 = lim_mig.create_maj( a, b, c ); + + /* make f1 very popular */ + lim_mig.create_and( f1, a ); + lim_mig.create_and( f1, b ); + lim_mig.create_and( f1, c ); + lim_mig.create_or( f1, a ); + + CHECK( lim_mig.num_gates() == 5u ); + + lim_mig.create_or( f1, b ); + lim_mig.create_or( f1, c ); + + CHECK( lim_mig.num_gates() == 8u ); + lim_mig.foreach_gate( [&]( node const& n ){ + CHECK( lim_mig.fanout_size( n ) <= 4u ); + }); +} + +TEST_CASE( "test rippled replication", "[fanout_limit_view]" ) +{ + using node = mig_network::node; + using signal = mig_network::signal; + + fanout_limit_view_params ps{4u}; + fanout_limit_view lim_mig{ps}; + + signal const a = lim_mig.create_pi(); + signal const b = lim_mig.create_pi(); + signal const c = lim_mig.create_pi(); + signal const d = lim_mig.create_pi(); + signal const e = lim_mig.create_pi(); + + /* create two nodes */ + signal const f1 = lim_mig.create_maj( a, b, c ); + signal const f2 = lim_mig.create_maj( d, f1, e ); + + /* make f1 and f2 popular */ + lim_mig.create_and( f1, a ); + lim_mig.create_and( f1, b ); + lim_mig.create_and( f1, c ); + + lim_mig.create_and( f2, a ); + lim_mig.create_and( f2, b ); + lim_mig.create_and( f2, c ); + lim_mig.create_or( f2, a ); + + CHECK( lim_mig.num_gates() == 9u ); + lim_mig.foreach_gate( [&]( node const& n ){ + CHECK( lim_mig.fanout_size( n ) <= 4u ); + }); + + /* +3 majority gates, because first f2 has to be replicated, and then also f1 */ + lim_mig.create_or( f2, b ); + + CHECK( lim_mig.num_gates() == 12u ); + lim_mig.foreach_gate( [&]( node const& n ){ + CHECK( lim_mig.fanout_size( n ) <= 4u ); + }); + + CHECK( lim_mig.fanout_size( lim_mig.get_node( f1 ) ) == 4u ); + CHECK( lim_mig.fanout_size( lim_mig.get_node( f2 ) ) == 4u ); +} + +TEST_CASE( "test duplicate fanout node", "[fanout_limit_view]" ) +{ + using node = mig_network::node; + using signal = mig_network::signal; + + fanout_limit_view_params ps{4u}; + fanout_limit_view lim_mig{ps}; + + signal const a = lim_mig.create_pi(); + signal const b = lim_mig.create_pi(); + signal const c = lim_mig.create_pi(); + + signal const f = lim_mig.create_maj( a, b, c ); + + /* only one node is needed for fanout up to 4 */ + lim_mig.create_po( f ); + lim_mig.create_po( f ); + lim_mig.create_po( f ); + lim_mig.create_po( f ); + + CHECK( lim_mig.num_gates() == 1u ); + CHECK( lim_mig.fanout_size( lim_mig.get_node( f ) ) == 4u ); + + /* afterward the node need to be replicated */ + lim_mig.create_po( f ); + lim_mig.create_po( f ); + lim_mig.create_po( f ); + lim_mig.create_po( f ); + + CHECK( lim_mig.num_gates() == 2u ); + + lim_mig.foreach_gate( [&]( node const& n ){ + CHECK( lim_mig.fanout_size( n ) <= 4u ); + }); +} From b80008a2871cd23be71773a4e44e8e8d1f0b6a2c Mon Sep 17 00:00:00 2001 From: Sonia Date: Mon, 26 Apr 2021 22:56:25 +0200 Subject: [PATCH 3/4] duplicate popular PIs in fanout_limit_view --- .../mockturtle/views/fanout_limit_view.hpp | 28 ++++++++++--- test/views/fanout_limit_view.cpp | 41 +++++++++++++++++++ 2 files changed, 64 insertions(+), 5 deletions(-) diff --git a/include/mockturtle/views/fanout_limit_view.hpp b/include/mockturtle/views/fanout_limit_view.hpp index 62fb24eb8..162591467 100644 --- a/include/mockturtle/views/fanout_limit_view.hpp +++ b/include/mockturtle/views/fanout_limit_view.hpp @@ -39,7 +39,9 @@ namespace mockturtle struct fanout_limit_view_params { - uint64_t fanout_limit{16}; + uint64_t fanout_limit{16u}; + + bool duplicate_pis{false}; }; @@ -57,12 +59,14 @@ class fanout_limit_view : public Ntk , ps( ps ) { static_assert( is_network_type_v, "Ntk is not a network type" ); + static_assert( std::is_same_v, "base type of Ntk is not mig_network" ); assert( ps.fanout_limit > 0u ); } uint32_t create_po( signal const& f, std::string const& name = std::string() ) { - if ( Ntk::is_maj( Ntk::get_node( f ) ) && Ntk::fanout_size( Ntk::get_node( f ) ) + 1 > ps.fanout_limit ) + if ( ( Ntk::is_maj( Ntk::get_node( f ) ) || ( ps.duplicate_pis && Ntk::is_pi( Ntk::get_node( f ) ) ) ) + && Ntk::fanout_size( Ntk::get_node( f ) ) + 1 > ps.fanout_limit ) { return Ntk::create_po( replicate_node( f ), name ); } @@ -75,9 +79,12 @@ class fanout_limit_view : public Ntk signal create_maj( signal const& a, signal const& b, signal const& c ) { std::array fanins; - fanins[0u] = ( Ntk::is_maj( Ntk::get_node( a ) ) && Ntk::fanout_size( Ntk::get_node( a ) ) > ps.fanout_limit - 1 ) ? replicate_node( a ) : a; - fanins[1u] = ( Ntk::is_maj( Ntk::get_node( b ) ) && Ntk::fanout_size( Ntk::get_node( b ) ) > ps.fanout_limit - 1 ) ? replicate_node( b ) : b; - fanins[2u] = ( Ntk::is_maj( Ntk::get_node( c ) ) && Ntk::fanout_size( Ntk::get_node( c ) ) > ps.fanout_limit - 1 ) ? replicate_node( c ) : c; + fanins[0u] = ( ( Ntk::is_maj( Ntk::get_node( a ) ) || ( ps.duplicate_pis && Ntk::is_pi( Ntk::get_node( a ) ) ) ) + && Ntk::fanout_size( Ntk::get_node( a ) ) > ps.fanout_limit - 1 ) ? replicate_node( a ) : a; + fanins[1u] = ( ( Ntk::is_maj( Ntk::get_node( b ) ) || ( ps.duplicate_pis && Ntk::is_pi( Ntk::get_node( b ) ) ) ) + && Ntk::fanout_size( Ntk::get_node( b ) ) > ps.fanout_limit - 1 ) ? replicate_node( b ) : b; + fanins[2u] = ( ( Ntk::is_maj( Ntk::get_node( c ) ) || ( ps.duplicate_pis && Ntk::is_pi( Ntk::get_node( c ) ) ) ) + && Ntk::fanout_size( Ntk::get_node( c ) ) > ps.fanout_limit - 1 ) ? replicate_node( c ) : c; return Ntk::create_maj( fanins[0u], fanins[1u], fanins[2u] ); } @@ -188,6 +195,17 @@ class fanout_limit_view : public Ntk } } + if ( Ntk::is_pi( n ) ) + { + assert( ps.duplicate_pis ); + const auto index = Ntk::_storage->nodes.size(); + auto& node = Ntk::_storage->nodes.emplace_back(); + node.children[0].data = node.children[1].data = node.children[2].data = ~static_cast( 0 ); + Ntk::_storage->inputs.emplace_back( index ); + replicas[n] = index; + return {index, 0}; + } + std::array fanins; Ntk::foreach_fanin( n, [&]( signal const& f, auto index ){ fanins[index] = ( Ntk::is_maj( Ntk::get_node( f ) ) && Ntk::fanout_size( Ntk::get_node( f ) ) > ps.fanout_limit - 1u ) ? replicate_node( f ) : f; diff --git a/test/views/fanout_limit_view.cpp b/test/views/fanout_limit_view.cpp index 9c03862a8..6544fe435 100644 --- a/test/views/fanout_limit_view.cpp +++ b/test/views/fanout_limit_view.cpp @@ -118,3 +118,44 @@ TEST_CASE( "test duplicate fanout node", "[fanout_limit_view]" ) CHECK( lim_mig.fanout_size( n ) <= 4u ); }); } + + +TEST_CASE( "popular PI", "[fanout_limit_view]" ) +{ + using node = mig_network::node; + using signal = mig_network::signal; + + fanout_limit_view_params ps{4u, true}; + fanout_limit_view lim_mig{ps}; + + signal const a = lim_mig.create_pi(); + signal const b = lim_mig.create_pi(); + signal const c = lim_mig.create_pi(); + signal const d = lim_mig.create_pi(); + + /* make `a` very popular */ + signal const f1 = lim_mig.create_maj( a, b, c ); + lim_mig.create_maj( a, b, d ); + lim_mig.create_maj( a, c, d ); + lim_mig.create_and( f1, a ); + lim_mig.create_or( f1, a ); + + CHECK( lim_mig.num_gates() == 5u ); + CHECK( lim_mig.num_pis() == 4u ); /* duplicated PI does not increase `num_pis` */ + uint32_t count{0u}; + lim_mig.foreach_pi( [&]( node const& n ){ + (void)n; + ++count; + }); + CHECK( count == 4u ); /* duplicated PI is iterated only once in `foreach_pi` */ + + /* 5 gates + 1 constant + 4 PIs + 1 duplicated PI */ + CHECK( lim_mig.size() == 11u ); + + count = 0u; + lim_mig.foreach_node( [&]( node const& n ){ + ++count; + CHECK( lim_mig.fanout_size( n ) <= 4u ); + }); + CHECK( count == 11u ); /* duplicated PI is iterated twice in `foreach_node` */ +} From 08e728e9f6990cc682aaee620705a57e46f6f6a3 Mon Sep 17 00:00:00 2001 From: Sonia Date: Tue, 27 Apr 2021 17:21:19 +0200 Subject: [PATCH 4/4] Revert "duplicate popular PIs in fanout_limit_view" This reverts commit b80008a2871cd23be71773a4e44e8e8d1f0b6a2c. --- .../mockturtle/views/fanout_limit_view.hpp | 28 +++---------- test/views/fanout_limit_view.cpp | 41 ------------------- 2 files changed, 5 insertions(+), 64 deletions(-) diff --git a/include/mockturtle/views/fanout_limit_view.hpp b/include/mockturtle/views/fanout_limit_view.hpp index 162591467..62fb24eb8 100644 --- a/include/mockturtle/views/fanout_limit_view.hpp +++ b/include/mockturtle/views/fanout_limit_view.hpp @@ -39,9 +39,7 @@ namespace mockturtle struct fanout_limit_view_params { - uint64_t fanout_limit{16u}; - - bool duplicate_pis{false}; + uint64_t fanout_limit{16}; }; @@ -59,14 +57,12 @@ class fanout_limit_view : public Ntk , ps( ps ) { static_assert( is_network_type_v, "Ntk is not a network type" ); - static_assert( std::is_same_v, "base type of Ntk is not mig_network" ); assert( ps.fanout_limit > 0u ); } uint32_t create_po( signal const& f, std::string const& name = std::string() ) { - if ( ( Ntk::is_maj( Ntk::get_node( f ) ) || ( ps.duplicate_pis && Ntk::is_pi( Ntk::get_node( f ) ) ) ) - && Ntk::fanout_size( Ntk::get_node( f ) ) + 1 > ps.fanout_limit ) + if ( Ntk::is_maj( Ntk::get_node( f ) ) && Ntk::fanout_size( Ntk::get_node( f ) ) + 1 > ps.fanout_limit ) { return Ntk::create_po( replicate_node( f ), name ); } @@ -79,12 +75,9 @@ class fanout_limit_view : public Ntk signal create_maj( signal const& a, signal const& b, signal const& c ) { std::array fanins; - fanins[0u] = ( ( Ntk::is_maj( Ntk::get_node( a ) ) || ( ps.duplicate_pis && Ntk::is_pi( Ntk::get_node( a ) ) ) ) - && Ntk::fanout_size( Ntk::get_node( a ) ) > ps.fanout_limit - 1 ) ? replicate_node( a ) : a; - fanins[1u] = ( ( Ntk::is_maj( Ntk::get_node( b ) ) || ( ps.duplicate_pis && Ntk::is_pi( Ntk::get_node( b ) ) ) ) - && Ntk::fanout_size( Ntk::get_node( b ) ) > ps.fanout_limit - 1 ) ? replicate_node( b ) : b; - fanins[2u] = ( ( Ntk::is_maj( Ntk::get_node( c ) ) || ( ps.duplicate_pis && Ntk::is_pi( Ntk::get_node( c ) ) ) ) - && Ntk::fanout_size( Ntk::get_node( c ) ) > ps.fanout_limit - 1 ) ? replicate_node( c ) : c; + fanins[0u] = ( Ntk::is_maj( Ntk::get_node( a ) ) && Ntk::fanout_size( Ntk::get_node( a ) ) > ps.fanout_limit - 1 ) ? replicate_node( a ) : a; + fanins[1u] = ( Ntk::is_maj( Ntk::get_node( b ) ) && Ntk::fanout_size( Ntk::get_node( b ) ) > ps.fanout_limit - 1 ) ? replicate_node( b ) : b; + fanins[2u] = ( Ntk::is_maj( Ntk::get_node( c ) ) && Ntk::fanout_size( Ntk::get_node( c ) ) > ps.fanout_limit - 1 ) ? replicate_node( c ) : c; return Ntk::create_maj( fanins[0u], fanins[1u], fanins[2u] ); } @@ -195,17 +188,6 @@ class fanout_limit_view : public Ntk } } - if ( Ntk::is_pi( n ) ) - { - assert( ps.duplicate_pis ); - const auto index = Ntk::_storage->nodes.size(); - auto& node = Ntk::_storage->nodes.emplace_back(); - node.children[0].data = node.children[1].data = node.children[2].data = ~static_cast( 0 ); - Ntk::_storage->inputs.emplace_back( index ); - replicas[n] = index; - return {index, 0}; - } - std::array fanins; Ntk::foreach_fanin( n, [&]( signal const& f, auto index ){ fanins[index] = ( Ntk::is_maj( Ntk::get_node( f ) ) && Ntk::fanout_size( Ntk::get_node( f ) ) > ps.fanout_limit - 1u ) ? replicate_node( f ) : f; diff --git a/test/views/fanout_limit_view.cpp b/test/views/fanout_limit_view.cpp index 6544fe435..9c03862a8 100644 --- a/test/views/fanout_limit_view.cpp +++ b/test/views/fanout_limit_view.cpp @@ -118,44 +118,3 @@ TEST_CASE( "test duplicate fanout node", "[fanout_limit_view]" ) CHECK( lim_mig.fanout_size( n ) <= 4u ); }); } - - -TEST_CASE( "popular PI", "[fanout_limit_view]" ) -{ - using node = mig_network::node; - using signal = mig_network::signal; - - fanout_limit_view_params ps{4u, true}; - fanout_limit_view lim_mig{ps}; - - signal const a = lim_mig.create_pi(); - signal const b = lim_mig.create_pi(); - signal const c = lim_mig.create_pi(); - signal const d = lim_mig.create_pi(); - - /* make `a` very popular */ - signal const f1 = lim_mig.create_maj( a, b, c ); - lim_mig.create_maj( a, b, d ); - lim_mig.create_maj( a, c, d ); - lim_mig.create_and( f1, a ); - lim_mig.create_or( f1, a ); - - CHECK( lim_mig.num_gates() == 5u ); - CHECK( lim_mig.num_pis() == 4u ); /* duplicated PI does not increase `num_pis` */ - uint32_t count{0u}; - lim_mig.foreach_pi( [&]( node const& n ){ - (void)n; - ++count; - }); - CHECK( count == 4u ); /* duplicated PI is iterated only once in `foreach_pi` */ - - /* 5 gates + 1 constant + 4 PIs + 1 duplicated PI */ - CHECK( lim_mig.size() == 11u ); - - count = 0u; - lim_mig.foreach_node( [&]( node const& n ){ - ++count; - CHECK( lim_mig.fanout_size( n ) <= 4u ); - }); - CHECK( count == 11u ); /* duplicated PI is iterated twice in `foreach_node` */ -}