From 16b15bb7e7cb4fea9edccd4af6d6f728446c979b Mon Sep 17 00:00:00 2001 From: aletempiac Date: Mon, 23 Sep 2024 16:57:07 +0200 Subject: [PATCH 1/2] Adding XAG resub and improving AIG resub --- docs/algorithms/resubstitution.rst | 2 +- docs/changelog.rst | 2 + experiments/aig_resubstitution.cpp | 8 +- experiments/xag_resubstitution.cpp | 77 +++++++ include/mockturtle/algorithms/aig_resub.hpp | 174 ++++++++++++++ .../algorithms/resyn_engines/xag_resyn.hpp | 15 ++ include/mockturtle/algorithms/xag_resub.hpp | 216 ++++++++++++++++++ test/algorithms/resubstitution.cpp | 115 ++++++++++ 8 files changed, 606 insertions(+), 3 deletions(-) create mode 100644 experiments/xag_resubstitution.cpp create mode 100644 include/mockturtle/algorithms/xag_resub.hpp diff --git a/docs/algorithms/resubstitution.rst b/docs/algorithms/resubstitution.rst index 6e80571d4..7140ad8e0 100644 --- a/docs/algorithms/resubstitution.rst +++ b/docs/algorithms/resubstitution.rst @@ -7,7 +7,7 @@ Several resubstitution algorithms are implemented and can be called directly, in - ``default_resubstitution`` does functional reduction within a window. -- ``aig_resubstitution``, ``mig_resubstitution`` and ``xmg_resubstitution`` do window-based resubstitution in the corresponding network types. +- ``aig_resubstitution``, ``aig_resubstitution2``, ``xag_resubstitution``, ``mig_resubstitution``, ``mig_resubstitution2``, and ``xmg_resubstitution`` do window-based resubstitution in the corresponding network types. - ``resubstitution_minmc_withDC`` minimizes multiplicative complexity in XAGs with window-based resubstitution. diff --git a/docs/changelog.rst b/docs/changelog.rst index 42c41111c..f5dd5874e 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -19,6 +19,7 @@ v0.4 (not yet released) - Adding a new network type to represent multi-output gates (`block_network`) `#623 `_ * Algorithms: - AIG balancing (`aig_balance`) `#580 `_ + - AIG resubstitution (`xag_resubstitution2`) `#658 `_ - Cost-generic resubstitution (`cost_generic_resub`) `#554 `_ - Cost aware resynthesis solver (`cost_resyn`) `#554 `_ - Resynthesis based on SOP factoring (`sop_factoring`) `#579 `_ @@ -38,6 +39,7 @@ v0.4 (not yet released) - Adding circuit extraction of half and full adders (`extract_adders`) `#623 `_ - Adding don't care support in rewriting (`map`, `rewrite`) `#623 `_ - XAG balancing (`xag_balance`) `#627 `_ + - XAG resubstitution (`xag_resubstitution`) `#658 `_ * I/O: - Write gates to GENLIB file (`write_genlib`) `#606 `_ * Views: diff --git a/experiments/aig_resubstitution.cpp b/experiments/aig_resubstitution.cpp index d3f947210..825879a2a 100644 --- a/experiments/aig_resubstitution.cpp +++ b/experiments/aig_resubstitution.cpp @@ -33,6 +33,8 @@ #include #include #include +#include +#include #include @@ -56,11 +58,13 @@ int main() resubstitution_stats st; ps.max_pis = 8u; - ps.max_inserts = 1u; + ps.max_inserts = 2u; ps.progress = false; const uint32_t size_before = aig.num_gates(); - aig_resubstitution( aig, ps, &st ); + depth_view depth_aig{ aig }; + fanout_view fanout_aig{ depth_aig }; + aig_resubstitution2( fanout_aig, ps, &st ); aig = cleanup_dangling( aig ); diff --git a/experiments/xag_resubstitution.cpp b/experiments/xag_resubstitution.cpp new file mode 100644 index 000000000..d7fe6fc6e --- /dev/null +++ b/experiments/xag_resubstitution.cpp @@ -0,0 +1,77 @@ +/* mockturtle: C++ logic network library + * Copyright (C) 2018-2024 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +int main() +{ + using namespace experiments; + using namespace mockturtle; + + experiment + exp( "xag_resubstitution", "benchmark", "size_before", "size_after", "runtime", "equivalent" ); + + for ( auto const& benchmark : epfl_benchmarks() ) + { + fmt::print( "[i] processing {}\n", benchmark ); + + xag_network xag; + if ( lorina::read_aiger( benchmark_path( benchmark ), aiger_reader( xag ) ) != lorina::return_code::success ) + { + continue; + } + + resubstitution_params ps; + resubstitution_stats st; + ps.max_pis = 8u; + ps.max_inserts = 1u; + ps.progress = false; + + depth_view depth_xag{ xag }; + fanout_view fanout_xag{ depth_xag }; + + uint32_t const size_before = fanout_xag.num_gates(); + xag_resubstitution( fanout_xag, ps, &st ); + xag = cleanup_dangling( xag ); + + bool const cec = benchmark == "hyp" ? true : abc_cec( fanout_xag, benchmark ); + exp( benchmark, size_before, xag.num_gates(), to_seconds( st.time_total ), cec ); + } + + exp.save(); + exp.table(); + + return 0; +} \ No newline at end of file diff --git a/include/mockturtle/algorithms/aig_resub.hpp b/include/mockturtle/algorithms/aig_resub.hpp index d7eea28c5..ac6ad5d70 100644 --- a/include/mockturtle/algorithms/aig_resub.hpp +++ b/include/mockturtle/algorithms/aig_resub.hpp @@ -27,6 +27,7 @@ \file aig_resub.hpp \brief Resubstitution + \author Alessandro Tempia Calvino \author Eleonora Testa \author Heinz Riener \author Mathias Soeken @@ -36,7 +37,10 @@ #pragma once #include "../networks/aig.hpp" +#include "../utils/index_list.hpp" +#include "../utils/truth_table_utils.hpp" #include "resubstitution.hpp" +#include "resyn_engines/xag_resyn.hpp" namespace mockturtle { @@ -731,6 +735,90 @@ struct aig_resub_functor binate_divisors bdivs; }; /* aig_resub_functor */ +struct aig_resyn_resub_stats +{ + /*! \brief Time for finding dependency function. */ + stopwatch<>::duration time_compute_function{ 0 }; + + /*! \brief Number of found solutions. */ + uint32_t num_success{ 0 }; + + /*! \brief Number of times that no solution can be found. */ + uint32_t num_fail{ 0 }; + + void report() const + { + fmt::print( "[i] \n" ); + fmt::print( "[i] #solution = {:6d}\n", num_success ); + fmt::print( "[i] #invoke = {:6d}\n", num_success + num_fail ); + fmt::print( "[i] engine time: {:>5.2f} secs\n", to_seconds( time_compute_function ) ); + } +}; /* aig_resyn_resub_stats */ + +/*! \brief Interfacing resubstitution functor with AIG resynthesis engines for `window_based_resub_engine`. + */ +template>> +struct aig_resyn_functor +{ +public: + using node = aig_network::node; + using signal = aig_network::signal; + using stats = aig_resyn_resub_stats; + using TT = typename ResynEngine::truth_table_t; + + static_assert( std::is_same_v, "truth table type of the simulator does not match" ); + +public: + explicit aig_resyn_functor( Ntk& ntk, Simulator const& sim, std::vector const& divs, uint32_t num_divs, stats& st ) + : ntk( ntk ), sim( sim ), tts( ntk ), divs( divs ), st( st ) + { + assert( divs.size() == num_divs ); + (void)num_divs; + div_signals.reserve( divs.size() ); + } + + std::optional operator()( node const& root, TTcare care, uint32_t required, uint32_t max_inserts, uint32_t potential_gain, uint32_t& real_gain ) + { + (void)required; + TT target = sim.get_tt( sim.get_phase( root ) ? !ntk.make_signal( root ) : ntk.make_signal( root ) ); + TT care_transformed = target.construct(); + care_transformed = care; + + typename ResynEngine::stats st_eng; + ResynEngine engine( st_eng ); + for ( auto const& d : divs ) + { + div_signals.emplace_back( sim.get_phase( d ) ? !ntk.make_signal( d ) : ntk.make_signal( d ) ); + tts[d] = sim.get_tt( ntk.make_signal( d ) ); + } + + auto const res = call_with_stopwatch( st.time_compute_function, [&]() { + return engine( target, care_transformed, std::begin( divs ), std::end( divs ), tts, std::min( potential_gain - 1, max_inserts ) ); + } ); + if ( res ) + { + ++st.num_success; + signal ret; + real_gain = potential_gain - ( *res ).num_gates(); + insert( ntk, div_signals.begin(), div_signals.end(), *res, [&]( signal const& s ) { ret = s; } ); + return ret; + } + else + { + ++st.num_fail; + return std::nullopt; + } + } + +private: + Ntk& ntk; + Simulator const& sim; + unordered_node_map tts; + std::vector const& divs; + std::vector div_signals; + stats& st; +}; /* aig_resyn_functor */ + template void aig_resubstitution( Ntk& ntk, resubstitution_params const& ps = {}, resubstitution_stats* pst = nullptr ) { @@ -809,4 +897,90 @@ void aig_resubstitution( Ntk& ntk, resubstitution_params const& ps = {}, resubst } } +/*! \brief AIG-specific resubstitution algorithm. + * + * This algorithms iterates over each node, creates a + * reconvergence-driven cut, and attempts to re-express the node's + * function using existing nodes from the cut. Node which are no + * longer used (including nodes in their transitive fanins) can then + * be removed. The objective is to reduce the size of the network as + * much as possible while maintaining the global input-output + * functionality. + * + * **Required network functions:** + * + * - `clear_values` + * - `fanout_size` + * - `foreach_fanin` + * - `foreach_fanout` + * - `foreach_gate` + * - `foreach_node` + * - `get_constant` + * - `get_node` + * - `is_complemented` + * - `is_pi` + * - `level` + * - `make_signal` + * - `set_value` + * - `set_visited` + * - `size` + * - `substitute_node` + * - `value` + * - `visited` + * + * \param ntk A network type derived from aig_network + * \param ps Resubstitution parameters + * \param pst Resubstitution statistics + */ +template +void aig_resubstitution2( Ntk& ntk, resubstitution_params const& ps = {}, resubstitution_stats* pst = nullptr ) +{ + static_assert( is_network_type_v, "Ntk is not a network type" ); + static_assert( std::is_same_v, "Network type is not aig_network" ); + + static_assert( has_clear_values_v, "Ntk does not implement the clear_values method" ); + static_assert( has_fanout_size_v, "Ntk does not implement the fanout_size method" ); + static_assert( has_foreach_fanin_v, "Ntk does not implement the foreach_fanin method" ); + static_assert( has_foreach_gate_v, "Ntk does not implement the foreach_gate method" ); + static_assert( has_foreach_node_v, "Ntk does not implement the foreach_node method" ); + static_assert( has_get_constant_v, "Ntk does not implement the get_constant method" ); + static_assert( has_get_node_v, "Ntk does not implement the get_node method" ); + static_assert( has_is_complemented_v, "Ntk does not implement the is_complemented method" ); + static_assert( has_is_pi_v, "Ntk does not implement the is_pi method" ); + static_assert( has_make_signal_v, "Ntk does not implement the make_signal method" ); + static_assert( has_set_value_v, "Ntk does not implement the set_value method" ); + static_assert( has_set_visited_v, "Ntk does not implement the set_visited method" ); + static_assert( has_size_v, "Ntk does not implement the has_size method" ); + static_assert( has_substitute_node_v, "Ntk does not implement the has substitute_node method" ); + 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" ); + static_assert( has_level_v, "Ntk does not implement the level method" ); + static_assert( has_foreach_fanout_v, "Ntk does not implement the foreach_fanout method" ); + + using truthtable_t = kitty::dynamic_truth_table; + using truthtable_dc_t = kitty::dynamic_truth_table; + using functor_t = aig_resyn_functor, truthtable_dc_t>; + + using resub_impl_t = detail::resubstitution_impl>; + + resubstitution_stats st; + typename resub_impl_t::engine_st_t engine_st; + typename resub_impl_t::collector_st_t collector_st; + + resub_impl_t p( ntk, ps, st, engine_st, collector_st ); + p.run(); + + if ( ps.verbose ) + { + st.report(); + collector_st.report(); + engine_st.report(); + } + + if ( pst ) + { + *pst = st; + } +} + } /* namespace mockturtle */ \ No newline at end of file diff --git a/include/mockturtle/algorithms/resyn_engines/xag_resyn.hpp b/include/mockturtle/algorithms/resyn_engines/xag_resyn.hpp index ad39d8431..ae01942ef 100644 --- a/include/mockturtle/algorithms/resyn_engines/xag_resyn.hpp +++ b/include/mockturtle/algorithms/resyn_engines/xag_resyn.hpp @@ -99,6 +99,13 @@ struct aig_resyn_static_params_default : public xag_resyn_static_params_default< static constexpr bool use_xor = false; }; +template +struct xag_resyn_static_params_for_win_resub : public xag_resyn_static_params +{ + using truth_table_storage_type = unordered_node_map; + using node_type = typename Ntk::node; +}; + template struct xag_resyn_static_params_for_sim_resub : public xag_resyn_static_params { @@ -106,6 +113,14 @@ struct xag_resyn_static_params_for_sim_resub : public xag_resyn_static_params using node_type = typename Ntk::node; }; +template +struct aig_resyn_static_params_for_win_resub : public xag_resyn_static_params +{ + using truth_table_storage_type = unordered_node_map; + using node_type = typename Ntk::node; + static constexpr bool use_xor = false; +}; + template struct aig_resyn_static_params_for_sim_resub : public xag_resyn_static_params_for_sim_resub { diff --git a/include/mockturtle/algorithms/xag_resub.hpp b/include/mockturtle/algorithms/xag_resub.hpp new file mode 100644 index 000000000..bb15faeb8 --- /dev/null +++ b/include/mockturtle/algorithms/xag_resub.hpp @@ -0,0 +1,216 @@ +/* mockturtle: C++ logic network library + * Copyright (C) 2018-2024 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 xag_resub.hpp + \brief XAG-specific resubstitution rules + + \author Alessandro Tempia Calvino +*/ + +#pragma once + +#include "../networks/xag.hpp" +#include "../utils/index_list.hpp" +#include "../utils/truth_table_utils.hpp" +#include "resubstitution.hpp" +#include "resyn_engines/xag_resyn.hpp" + +#include + +namespace mockturtle +{ + +struct xag_resyn_resub_stats +{ + /*! \brief Time for finding dependency function. */ + stopwatch<>::duration time_compute_function{ 0 }; + + /*! \brief Number of found solutions. */ + uint32_t num_success{ 0 }; + + /*! \brief Number of times that no solution can be found. */ + uint32_t num_fail{ 0 }; + + void report() const + { + fmt::print( "[i] \n" ); + fmt::print( "[i] #solution = {:6d}\n", num_success ); + fmt::print( "[i] #invoke = {:6d}\n", num_success + num_fail ); + fmt::print( "[i] engine time: {:>5.2f} secs\n", to_seconds( time_compute_function ) ); + } +}; /* xag_resyn_resub_stats */ + +/*! \brief Interfacing resubstitution functor with XAG resynthesis engines for `window_based_resub_engine`. + */ +template>> +struct xag_resyn_functor +{ +public: + using node = xag_network::node; + using signal = xag_network::signal; + using stats = xag_resyn_resub_stats; + using TT = typename ResynEngine::truth_table_t; + + static_assert( std::is_same_v, "truth table type of the simulator does not match" ); + +public: + explicit xag_resyn_functor( Ntk& ntk, Simulator const& sim, std::vector const& divs, uint32_t num_divs, stats& st ) + : ntk( ntk ), sim( sim ), tts( ntk ), divs( divs ), st( st ) + { + assert( divs.size() == num_divs ); + (void)num_divs; + div_signals.reserve( divs.size() ); + } + + std::optional operator()( node const& root, TTcare care, uint32_t required, uint32_t max_inserts, uint32_t potential_gain, uint32_t& real_gain ) + { + (void)required; + TT target = sim.get_tt( sim.get_phase( root ) ? !ntk.make_signal( root ) : ntk.make_signal( root ) ); + TT care_transformed = target.construct(); + care_transformed = care; + + typename ResynEngine::stats st_eng; + ResynEngine engine( st_eng ); + for ( auto const& d : divs ) + { + div_signals.emplace_back( sim.get_phase( d ) ? !ntk.make_signal( d ) : ntk.make_signal( d ) ); + tts[d] = sim.get_tt( ntk.make_signal( d ) ); + } + + auto const res = call_with_stopwatch( st.time_compute_function, [&]() { + return engine( target, care_transformed, std::begin( divs ), std::end( divs ), tts, std::min( potential_gain - 1, max_inserts ) ); + } ); + if ( res ) + { + ++st.num_success; + signal ret; + real_gain = potential_gain - ( *res ).num_gates(); + insert( ntk, div_signals.begin(), div_signals.end(), *res, [&]( signal const& s ) { ret = s; } ); + return ret; + } + else + { + ++st.num_fail; + return std::nullopt; + } + } + +private: + Ntk& ntk; + Simulator const& sim; + unordered_node_map tts; + std::vector const& divs; + std::vector div_signals; + stats& st; +}; /* xag_resyn_functor */ + +/*! \brief XAG-specific resubstitution algorithm. + * + * This algorithms iterates over each node, creates a + * reconvergence-driven cut, and attempts to re-express the node's + * function using existing nodes from the cut. Node which are no + * longer used (including nodes in their transitive fanins) can then + * be removed. The objective is to reduce the size of the network as + * much as possible while maintaining the global input-output + * functionality. + * + * **Required network functions:** + * + * - `clear_values` + * - `fanout_size` + * - `foreach_fanin` + * - `foreach_fanout` + * - `foreach_gate` + * - `foreach_node` + * - `get_constant` + * - `get_node` + * - `is_complemented` + * - `is_pi` + * - `level` + * - `make_signal` + * - `set_value` + * - `set_visited` + * - `size` + * - `substitute_node` + * - `value` + * - `visited` + * + * \param ntk A network type derived from xag_network + * \param ps Resubstitution parameters + * \param pst Resubstitution statistics + */ +template +void xag_resubstitution( Ntk& ntk, resubstitution_params const& ps = {}, resubstitution_stats* pst = nullptr ) +{ + static_assert( is_network_type_v, "Ntk is not a network type" ); + static_assert( std::is_same_v, "Network type is not xag_network" ); + + static_assert( has_clear_values_v, "Ntk does not implement the clear_values method" ); + static_assert( has_fanout_size_v, "Ntk does not implement the fanout_size method" ); + static_assert( has_foreach_fanin_v, "Ntk does not implement the foreach_fanin method" ); + static_assert( has_foreach_gate_v, "Ntk does not implement the foreach_gate method" ); + static_assert( has_foreach_node_v, "Ntk does not implement the foreach_node method" ); + static_assert( has_get_constant_v, "Ntk does not implement the get_constant method" ); + static_assert( has_get_node_v, "Ntk does not implement the get_node method" ); + static_assert( has_is_complemented_v, "Ntk does not implement the is_complemented method" ); + static_assert( has_is_pi_v, "Ntk does not implement the is_pi method" ); + static_assert( has_make_signal_v, "Ntk does not implement the make_signal method" ); + static_assert( has_set_value_v, "Ntk does not implement the set_value method" ); + static_assert( has_set_visited_v, "Ntk does not implement the set_visited method" ); + static_assert( has_size_v, "Ntk does not implement the has_size method" ); + static_assert( has_substitute_node_v, "Ntk does not implement the has substitute_node method" ); + 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" ); + static_assert( has_level_v, "Ntk does not implement the level method" ); + static_assert( has_foreach_fanout_v, "Ntk does not implement the foreach_fanout method" ); + + using truthtable_t = kitty::dynamic_truth_table; + using truthtable_dc_t = kitty::dynamic_truth_table; + using functor_t = xag_resyn_functor, truthtable_dc_t>; + + using resub_impl_t = detail::resubstitution_impl>; + + resubstitution_stats st; + typename resub_impl_t::engine_st_t engine_st; + typename resub_impl_t::collector_st_t collector_st; + + resub_impl_t p( ntk, ps, st, engine_st, collector_st ); + p.run(); + + if ( ps.verbose ) + { + st.report(); + collector_st.report(); + engine_st.report(); + } + + if ( pst ) + { + *pst = st; + } +} + +} /* namespace mockturtle */ diff --git a/test/algorithms/resubstitution.cpp b/test/algorithms/resubstitution.cpp index d5b1f263a..98dd34515 100644 --- a/test/algorithms/resubstitution.cpp +++ b/test/algorithms/resubstitution.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -285,6 +286,83 @@ TEST_CASE( "Substitute AND-2OR in AIG", "[resubstitution]" ) CHECK( aig.num_gates() == 6u ); } +TEST_CASE( "Substitute AND-2OR in AIG version 2", "[resubstitution]" ) +{ + aig_network aig; + auto x0 = aig.create_pi(); + auto x1 = aig.create_pi(); + auto x2 = aig.create_pi(); + auto x3 = aig.create_pi(); + auto n0 = aig.create_and( !x2, x3 ); + auto n1 = aig.create_and( !x2, n0 ); + auto n2 = aig.create_and( x3, !n1 ); + auto n3 = aig.create_and( x0, !x1 ); + auto n4 = aig.create_and( !n2, n3 ); + auto n5 = aig.create_and( x1, !n2 ); + auto n6 = aig.create_and( !n4, !n5 ); + auto n7 = aig.create_and( n1, n3 ); + aig.create_po( n6 ); + aig.create_po( n7 ); + + const auto tt = simulate>( aig ); + CHECK( tt[0]._bits == 0xf111 ); + CHECK( tt[1]._bits == 0x200 ); + CHECK( aig.num_gates() == 8u ); + + using view_t = depth_view>; + fanout_view fanout_view{ aig }; + view_t resub_view{ fanout_view }; + + resubstitution_params ps; + ps.max_inserts = 3; + aig_resubstitution2( resub_view, ps ); + aig = cleanup_dangling( aig ); + + /* check equivalence */ + const auto tt_opt = simulate>( aig ); + CHECK( tt_opt[0]._bits == tt[0]._bits ); + CHECK( tt_opt[1]._bits == tt[1]._bits ); + CHECK( aig.num_gates() == 6u ); +} + +TEST_CASE( "Resubstitution of XAG", "[resubstitution]" ) +{ + xag_network xag; + + const auto a = xag.create_pi(); + const auto b = xag.create_pi(); + const auto c = xag.create_pi(); + + const auto f = xag.create_and( xag.create_or( xag.create_and( b, xag.create_not( a ) ), xag.create_and( xag.create_not( b ), a ) ), c ); + xag.create_po( f ); + + CHECK( xag.size() == 8 ); + CHECK( xag.num_pis() == 3 ); + CHECK( xag.num_pos() == 1 ); + CHECK( xag.num_gates() == 4 ); + + const auto tt = simulate>( xag )[0]; + + resubstitution_params ps; + + using view_t = depth_view>; + fanout_view fanout_view{ xag }; + view_t resub_view{ fanout_view }; + + xag_resubstitution( resub_view, ps ); + + xag = cleanup_dangling( xag ); + + /* check equivalence */ + const auto tt_opt = simulate>( xag )[0]; + CHECK( tt_opt._bits == tt._bits ); + + CHECK( xag.size() == 6 ); + CHECK( xag.num_pis() == 3 ); + CHECK( xag.num_pos() == 1 ); + CHECK( xag.num_gates() == 2 ); +} + TEST_CASE( "Resubstitution of MIG", "[resubstitution]" ) { mig_network mig; @@ -322,6 +400,43 @@ TEST_CASE( "Resubstitution of MIG", "[resubstitution]" ) CHECK( mig.num_gates() == 1 ); } +TEST_CASE( "Resubstitution of MIG version 2", "[resubstitution]" ) +{ + mig_network mig; + + const auto a = mig.create_pi(); + const auto b = mig.create_pi(); + const auto c = mig.create_pi(); + + const auto f = mig.create_maj( a, mig.create_maj( a, b, c ), c ); + mig.create_po( f ); + + CHECK( mig.size() == 6 ); + CHECK( mig.num_pis() == 3 ); + CHECK( mig.num_pos() == 1 ); + CHECK( mig.num_gates() == 2 ); + + const auto tt = simulate>( mig )[0]; + CHECK( tt._bits == 0xe8 ); + + using view_t = depth_view>; + fanout_view fanout_view{ mig }; + view_t resub_view{ fanout_view }; + + mig_resubstitution2( resub_view ); + + mig = cleanup_dangling( mig ); + + /* check equivalence */ + const auto tt_opt = simulate>( mig )[0]; + CHECK( tt_opt._bits == tt._bits ); + + CHECK( mig.size() == 5 ); + CHECK( mig.num_pis() == 3 ); + CHECK( mig.num_pos() == 1 ); + CHECK( mig.num_gates() == 1 ); +} + TEST_CASE( "Resubstitution of XMG", "[resubstitution]" ) { xmg_network xmg; From ffe13ba2b858e3ad019abb3efa55a36761b86044 Mon Sep 17 00:00:00 2001 From: aletempiac Date: Mon, 23 Sep 2024 17:01:18 +0200 Subject: [PATCH 2/2] Removing gcc11 from macOS checks --- .github/workflows/macos.yml | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 488c2242e..7f2c96249 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -9,24 +9,6 @@ on: - master jobs: - build-gcc11: - name: GNU GCC 11 - runs-on: macOS-latest - - steps: - - uses: actions/checkout@v1 - with: - submodules: true - - name: Build mockturtle - run: | - mkdir build - cd build - cmake -DCMAKE_CXX_COMPILER=$(which g++-11) -DMOCKTURTLE_TEST=ON .. - make run_tests - - name: Run tests - run: | - cd build - ./test/run_tests "~[quality]" build-gcc12: name: GNU GCC 12 runs-on: macOS-latest