From 71d69fb753986b74d61d8323dbff82c63c3329d1 Mon Sep 17 00:00:00 2001 From: Heinz Riener Date: Tue, 21 Jul 2020 10:08:08 +0200 Subject: [PATCH 1/8] mig_network: `compute` last block of `partial_truth_table`. --- include/mockturtle/networks/mig.hpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/include/mockturtle/networks/mig.hpp b/include/mockturtle/networks/mig.hpp index 1e1d13f19..837e3867f 100644 --- a/include/mockturtle/networks/mig.hpp +++ b/include/mockturtle/networks/mig.hpp @@ -1095,6 +1095,35 @@ class mig_network return kitty::ternary_majority( c1.weight ? ~tt1 : tt1, c2.weight ? ~tt2 : tt2, c3.weight ? ~tt3 : tt3 ); } + + /*! \brief Re-compute the last block. */ + template + void compute( node const& n, kitty::partial_truth_table& result, Iterator begin, Iterator end ) const + { + (void)end; + + assert( n != 0 && !is_ci( n ) ); + + auto const& c1 = _storage->nodes[n].children[0]; + auto const& c2 = _storage->nodes[n].children[1]; + auto const& c3 = _storage->nodes[n].children[2]; + + auto tt1 = *begin++; + auto tt2 = *begin++; + auto tt3 = *begin++; + + assert( tt1.num_bits() == tt2.num_bits() ); + assert( tt1.num_bits() == tt3.num_bits() ); + assert( tt1.num_bits() >= result.num_bits() ); + assert( result.num_blocks() == tt1.num_blocks() || ( result.num_blocks() == tt1.num_blocks() - 1 && result.num_bits() % 64 == 0 ) ); + + result.resize( tt1.num_bits() ); + result._bits.back() = + ( ( c1.weight ? ~tt1._bits.back() : tt1._bits.back() ) & ( c2.weight ? ~tt2._bits.back() : tt2._bits.back() ) ) | + ( ( c1.weight ? ~tt1._bits.back() : tt1._bits.back() ) & ( c3.weight ? ~tt3._bits.back() : tt3._bits.back() ) ) | + ( ( c2.weight ? ~tt2._bits.back() : tt2._bits.back() ) & ( c3.weight ? ~tt3._bits.back() : tt3._bits.back() ) ); + result.mask_bits(); + } #pragma endregion #pragma region Custom node values From 5c93eb76af3824ee2e208861b0482da3b01f56b9 Mon Sep 17 00:00:00 2001 From: Heinz Riener Date: Tue, 21 Jul 2020 10:48:24 +0200 Subject: [PATCH 2/8] tests. --- test/networks/aig.cpp | 48 ++++++++++++++++++++++++----- test/networks/mig.cpp | 70 +++++++++++++++++++++++++++++++++++++------ test/networks/xag.cpp | 48 ++++++++++++++++++++++++----- 3 files changed, 141 insertions(+), 25 deletions(-) diff --git a/test/networks/aig.cpp b/test/networks/aig.cpp index 61d80c8df..146116e55 100644 --- a/test/networks/aig.cpp +++ b/test/networks/aig.cpp @@ -437,6 +437,7 @@ TEST_CASE( "compute values in AIGs", "[aig]" ) CHECK( has_compute_v ); CHECK( has_compute_v ); + CHECK( has_compute_v ); const auto x1 = aig.create_pi(); const auto x2 = aig.create_pi(); @@ -445,17 +446,48 @@ TEST_CASE( "compute values in AIGs", "[aig]" ) aig.create_po( f1 ); aig.create_po( f2 ); - std::vector values{{true, false}}; + { + std::vector values{{true, false}}; - CHECK( aig.compute( aig.get_node( f1 ), values.begin(), values.end() ) == false ); - CHECK( aig.compute( aig.get_node( f2 ), values.begin(), values.end() ) == true ); + CHECK( aig.compute( aig.get_node( f1 ), values.begin(), values.end() ) == false ); + CHECK( aig.compute( aig.get_node( f2 ), values.begin(), values.end() ) == true ); + } - std::vector xs{2, kitty::dynamic_truth_table( 2 )}; - kitty::create_nth_var( xs[0], 0 ); - kitty::create_nth_var( xs[1], 1 ); + { + std::vector xs{2, kitty::dynamic_truth_table( 2 )}; + kitty::create_nth_var( xs[0], 0 ); + kitty::create_nth_var( xs[1], 1 ); - CHECK( aig.compute( aig.get_node( f1 ), xs.begin(), xs.end() ) == ( ~xs[0] & xs[1] ) ); - CHECK( aig.compute( aig.get_node( f2 ), xs.begin(), xs.end() ) == ( xs[0] & ~xs[1] ) ); + CHECK( aig.compute( aig.get_node( f1 ), xs.begin(), xs.end() ) == ( ~xs[0] & xs[1] ) ); + CHECK( aig.compute( aig.get_node( f2 ), xs.begin(), xs.end() ) == ( xs[0] & ~xs[1] ) ); + } + + { + std::vector xs{2, kitty::partial_truth_table( 4 )}; + + CHECK( aig.compute( aig.get_node( f1 ), xs.begin(), xs.end() ) == ( ~xs[0] & xs[1] ) ); + CHECK( aig.compute( aig.get_node( f2 ), xs.begin(), xs.end() ) == ( xs[0] & ~xs[1] ) ); + + xs[0].add_bit( 0 ); xs[1].add_bit( 1 ); + + CHECK( aig.compute( aig.get_node( f1 ), xs.begin(), xs.end() ) == ( ~xs[0] & xs[1] ) ); + CHECK( aig.compute( aig.get_node( f2 ), xs.begin(), xs.end() ) == ( xs[0] & ~xs[1] ) ); + + xs[0].add_bit( 1 ); xs[1].add_bit( 0 ); + + CHECK( aig.compute( aig.get_node( f1 ), xs.begin(), xs.end() ) == ( ~xs[0] & xs[1] ) ); + CHECK( aig.compute( aig.get_node( f2 ), xs.begin(), xs.end() ) == ( xs[0] & ~xs[1] ) ); + + xs[0].add_bit( 0 ); xs[1].add_bit( 0 ); + + CHECK( aig.compute( aig.get_node( f1 ), xs.begin(), xs.end() ) == ( ~xs[0] & xs[1] ) ); + CHECK( aig.compute( aig.get_node( f2 ), xs.begin(), xs.end() ) == ( xs[0] & ~xs[1] ) ); + + xs[0].add_bit( 1 ); xs[1].add_bit( 1 ); + + CHECK( aig.compute( aig.get_node( f1 ), xs.begin(), xs.end() ) == ( ~xs[0] & xs[1] ) ); + CHECK( aig.compute( aig.get_node( f2 ), xs.begin(), xs.end() ) == ( xs[0] & ~xs[1] ) ); + } } TEST_CASE( "custom node values in AIGs", "[aig]" ) diff --git a/test/networks/mig.cpp b/test/networks/mig.cpp index 4251ba385..b6056fe16 100644 --- a/test/networks/mig.cpp +++ b/test/networks/mig.cpp @@ -468,6 +468,7 @@ TEST_CASE( "compute values in MIGs", "[mig]" ) CHECK( has_compute_v ); CHECK( has_compute_v ); + CHECK( has_compute_v ); const auto x1 = mig.create_pi(); const auto x2 = mig.create_pi(); @@ -477,18 +478,69 @@ TEST_CASE( "compute values in MIGs", "[mig]" ) mig.create_po( f1 ); mig.create_po( f2 ); - std::vector values{{true, false, true}}; + { + std::vector values{{true, false, true}}; - CHECK( mig.compute( mig.get_node( f1 ), values.begin(), values.end() ) == false ); - CHECK( mig.compute( mig.get_node( f2 ), values.begin(), values.end() ) == true ); + CHECK( mig.compute( mig.get_node( f1 ), values.begin(), values.end() ) == false ); + CHECK( mig.compute( mig.get_node( f2 ), values.begin(), values.end() ) == true ); + } - std::vector xs{3, kitty::dynamic_truth_table( 3 )}; - kitty::create_nth_var( xs[0], 0 ); - kitty::create_nth_var( xs[1], 1 ); - kitty::create_nth_var( xs[2], 2 ); + { + std::vector xs{3, kitty::dynamic_truth_table( 3 )}; + kitty::create_nth_var( xs[0], 0 ); + kitty::create_nth_var( xs[1], 1 ); + kitty::create_nth_var( xs[2], 2 ); - CHECK( mig.compute( mig.get_node( f1 ), xs.begin(), xs.end() ) == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); - CHECK( mig.compute( mig.get_node( f2 ), xs.begin(), xs.end() ) == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + CHECK( mig.compute( mig.get_node( f1 ), xs.begin(), xs.end() ) == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + CHECK( mig.compute( mig.get_node( f2 ), xs.begin(), xs.end() ) == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + } + + { + std::vector xs{3, kitty::partial_truth_table( 8 )}; + + CHECK( mig.compute( mig.get_node( f1 ), xs.begin(), xs.end() ) == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + CHECK( mig.compute( mig.get_node( f2 ), xs.begin(), xs.end() ) == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + + xs[0].add_bit( 0 ); xs[1].add_bit( 0 ); xs[2].add_bit( 0 ); + + CHECK( mig.compute( mig.get_node( f1 ), xs.begin(), xs.end() ) == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + CHECK( mig.compute( mig.get_node( f2 ), xs.begin(), xs.end() ) == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + + xs[0].add_bit( 0 ); xs[1].add_bit( 0 ); xs[2].add_bit( 1 ); + + CHECK( mig.compute( mig.get_node( f1 ), xs.begin(), xs.end() ) == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + CHECK( mig.compute( mig.get_node( f2 ), xs.begin(), xs.end() ) == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + + xs[0].add_bit( 0 ); xs[1].add_bit( 1 ); xs[2].add_bit( 0 ); + + CHECK( mig.compute( mig.get_node( f1 ), xs.begin(), xs.end() ) == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + CHECK( mig.compute( mig.get_node( f2 ), xs.begin(), xs.end() ) == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + + xs[0].add_bit( 0 ); xs[1].add_bit( 1 ); xs[2].add_bit( 1 ); + + CHECK( mig.compute( mig.get_node( f1 ), xs.begin(), xs.end() ) == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + CHECK( mig.compute( mig.get_node( f2 ), xs.begin(), xs.end() ) == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + + xs[0].add_bit( 1 ); xs[1].add_bit( 0 ); xs[2].add_bit( 0 ); + + CHECK( mig.compute( mig.get_node( f1 ), xs.begin(), xs.end() ) == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + CHECK( mig.compute( mig.get_node( f2 ), xs.begin(), xs.end() ) == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + + xs[0].add_bit( 1 ); xs[1].add_bit( 0 ); xs[2].add_bit( 1 ); + + CHECK( mig.compute( mig.get_node( f1 ), xs.begin(), xs.end() ) == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + CHECK( mig.compute( mig.get_node( f2 ), xs.begin(), xs.end() ) == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + + xs[0].add_bit( 1 ); xs[1].add_bit( 1 ); xs[2].add_bit( 0 ); + + CHECK( mig.compute( mig.get_node( f1 ), xs.begin(), xs.end() ) == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + CHECK( mig.compute( mig.get_node( f2 ), xs.begin(), xs.end() ) == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + + xs[0].add_bit( 1 ); xs[1].add_bit( 1 ); xs[2].add_bit( 1 ); + + CHECK( mig.compute( mig.get_node( f1 ), xs.begin(), xs.end() ) == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + CHECK( mig.compute( mig.get_node( f2 ), xs.begin(), xs.end() ) == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + } } TEST_CASE( "custom node values in MIGs", "[mig]" ) diff --git a/test/networks/xag.cpp b/test/networks/xag.cpp index fa6b132df..159df990b 100644 --- a/test/networks/xag.cpp +++ b/test/networks/xag.cpp @@ -542,6 +542,7 @@ TEST_CASE( "compute values in xags", "[xag]" ) CHECK( has_compute_v ); CHECK( has_compute_v ); + CHECK( has_compute_v ); const auto x1 = xag.create_pi(); const auto x2 = xag.create_pi(); @@ -550,17 +551,48 @@ TEST_CASE( "compute values in xags", "[xag]" ) xag.create_po( f1 ); xag.create_po( f2 ); - std::vector values{{true, false}}; + { + std::vector values{{true, false}}; - CHECK( xag.compute( xag.get_node( f1 ), values.begin(), values.end() ) == false ); - CHECK( xag.compute( xag.get_node( f2 ), values.begin(), values.end() ) == true ); + CHECK( xag.compute( xag.get_node( f1 ), values.begin(), values.end() ) == false ); + CHECK( xag.compute( xag.get_node( f2 ), values.begin(), values.end() ) == true ); + } - std::vector xs{2, kitty::dynamic_truth_table( 2 )}; - kitty::create_nth_var( xs[0], 0 ); - kitty::create_nth_var( xs[1], 1 ); + { + std::vector xs{2, kitty::dynamic_truth_table( 2 )}; + kitty::create_nth_var( xs[0], 0 ); + kitty::create_nth_var( xs[1], 1 ); - CHECK( xag.compute( xag.get_node( f1 ), xs.begin(), xs.end() ) == ( ~xs[0] & xs[1] ) ); - CHECK( xag.compute( xag.get_node( f2 ), xs.begin(), xs.end() ) == ( xs[0] & ~xs[1] ) ); + CHECK( xag.compute( xag.get_node( f1 ), xs.begin(), xs.end() ) == ( ~xs[0] & xs[1] ) ); + CHECK( xag.compute( xag.get_node( f2 ), xs.begin(), xs.end() ) == ( xs[0] & ~xs[1] ) ); + } + + { + std::vector xs{2, kitty::partial_truth_table( 4 )}; + + CHECK( xag.compute( xag.get_node( f1 ), xs.begin(), xs.end() ) == ( ~xs[0] & xs[1] ) ); + CHECK( xag.compute( xag.get_node( f2 ), xs.begin(), xs.end() ) == ( xs[0] & ~xs[1] ) ); + + xs[0].add_bit( 0 ); xs[1].add_bit( 1 ); + + CHECK( xag.compute( xag.get_node( f1 ), xs.begin(), xs.end() ) == ( ~xs[0] & xs[1] ) ); + CHECK( xag.compute( xag.get_node( f2 ), xs.begin(), xs.end() ) == ( xs[0] & ~xs[1] ) ); + + xs[0].add_bit( 1 ); xs[1].add_bit( 0 ); + + CHECK( xag.compute( xag.get_node( f1 ), xs.begin(), xs.end() ) == ( ~xs[0] & xs[1] ) ); + CHECK( xag.compute( xag.get_node( f2 ), xs.begin(), xs.end() ) == ( xs[0] & ~xs[1] ) ); + + xs[0].add_bit( 0 ); xs[1].add_bit( 0 ); + + CHECK( xag.compute( xag.get_node( f1 ), xs.begin(), xs.end() ) == ( ~xs[0] & xs[1] ) ); + CHECK( xag.compute( xag.get_node( f2 ), xs.begin(), xs.end() ) == ( xs[0] & ~xs[1] ) ); + + xs[0].add_bit( 1 ); xs[1].add_bit( 1 ); + + CHECK( xag.compute( xag.get_node( f1 ), xs.begin(), xs.end() ) == ( ~xs[0] & xs[1] ) ); + CHECK( xag.compute( xag.get_node( f2 ), xs.begin(), xs.end() ) == ( xs[0] & ~xs[1] ) ); + } } TEST_CASE( "custom node values in xags", "[xag]" ) From 5a5499aa43ec9be31f6b54f6ff449c7cd61949b9 Mon Sep 17 00:00:00 2001 From: Heinz Riener Date: Tue, 21 Jul 2020 10:57:58 +0200 Subject: [PATCH 3/8] osx workflow update. --- .github/workflows/macos.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index ce2334d88..9cfad2bf0 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -39,7 +39,7 @@ jobs: run: | mkdir build cd build - cmake -DCMAKE_CXX_COMPILER=/usr/local/opt/gcc/bin/g++-9 -DMOCKTURTLE_TEST=ON .. + cmake -DCMAKE_CXX_COMPILER=/usr/local/opt/gcc@9/bin/g++-9 -DMOCKTURTLE_TEST=ON .. make run_tests - name: Run tests run: | From b3d10cb31a0443696876b30331265fe2701795bc Mon Sep 17 00:00:00 2001 From: Heinz Riener Date: Tue, 21 Jul 2020 11:31:16 +0200 Subject: [PATCH 4/8] new trait `has_compute_inplace` for computing values in-place. --- include/mockturtle/traits.hpp | 15 +++++++++++++++ test/networks/aig.cpp | 1 + test/networks/mig.cpp | 1 + test/networks/xag.cpp | 1 + 4 files changed, 18 insertions(+) diff --git a/include/mockturtle/traits.hpp b/include/mockturtle/traits.hpp index ce2851b50..82d9471e7 100644 --- a/include/mockturtle/traits.hpp +++ b/include/mockturtle/traits.hpp @@ -1553,6 +1553,21 @@ template inline constexpr bool has_compute_v = has_compute::value; #pragma endregion +#pragma region has_compute_inplace +template +struct has_compute_inplace : std::false_type +{ +}; + +template +struct has_compute_inplace().compute( std::declval>(), std::declval(), std::begin( std::vector() ), std::end( std::vector() ) ) )>> : std::true_type +{ +}; + +template +inline constexpr bool has_compute_inplace_v = has_compute_inplace::value; +#pragma endregion + #pragma region has_has_mapping template struct has_has_mapping : std::false_type diff --git a/test/networks/aig.cpp b/test/networks/aig.cpp index 146116e55..a14e74461 100644 --- a/test/networks/aig.cpp +++ b/test/networks/aig.cpp @@ -438,6 +438,7 @@ TEST_CASE( "compute values in AIGs", "[aig]" ) CHECK( has_compute_v ); CHECK( has_compute_v ); CHECK( has_compute_v ); + CHECK( has_compute_inplace_v ); const auto x1 = aig.create_pi(); const auto x2 = aig.create_pi(); diff --git a/test/networks/mig.cpp b/test/networks/mig.cpp index b6056fe16..fe81a1a99 100644 --- a/test/networks/mig.cpp +++ b/test/networks/mig.cpp @@ -469,6 +469,7 @@ TEST_CASE( "compute values in MIGs", "[mig]" ) CHECK( has_compute_v ); CHECK( has_compute_v ); CHECK( has_compute_v ); + CHECK( has_compute_inplace_v ); const auto x1 = mig.create_pi(); const auto x2 = mig.create_pi(); diff --git a/test/networks/xag.cpp b/test/networks/xag.cpp index 159df990b..f03522e78 100644 --- a/test/networks/xag.cpp +++ b/test/networks/xag.cpp @@ -543,6 +543,7 @@ TEST_CASE( "compute values in xags", "[xag]" ) CHECK( has_compute_v ); CHECK( has_compute_v ); CHECK( has_compute_v ); + CHECK( has_compute_inplace_v ); const auto x1 = xag.create_pi(); const auto x2 = xag.create_pi(); From c6f5668b298db241dc60bfc49d89f3a3b605d970 Mon Sep 17 00:00:00 2001 From: Heinz Riener Date: Tue, 21 Jul 2020 11:31:34 +0200 Subject: [PATCH 5/8] fixed includes. --- test/algorithms/pattern_generation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/algorithms/pattern_generation.cpp b/test/algorithms/pattern_generation.cpp index bd2855fda..b43129106 100644 --- a/test/algorithms/pattern_generation.cpp +++ b/test/algorithms/pattern_generation.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include From f66adb097ae4ee4b104e2d2abda21e051c092702 Mon Sep 17 00:00:00 2001 From: Heinz Riener Date: Tue, 21 Jul 2020 11:36:07 +0200 Subject: [PATCH 6/8] remove network dependencies from simulation. --- include/mockturtle/algorithms/simulation.hpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/include/mockturtle/algorithms/simulation.hpp b/include/mockturtle/algorithms/simulation.hpp index 65a8643ab..f42867b78 100644 --- a/include/mockturtle/algorithms/simulation.hpp +++ b/include/mockturtle/algorithms/simulation.hpp @@ -38,8 +38,6 @@ #include "../traits.hpp" #include "../utils/node_map.hpp" -#include "../networks/aig.hpp" -#include "../networks/xag.hpp" #include #include @@ -479,7 +477,7 @@ void update_const_pi( Ntk const& ntk, unordered_node_map, "Ntk does not implement the get_node method" ); static_assert( has_foreach_pi_v, "Ntk does not implement the foreach_pi method" ); static_assert( has_foreach_fanin_v, "Ntk does not implement the foreach_fanin method" ); - static_assert( has_compute_v, "Ntk does not implement the compute method for kitty::partial_truth_table" ); - static_assert( std::is_same_v || std::is_same_v, "The partial_truth_table specialized ntk.compute is currently only implemented in AIG and XAG" ); + static_assert( has_compute_v, "Ntk does not implement the compute specialization for kitty::partial_truth_table" ); + static_assert( has_compute_inplace_v, "Ntk does not implement the in-place compute specialization for kitty::partial_truth_table" ); if ( node_to_value[ntk.get_node( ntk.get_constant( false ) )].num_bits() != sim.num_bits() ) { @@ -545,8 +543,8 @@ void simulate_nodes( Ntk const& ntk, unordered_node_map, "Ntk does not implement the foreach_pi method" ); static_assert( has_foreach_gate_v, "Ntk does not implement the foreach_gate method" ); static_assert( has_foreach_fanin_v, "Ntk does not implement the foreach_fanin method" ); - static_assert( has_compute_v, "Ntk does not implement the compute method for kitty::partial_truth_table" ); - static_assert( std::is_same_v || std::is_same_v, "The partial_truth_table specialized ntk.compute is currently only implemented in AIG and XAG" ); + static_assert( has_compute_v, "Ntk does not implement the compute specialization for kitty::partial_truth_table" ); + static_assert( has_compute_inplace_v, "Ntk does not implement the in-place compute specialization for kitty::partial_truth_table" ); detail::update_const_pi( ntk, node_to_value, sim ); From 2b79c72357e82099deeba837912113b88ea7fd02 Mon Sep 17 00:00:00 2001 From: Heinz Riener Date: Tue, 21 Jul 2020 12:10:26 +0200 Subject: [PATCH 7/8] improved test cases. --- test/networks/aig.cpp | 2 +- test/networks/mig.cpp | 2 +- test/networks/xag.cpp | 4 +-- test/networks/xmg.cpp | 73 +++++++++++++++++++++++++++++++++++++------ 4 files changed, 67 insertions(+), 14 deletions(-) diff --git a/test/networks/aig.cpp b/test/networks/aig.cpp index a14e74461..b37f8c0eb 100644 --- a/test/networks/aig.cpp +++ b/test/networks/aig.cpp @@ -464,7 +464,7 @@ TEST_CASE( "compute values in AIGs", "[aig]" ) } { - std::vector xs{2, kitty::partial_truth_table( 4 )}; + std::vector xs{2}; CHECK( aig.compute( aig.get_node( f1 ), xs.begin(), xs.end() ) == ( ~xs[0] & xs[1] ) ); CHECK( aig.compute( aig.get_node( f2 ), xs.begin(), xs.end() ) == ( xs[0] & ~xs[1] ) ); diff --git a/test/networks/mig.cpp b/test/networks/mig.cpp index fe81a1a99..64addf516 100644 --- a/test/networks/mig.cpp +++ b/test/networks/mig.cpp @@ -497,7 +497,7 @@ TEST_CASE( "compute values in MIGs", "[mig]" ) } { - std::vector xs{3, kitty::partial_truth_table( 8 )}; + std::vector xs{3}; CHECK( mig.compute( mig.get_node( f1 ), xs.begin(), xs.end() ) == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); CHECK( mig.compute( mig.get_node( f2 ), xs.begin(), xs.end() ) == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); diff --git a/test/networks/xag.cpp b/test/networks/xag.cpp index f03522e78..9df2229eb 100644 --- a/test/networks/xag.cpp +++ b/test/networks/xag.cpp @@ -536,7 +536,7 @@ TEST_CASE( "node and signal iteration in an xag", "[xag]" ) CHECK( mask == 2 ); } -TEST_CASE( "compute values in xags", "[xag]" ) +TEST_CASE( "compute values in XAGs", "[xag]" ) { xag_network xag; @@ -569,7 +569,7 @@ TEST_CASE( "compute values in xags", "[xag]" ) } { - std::vector xs{2, kitty::partial_truth_table( 4 )}; + std::vector xs{2}; CHECK( xag.compute( xag.get_node( f1 ), xs.begin(), xs.end() ) == ( ~xs[0] & xs[1] ) ); CHECK( xag.compute( xag.get_node( f2 ), xs.begin(), xs.end() ) == ( xs[0] & ~xs[1] ) ); diff --git a/test/networks/xmg.cpp b/test/networks/xmg.cpp index 6118d34f1..a218ae0e7 100644 --- a/test/networks/xmg.cpp +++ b/test/networks/xmg.cpp @@ -545,12 +545,14 @@ TEST_CASE( "node and signal iteration in an xmg", "[xmg]" ) CHECK( mask == 2 ); } -TEST_CASE( "compute values in xmgs", "[xmg]" ) +TEST_CASE( "compute values in XMGs", "[xmg]" ) { xmg_network xmg; CHECK( has_compute_v ); CHECK( has_compute_v ); + CHECK( has_compute_v ); + CHECK( !has_compute_inplace_v ); const auto x1 = xmg.create_pi(); const auto x2 = xmg.create_pi(); @@ -560,18 +562,69 @@ TEST_CASE( "compute values in xmgs", "[xmg]" ) xmg.create_po( f1 ); xmg.create_po( f2 ); - std::vector values{{true, false, true}}; + { + std::vector values{{true, false, true}}; - CHECK( xmg.compute( xmg.get_node( f1 ), values.begin(), values.end() ) == false ); - CHECK( xmg.compute( xmg.get_node( f2 ), values.begin(), values.end() ) == true ); + CHECK( xmg.compute( xmg.get_node( f1 ), values.begin(), values.end() ) == false ); + CHECK( xmg.compute( xmg.get_node( f2 ), values.begin(), values.end() ) == true ); + } - std::vector xs{3, kitty::dynamic_truth_table( 3 )}; - kitty::create_nth_var( xs[0], 0 ); - kitty::create_nth_var( xs[1], 1 ); - kitty::create_nth_var( xs[2], 2 ); + { + std::vector xs{3, kitty::dynamic_truth_table( 3 )}; + kitty::create_nth_var( xs[0], 0 ); + kitty::create_nth_var( xs[1], 1 ); + kitty::create_nth_var( xs[2], 2 ); - CHECK( xmg.compute( xmg.get_node( f1 ), xs.begin(), xs.end() ) == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); - CHECK( xmg.compute( xmg.get_node( f2 ), xs.begin(), xs.end() ) == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + CHECK( xmg.compute( xmg.get_node( f1 ), xs.begin(), xs.end() ) == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + CHECK( xmg.compute( xmg.get_node( f2 ), xs.begin(), xs.end() ) == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + } + + { + std::vector xs{3}; + + CHECK( xmg.compute( xmg.get_node( f1 ), xs.begin(), xs.end() ) == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + CHECK( xmg.compute( xmg.get_node( f2 ), xs.begin(), xs.end() ) == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + + xs[0].add_bit( 0 ); xs[1].add_bit( 0 ); xs[2].add_bit( 0 ); + + CHECK( xmg.compute( xmg.get_node( f1 ), xs.begin(), xs.end() ) == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + CHECK( xmg.compute( xmg.get_node( f2 ), xs.begin(), xs.end() ) == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + + xs[0].add_bit( 0 ); xs[1].add_bit( 0 ); xs[2].add_bit( 1 ); + + CHECK( xmg.compute( xmg.get_node( f1 ), xs.begin(), xs.end() ) == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + CHECK( xmg.compute( xmg.get_node( f2 ), xs.begin(), xs.end() ) == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + + xs[0].add_bit( 0 ); xs[1].add_bit( 1 ); xs[2].add_bit( 0 ); + + CHECK( xmg.compute( xmg.get_node( f1 ), xs.begin(), xs.end() ) == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + CHECK( xmg.compute( xmg.get_node( f2 ), xs.begin(), xs.end() ) == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + + xs[0].add_bit( 0 ); xs[1].add_bit( 1 ); xs[2].add_bit( 1 ); + + CHECK( xmg.compute( xmg.get_node( f1 ), xs.begin(), xs.end() ) == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + CHECK( xmg.compute( xmg.get_node( f2 ), xs.begin(), xs.end() ) == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + + xs[0].add_bit( 1 ); xs[1].add_bit( 0 ); xs[2].add_bit( 0 ); + + CHECK( xmg.compute( xmg.get_node( f1 ), xs.begin(), xs.end() ) == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + CHECK( xmg.compute( xmg.get_node( f2 ), xs.begin(), xs.end() ) == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + + xs[0].add_bit( 1 ); xs[1].add_bit( 0 ); xs[2].add_bit( 1 ); + + CHECK( xmg.compute( xmg.get_node( f1 ), xs.begin(), xs.end() ) == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + CHECK( xmg.compute( xmg.get_node( f2 ), xs.begin(), xs.end() ) == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + + xs[0].add_bit( 1 ); xs[1].add_bit( 1 ); xs[2].add_bit( 0 ); + + CHECK( xmg.compute( xmg.get_node( f1 ), xs.begin(), xs.end() ) == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + CHECK( xmg.compute( xmg.get_node( f2 ), xs.begin(), xs.end() ) == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + + xs[0].add_bit( 1 ); xs[1].add_bit( 1 ); xs[2].add_bit( 1 ); + + CHECK( xmg.compute( xmg.get_node( f1 ), xs.begin(), xs.end() ) == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + CHECK( xmg.compute( xmg.get_node( f2 ), xs.begin(), xs.end() ) == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + } } TEST_CASE( "custom node values in xmgs", "[xmg]" ) From 1d2c41a929baba1e75227249663ea96ca0689024 Mon Sep 17 00:00:00 2001 From: Heinz Riener Date: Tue, 21 Jul 2020 12:43:14 +0200 Subject: [PATCH 8/8] test cases and improved assertion checks for (in-place) compute. --- include/mockturtle/networks/aig.hpp | 5 +-- include/mockturtle/networks/mig.hpp | 4 ++- include/mockturtle/networks/xag.hpp | 5 +-- include/mockturtle/traits.hpp | 3 ++ test/networks/aig.cpp | 26 ++++++++++++++++ test/networks/mig.cpp | 48 +++++++++++++++++++++++++++++ test/networks/xag.cpp | 25 +++++++++++++++ 7 files changed, 111 insertions(+), 5 deletions(-) diff --git a/include/mockturtle/networks/aig.hpp b/include/mockturtle/networks/aig.hpp index 8cd709587..9a54e6818 100644 --- a/include/mockturtle/networks/aig.hpp +++ b/include/mockturtle/networks/aig.hpp @@ -1028,9 +1028,9 @@ class aig_network template void compute( node const& n, kitty::partial_truth_table& result, Iterator begin, Iterator end ) const { - (void)end; - /* TODO: assert type of *begin is partial_truth_table */ + static_assert( iterates_over_v, "begin and end have to iterate over partial_truth_tables" ); + (void)end; assert( n != 0 && !is_ci( n ) ); auto const& c1 = _storage->nodes[n].children[0]; @@ -1039,6 +1039,7 @@ class aig_network auto tt1 = *begin++; auto tt2 = *begin++; + assert( tt1.num_bits() > 0 && "truth tables must not be empty" ); assert( tt1.num_bits() == tt2.num_bits() ); assert( tt1.num_bits() >= result.num_bits() ); assert( result.num_blocks() == tt1.num_blocks() || ( result.num_blocks() == tt1.num_blocks() - 1 && result.num_bits() % 64 == 0 ) ); diff --git a/include/mockturtle/networks/mig.hpp b/include/mockturtle/networks/mig.hpp index 837e3867f..7e8ae5f1a 100644 --- a/include/mockturtle/networks/mig.hpp +++ b/include/mockturtle/networks/mig.hpp @@ -1100,8 +1100,9 @@ class mig_network template void compute( node const& n, kitty::partial_truth_table& result, Iterator begin, Iterator end ) const { - (void)end; + static_assert( iterates_over_v, "begin and end have to iterate over partial_truth_tables" ); + (void)end; assert( n != 0 && !is_ci( n ) ); auto const& c1 = _storage->nodes[n].children[0]; @@ -1112,6 +1113,7 @@ class mig_network auto tt2 = *begin++; auto tt3 = *begin++; + assert( tt1.num_bits() > 0 && "truth tables must not be empty" ); assert( tt1.num_bits() == tt2.num_bits() ); assert( tt1.num_bits() == tt3.num_bits() ); assert( tt1.num_bits() >= result.num_bits() ); diff --git a/include/mockturtle/networks/xag.hpp b/include/mockturtle/networks/xag.hpp index 161dad1a0..00666627f 100644 --- a/include/mockturtle/networks/xag.hpp +++ b/include/mockturtle/networks/xag.hpp @@ -1088,9 +1088,9 @@ class xag_network template void compute( node const& n, kitty::partial_truth_table& result, Iterator begin, Iterator end ) const { - (void)end; - /* TODO: assert type of *begin is partial_truth_table */ + static_assert( iterates_over_v, "begin and end have to iterate over partial_truth_tables" ); + (void)end; assert( n != 0 && !is_ci( n ) ); auto const& c1 = _storage->nodes[n].children[0]; @@ -1099,6 +1099,7 @@ class xag_network auto tt1 = *begin++; auto tt2 = *begin++; + assert( tt1.num_bits() > 0 && "truth tables must not be empty" ); assert( tt1.num_bits() == tt2.num_bits() ); assert( tt1.num_bits() >= result.num_bits() ); assert( result.num_blocks() == tt1.num_blocks() || ( result.num_blocks() == tt1.num_blocks() - 1 && result.num_bits() % 64 == 0 ) ); diff --git a/include/mockturtle/traits.hpp b/include/mockturtle/traits.hpp index 82d9471e7..bc0cb995e 100644 --- a/include/mockturtle/traits.hpp +++ b/include/mockturtle/traits.hpp @@ -1953,4 +1953,7 @@ using iterates_over_t = std::enable_if_t using iterates_over_truth_table_t = std::enable_if_t::value, typename Iterator::value_type>; +template +inline constexpr bool iterates_over_v = std::is_same_v; + } /* namespace mockturtle */ diff --git a/test/networks/aig.cpp b/test/networks/aig.cpp index b37f8c0eb..49a958158 100644 --- a/test/networks/aig.cpp +++ b/test/networks/aig.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include using namespace mockturtle; @@ -489,6 +490,31 @@ TEST_CASE( "compute values in AIGs", "[aig]" ) CHECK( aig.compute( aig.get_node( f1 ), xs.begin(), xs.end() ) == ( ~xs[0] & xs[1] ) ); CHECK( aig.compute( aig.get_node( f2 ), xs.begin(), xs.end() ) == ( xs[0] & ~xs[1] ) ); } + + { + std::vector xs{2}; + kitty::partial_truth_table result; + + xs[0].add_bit( 0 ); xs[1].add_bit( 1 ); + + aig.compute( aig.get_node( f1 ), result, xs.begin(), xs.end() ); CHECK( result == ( ~xs[0] & xs[1] ) ); + aig.compute( aig.get_node( f2 ), result, xs.begin(), xs.end() ); CHECK( result == ( xs[0] & ~xs[1] ) ); + + xs[0].add_bit( 1 ); xs[1].add_bit( 0 ); + + aig.compute( aig.get_node( f1 ), result, xs.begin(), xs.end() ); CHECK( result == ( ~xs[0] & xs[1] ) ); + aig.compute( aig.get_node( f2 ), result, xs.begin(), xs.end() ); CHECK( result == ( xs[0] & ~xs[1] ) ); + + xs[0].add_bit( 0 ); xs[1].add_bit( 0 ); + + aig.compute( aig.get_node( f1 ), result, xs.begin(), xs.end() ); CHECK( result == ( ~xs[0] & xs[1] ) ); + aig.compute( aig.get_node( f2 ), result, xs.begin(), xs.end() ); CHECK( result == ( xs[0] & ~xs[1] ) ); + + xs[0].add_bit( 1 ); xs[1].add_bit( 1 ); + + aig.compute( aig.get_node( f1 ), result, xs.begin(), xs.end() ); CHECK( result == ( ~xs[0] & xs[1] ) ); + aig.compute( aig.get_node( f2 ), result, xs.begin(), xs.end() ); CHECK( result == ( xs[0] & ~xs[1] ) ); + } } TEST_CASE( "custom node values in AIGs", "[aig]" ) diff --git a/test/networks/mig.cpp b/test/networks/mig.cpp index 64addf516..f6049e75b 100644 --- a/test/networks/mig.cpp +++ b/test/networks/mig.cpp @@ -542,6 +542,54 @@ TEST_CASE( "compute values in MIGs", "[mig]" ) CHECK( mig.compute( mig.get_node( f1 ), xs.begin(), xs.end() ) == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); CHECK( mig.compute( mig.get_node( f2 ), xs.begin(), xs.end() ) == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); } + + { + std::vector xs{3}; + kitty::partial_truth_table result; + + xs[0].add_bit( 0 ); xs[1].add_bit( 0 ); xs[2].add_bit( 0 ); + + mig.compute( mig.get_node( f1 ), result, xs.begin(), xs.end() ); CHECK( result == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + mig.compute( mig.get_node( f2 ), result, xs.begin(), xs.end() ); CHECK( result == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + + xs[0].add_bit( 0 ); xs[1].add_bit( 0 ); xs[2].add_bit( 1 ); + + mig.compute( mig.get_node( f1 ), result, xs.begin(), xs.end() ); CHECK( result == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + mig.compute( mig.get_node( f2 ), result, xs.begin(), xs.end() ); CHECK( result == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + + xs[0].add_bit( 0 ); xs[1].add_bit( 1 ); xs[2].add_bit( 0 ); + + mig.compute( mig.get_node( f1 ), result, xs.begin(), xs.end() ); CHECK( result == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + mig.compute( mig.get_node( f2 ), result, xs.begin(), xs.end() ); CHECK( result == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + + xs[0].add_bit( 0 ); xs[1].add_bit( 1 ); xs[2].add_bit( 1 ); + + mig.compute( mig.get_node( f1 ), result, xs.begin(), xs.end() ); CHECK( result == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + mig.compute( mig.get_node( f2 ), result, xs.begin(), xs.end() ); CHECK( result == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + + xs[0].add_bit( 1 ); xs[1].add_bit( 0 ); xs[2].add_bit( 0 ); + + mig.compute( mig.get_node( f1 ), result, xs.begin(), xs.end() ); CHECK( result == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + mig.compute( mig.get_node( f2 ), result, xs.begin(), xs.end() ); CHECK( result == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + + mig.compute( mig.get_node( f1 ), result, xs.begin(), xs.end() ); CHECK( result == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + mig.compute( mig.get_node( f2 ), result, xs.begin(), xs.end() ); CHECK( result == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + + xs[0].add_bit( 1 ); xs[1].add_bit( 0 ); xs[2].add_bit( 1 ); + + mig.compute( mig.get_node( f1 ), result, xs.begin(), xs.end() ); CHECK( result == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + mig.compute( mig.get_node( f2 ), result, xs.begin(), xs.end() ); CHECK( result == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + + xs[0].add_bit( 1 ); xs[1].add_bit( 1 ); xs[2].add_bit( 0 ); + + mig.compute( mig.get_node( f1 ), result, xs.begin(), xs.end() ); CHECK( result == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + mig.compute( mig.get_node( f2 ), result, xs.begin(), xs.end() ); CHECK( result == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + + xs[0].add_bit( 1 ); xs[1].add_bit( 1 ); xs[2].add_bit( 1 ); + + mig.compute( mig.get_node( f1 ), result, xs.begin(), xs.end() ); CHECK( result == ( ( ~xs[0] & xs[1] ) | ( ~xs[0] & xs[2] ) | ( xs[2] & xs[1] ) ) ); + mig.compute( mig.get_node( f2 ), result, xs.begin(), xs.end() ); CHECK( result == ( ( xs[0] & ~xs[1] ) | ( xs[0] & xs[2] ) | ( xs[2] & ~xs[1] ) ) ); + } } TEST_CASE( "custom node values in MIGs", "[mig]" ) diff --git a/test/networks/xag.cpp b/test/networks/xag.cpp index 9df2229eb..efb10e5e7 100644 --- a/test/networks/xag.cpp +++ b/test/networks/xag.cpp @@ -594,6 +594,31 @@ TEST_CASE( "compute values in XAGs", "[xag]" ) CHECK( xag.compute( xag.get_node( f1 ), xs.begin(), xs.end() ) == ( ~xs[0] & xs[1] ) ); CHECK( xag.compute( xag.get_node( f2 ), xs.begin(), xs.end() ) == ( xs[0] & ~xs[1] ) ); } + + { + std::vector xs{2}; + kitty::partial_truth_table result; + + xs[0].add_bit( 0 ); xs[1].add_bit( 1 ); + + xag.compute( xag.get_node( f1 ), result, xs.begin(), xs.end() ); CHECK( result == ( ~xs[0] & xs[1] ) ); + xag.compute( xag.get_node( f2 ), result, xs.begin(), xs.end() ); CHECK( result == ( xs[0] & ~xs[1] ) ); + + xs[0].add_bit( 1 ); xs[1].add_bit( 0 ); + + xag.compute( xag.get_node( f1 ), result, xs.begin(), xs.end() ); CHECK( result == ( ~xs[0] & xs[1] ) ); + xag.compute( xag.get_node( f2 ), result, xs.begin(), xs.end() ); CHECK( result == ( xs[0] & ~xs[1] ) ); + + xs[0].add_bit( 0 ); xs[1].add_bit( 0 ); + + xag.compute( xag.get_node( f1 ), result, xs.begin(), xs.end() ); CHECK( result == ( ~xs[0] & xs[1] ) ); + xag.compute( xag.get_node( f2 ), result, xs.begin(), xs.end() ); CHECK( result == ( xs[0] & ~xs[1] ) ); + + xs[0].add_bit( 1 ); xs[1].add_bit( 1 ); + + xag.compute( xag.get_node( f1 ), result, xs.begin(), xs.end() ); CHECK( result == ( ~xs[0] & xs[1] ) ); + xag.compute( xag.get_node( f2 ), result, xs.begin(), xs.end() ); CHECK( result == ( xs[0] & ~xs[1] ) ); + } } TEST_CASE( "custom node values in xags", "[xag]" )