diff --git a/include/mockturtle/algorithms/aig_resub.hpp b/include/mockturtle/algorithms/aig_resub.hpp index cbcfef367..1c63e42b2 100644 --- a/include/mockturtle/algorithms/aig_resub.hpp +++ b/include/mockturtle/algorithms/aig_resub.hpp @@ -740,7 +740,7 @@ void aig_resubstitution( Ntk& ntk, resubstitution_params const& ps = {}, resubst static_assert( has_value_v, "Ntk does not implement the has_value method" ); static_assert( has_visited_v, "Ntk does not implement the has_visited method" ); - using resub_view_t = fanout_view2>; + using resub_view_t = fanout_view>; depth_view depth_view{ntk}; resub_view_t resub_view{depth_view}; diff --git a/include/mockturtle/algorithms/cut_rewriting.hpp b/include/mockturtle/algorithms/cut_rewriting.hpp index 68b657f5c..29d2409d0 100644 --- a/include/mockturtle/algorithms/cut_rewriting.hpp +++ b/include/mockturtle/algorithms/cut_rewriting.hpp @@ -47,7 +47,7 @@ #include "../utils/progress_bar.hpp" #include "../utils/stopwatch.hpp" #include "../views/cut_view.hpp" -#include "../views/fanout_view2.hpp" +#include "../views/fanout_view.hpp" #include "cut_enumeration.hpp" #include "detail/mffc_utils.hpp" #include "dont_cares.hpp" @@ -690,10 +690,10 @@ void cut_rewriting( Ntk& ntk, RewritingFn&& rewriting_fn, cut_rewriting_params c } else { - fanout_view2_params fvps; + fanout_view_params fvps; fvps.update_on_delete = false; - fanout_view2 ntk_fo{ntk, fvps}; - detail::cut_rewriting_impl, RewritingFn, NodeCostFn> p( ntk_fo, rewriting_fn, ps, st, cost_fn ); + fanout_view ntk_fo{ntk, fvps}; + detail::cut_rewriting_impl, RewritingFn, NodeCostFn> p( ntk_fo, rewriting_fn, ps, st, cost_fn ); p.run(); } diff --git a/include/mockturtle/algorithms/mig_resub.hpp b/include/mockturtle/algorithms/mig_resub.hpp index 216d19ca5..db77b0cd3 100644 --- a/include/mockturtle/algorithms/mig_resub.hpp +++ b/include/mockturtle/algorithms/mig_resub.hpp @@ -665,7 +665,7 @@ void mig_resubstitution( Ntk& ntk, resubstitution_params const& ps = {}, resubst static_assert( has_value_v, "Ntk does not implement the has_value method" ); static_assert( has_visited_v, "Ntk does not implement the has_visited method" ); - using resub_view_t = fanout_view2>; + using resub_view_t = fanout_view>; depth_view depth_view{ntk}; resub_view_t resub_view{depth_view}; diff --git a/include/mockturtle/algorithms/resubstitution.hpp b/include/mockturtle/algorithms/resubstitution.hpp index e833e96ce..4ceadecdd 100644 --- a/include/mockturtle/algorithms/resubstitution.hpp +++ b/include/mockturtle/algorithms/resubstitution.hpp @@ -36,7 +36,7 @@ #include "../utils/progress_bar.hpp" #include "../utils/stopwatch.hpp" #include "../views/depth_view.hpp" -#include "../views/fanout_view2.hpp" +#include "../views/fanout_view.hpp" #include "dont_cares.hpp" #include "reconv_cut2.hpp" @@ -818,7 +818,7 @@ void resubstitution( Ntk& ntk, resubstitution_params const& ps = {}, resubstitut static_assert( has_value_v, "Ntk does not implement the has_value method" ); static_assert( has_visited_v, "Ntk does not implement the has_visited method" ); - using resub_view_t = fanout_view2>; + using resub_view_t = fanout_view>; depth_view depth_view{ntk}; resub_view_t resub_view{depth_view}; diff --git a/include/mockturtle/algorithms/xag_resub_withDC.hpp b/include/mockturtle/algorithms/xag_resub_withDC.hpp index 7fdd2fd83..3988989fb 100644 --- a/include/mockturtle/algorithms/xag_resub_withDC.hpp +++ b/include/mockturtle/algorithms/xag_resub_withDC.hpp @@ -956,7 +956,7 @@ void resubstitution_minmc_withDC( Ntk& ntk, resubstitution_params const& ps = {} static_assert( has_value_v, "Ntk does not implement the has_value method" ); static_assert( has_visited_v, "Ntk does not implement the has_visited method" ); - using resub_view_t = fanout_view2>; + using resub_view_t = fanout_view>; depth_view depth_view{ntk}; resub_view_t resub_view{depth_view}; diff --git a/include/mockturtle/mockturtle.hpp b/include/mockturtle/mockturtle.hpp index 24e149d7f..889aff5c4 100644 --- a/include/mockturtle/mockturtle.hpp +++ b/include/mockturtle/mockturtle.hpp @@ -112,7 +112,7 @@ #include "mockturtle/views/immutable_view.hpp" #include "mockturtle/views/topo_view.hpp" #include "mockturtle/views/window_view.hpp" -#include "mockturtle/views/fanout_view2.hpp" +#include "mockturtle/views/fanout_view.hpp" #include "mockturtle/views/names_view.hpp" #include "mockturtle/views/mapping_view.hpp" #include "mockturtle/views/fanout_view.hpp" diff --git a/include/mockturtle/views/fanout_view.hpp b/include/mockturtle/views/fanout_view.hpp index e6c966e43..2a6d0feaf 100644 --- a/include/mockturtle/views/fanout_view.hpp +++ b/include/mockturtle/views/fanout_view.hpp @@ -33,6 +33,7 @@ #pragma once #include +#include #include #include "../traits.hpp" @@ -43,6 +44,13 @@ namespace mockturtle { +struct fanout_view_params +{ + bool update_on_add{true}; + bool update_on_modified{true}; + bool update_on_delete{true}; +}; + /*! \brief Implements `foreach_fanout` methods for networks. * * This view computes the fanout of each node of the network. @@ -64,8 +72,9 @@ template class fanout_view : public Ntk { public: - fanout_view( Ntk const& ntk ) : Ntk( ntk ) + fanout_view( Ntk const& ntk, fanout_view_params const& ps = {} ) : Ntk( ntk ) { + (void)ps; } }; @@ -77,13 +86,46 @@ class fanout_view : public Ntk using node = typename Ntk::node; using signal = typename Ntk::signal; - fanout_view( Ntk const& ntk ) : Ntk( ntk ), _fanout( ntk ) + fanout_view( Ntk const& ntk, fanout_view_params const& ps = {} ) : Ntk( ntk ), _fanout( ntk ), _ps( ps ) { static_assert( is_network_type_v, "Ntk is not a network type" ); static_assert( has_foreach_node_v, "Ntk does not implement the foreach_node method" ); static_assert( has_foreach_fanin_v, "Ntk does not implement the foreach_fanin method" ); update_fanout(); + + if ( _ps.update_on_add ) + { + Ntk::events().on_add.push_back( [this]( auto const& n ) { + _fanout.resize(); + Ntk::foreach_fanin( n, [&, this]( auto const& f ) { + _fanout[f].push_back( n ); + } ); + } ); + } + + if ( _ps.update_on_modified ) + { + Ntk::events().on_modified.push_back( [this]( auto const& n, auto const& previous ) { + (void)previous; + for ( auto const& f : previous ) { + _fanout[f].erase( std::remove( _fanout[f].begin(), _fanout[f].end(), n ), _fanout[f].end() ); + } + Ntk::foreach_fanin( n, [&, this]( auto const& f ) { + _fanout[f].push_back( n ); + } ); + } ); + } + + if ( _ps.update_on_delete ) + { + Ntk::events().on_delete.push_back( [this]( auto const& n ) { + _fanout[n].clear(); + Ntk::foreach_fanin( n, [&, this]( auto const& f ) { + _fanout[f].erase( std::remove( _fanout[f].begin(), _fanout[f].end(), n ), _fanout[f].end() ); + } ); + } ); + } } template @@ -98,50 +140,36 @@ class fanout_view : public Ntk compute_fanout(); } - void resize_fanout() - { - _fanout.resize(); - } - std::vector fanout( node const& n ) const /* deprecated */ { - return _fanout[ n ]; + return _fanout[n]; } - void set_fanout( node const& n, std::vector const& fanout ) + void substitute_node( node const& old_node, signal const& new_signal ) { - _fanout[ n ] = fanout; - } - - void add_fanout( node const& n, node const& p ) - { - _fanout[ n ].emplace_back( p ); - } - - void remove_fanout( node const& n, node const& p ) - { - auto &f = _fanout[ n ]; - f.erase( std::remove( f.begin(), f.end(), p ), f.end() ); - } - - void substitute_node_of_parents( std::vector const& parents, node const& old_node, signal const& new_signal ) /* deprecated */ - { - Ntk::substitute_node_of_parents( parents, old_node, new_signal ); - - std::vector old_node_fanout = _fanout[ old_node ]; - std::sort( old_node_fanout.begin(), old_node_fanout.end() ); - - std::vector parents_copy( parents ); - std::sort( parents_copy.begin(), parents_copy.end() ); - - _fanout[ old_node ] = {}; - - std::vector intersection; - std::set_intersection( parents_copy.begin(), parents_copy.end(), old_node_fanout.begin(), old_node_fanout.end(), - std::back_inserter( intersection ) ); - - resize_fanout(); - set_fanout( this->get_node( new_signal ), intersection ); + std::stack> to_substitute; + to_substitute.push( {old_node, new_signal} ); + + while ( !to_substitute.empty() ) + { + const auto [_old, _new] = to_substitute.top(); + to_substitute.pop(); + + const auto parents = _fanout[_old]; + for ( auto n : parents ) + { + if ( const auto repl = Ntk::replace_in_node( n, _old, _new ); repl ) + { + to_substitute.push( *repl ); + } + } + + /* check outputs */ + Ntk::replace_in_outputs( _old, _new ); + + /* reset fan-in of old node */ + Ntk::take_out_node( _old ); + } } private: @@ -151,7 +179,7 @@ class fanout_view : public Ntk this->foreach_gate( [&]( auto const& n ){ this->foreach_fanin( n, [&]( auto const& c ){ - auto& fanout = _fanout[ c ]; + auto& fanout = _fanout[c]; if ( std::find( fanout.begin(), fanout.end(), n ) == fanout.end() ) { fanout.push_back( n ); @@ -161,9 +189,10 @@ class fanout_view : public Ntk } node_map, Ntk> _fanout; + fanout_view_params _ps; }; template -fanout_view(T const&) -> fanout_view; +fanout_view( T const&, fanout_view_params const& ps = {} ) -> fanout_view; } // namespace mockturtle diff --git a/include/mockturtle/views/fanout_view2.hpp b/include/mockturtle/views/fanout_view2.hpp deleted file mode 100644 index 981081f9a..000000000 --- a/include/mockturtle/views/fanout_view2.hpp +++ /dev/null @@ -1,198 +0,0 @@ -/* mockturtle: C++ logic network library - * Copyright (C) 2018-2019 EPFL - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -/*! - \file fanout_view2.hpp - \brief Implements fanout for a network - - \author Heinz Riener -*/ - -#pragma once - -#include -#include -#include - -#include "../traits.hpp" -#include "../networks/detail/foreach.hpp" -#include "../utils/node_map.hpp" -#include "immutable_view.hpp" - -namespace mockturtle -{ - -struct fanout_view2_params -{ - bool update_on_add{true}; - bool update_on_modified{true}; - bool update_on_delete{true}; -}; - -/*! \brief Implements `foreach_fanout` methods for networks. - * - * This view computes the fanout of each node of the network. - * It implements the network interface method `foreach_fanout`. The - * fanout are computed at construction and can be recomputed by - * calling the `update_fanout` method. - * - * **Required network functions:** - * - `foreach_node` - * - `foreach_fanin` - * - */ -template> -class fanout_view2 -{ -}; - -template -class fanout_view2 : public Ntk -{ -public: - fanout_view2( Ntk const& ntk, fanout_view2_params const& ps = {} ) : Ntk( ntk ) - { - (void)ps; - } -}; - -template -class fanout_view2 : public Ntk -{ -public: - using storage = typename Ntk::storage; - using node = typename Ntk::node; - using signal = typename Ntk::signal; - - fanout_view2( Ntk const& ntk, fanout_view2_params const& ps = {} ) : Ntk( ntk ), _fanout( ntk ), _ps( ps ) - { - static_assert( is_network_type_v, "Ntk is not a network type" ); - static_assert( has_foreach_node_v, "Ntk does not implement the foreach_node method" ); - static_assert( has_foreach_fanin_v, "Ntk does not implement the foreach_fanin method" ); - - update_fanout(); - - if ( _ps.update_on_add ) - { - Ntk::events().on_add.push_back( [this]( auto const& n ) { - _fanout.resize(); - Ntk::foreach_fanin( n, [&, this]( auto const& f ) { - _fanout[f].push_back( n ); - } ); - } ); - } - - if ( _ps.update_on_modified ) - { - Ntk::events().on_modified.push_back( [this]( auto const& n, auto const& previous ) { - (void)previous; - for ( auto const& f : previous ) { - _fanout[f].erase( std::remove( _fanout[f].begin(), _fanout[f].end(), n ), _fanout[f].end() ); - } - Ntk::foreach_fanin( n, [&, this]( auto const& f ) { - _fanout[f].push_back( n ); - } ); - } ); - } - - if ( _ps.update_on_delete ) - { - Ntk::events().on_delete.push_back( [this]( auto const& n ) { - _fanout[n].clear(); - Ntk::foreach_fanin( n, [&, this]( auto const& f ) { - _fanout[f].erase( std::remove( _fanout[f].begin(), _fanout[f].end(), n ), _fanout[f].end() ); - } ); - } ); - } - } - - template - void foreach_fanout( node const& n, Fn&& fn ) const - { - assert( n < this->size() ); - detail::foreach_element( _fanout[n].begin(), _fanout[n].end(), fn ); - } - - void update_fanout() - { - compute_fanout(); - } - - std::vector fanout( node const& n ) const /* deprecated */ - { - return _fanout[ n ]; - } - - void substitute_node( node const& old_node, signal const& new_signal ) - { - std::stack> to_substitute; - to_substitute.push( {old_node, new_signal} ); - - while ( !to_substitute.empty() ) - { - const auto [_old, _new] = to_substitute.top(); - to_substitute.pop(); - - const auto parents = _fanout[_old]; - for ( auto n : parents ) - { - if ( const auto repl = Ntk::replace_in_node( n, _old, _new ); repl ) - { - to_substitute.push( *repl ); - } - } - - /* check outputs */ - Ntk::replace_in_outputs( _old, _new ); - - // reset fan-in of old node - Ntk::take_out_node( _old ); - } - } - -private: - void compute_fanout() - { - _fanout.reset(); - - this->foreach_gate( [&]( auto const& n ){ - this->foreach_fanin( n, [&]( auto const& c ){ - auto& fanout = _fanout[ c ]; - if ( std::find( fanout.begin(), fanout.end(), n ) == fanout.end() ) - { - fanout.push_back( n ); - } - }); - }); - } - - node_map, Ntk> _fanout; - fanout_view2_params _ps; -}; - -template -fanout_view2(T const&, fanout_view2_params const& ps = {}) -> fanout_view2; - -} // namespace mockturtle diff --git a/include/mockturtle/views/window_view.hpp b/include/mockturtle/views/window_view.hpp index c3c589dd5..31c6606e9 100644 --- a/include/mockturtle/views/window_view.hpp +++ b/include/mockturtle/views/window_view.hpp @@ -41,7 +41,6 @@ #include "../traits.hpp" #include "../networks/detail/foreach.hpp" -#include "../views/fanout_view.hpp" #include "immutable_view.hpp" namespace mockturtle diff --git a/test/algorithms/resubstitution.cpp b/test/algorithms/resubstitution.cpp index 19a85000e..8b530be97 100644 --- a/test/algorithms/resubstitution.cpp +++ b/test/algorithms/resubstitution.cpp @@ -2,7 +2,6 @@ #include #include -#include #include #include #include @@ -37,8 +36,8 @@ TEST_CASE( "Resubstitution of AIG", "[resubstitution]" ) const auto tt = simulate>( aig )[0]; CHECK( tt._bits == 0x8 ); - using view_t = depth_view>; - fanout_view2 fanout_view{aig}; + using view_t = depth_view>; + fanout_view fanout_view{aig}; view_t resub_view{fanout_view}; aig_resubstitution( resub_view ); @@ -74,8 +73,8 @@ TEST_CASE( "Resubstitution of MIG", "[resubstitution]" ) const auto tt = simulate>( mig )[0]; CHECK( tt._bits == 0xe8 ); - using view_t = depth_view>; - fanout_view2 fanout_view{mig}; + using view_t = depth_view>; + fanout_view fanout_view{mig}; view_t resub_view{fanout_view}; mig_resubstitution( resub_view ); @@ -112,8 +111,8 @@ TEST_CASE( "Resubstitution of XAG to minimize ANDs", "[resubstitution]" ) resubstitution_params ps; - using view_t = depth_view>; - fanout_view2 fanout_view{xag}; + using view_t = depth_view>; + fanout_view fanout_view{xag}; view_t resub_view{fanout_view}; resubstitution_minmc_withDC( resub_view , ps);