Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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: |
Expand Down
12 changes: 5 additions & 7 deletions include/mockturtle/algorithms/simulation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@

#include "../traits.hpp"
#include "../utils/node_map.hpp"
#include "../networks/aig.hpp"
#include "../networks/xag.hpp"

#include <kitty/constructors.hpp>
#include <kitty/dynamic_truth_table.hpp>
Expand Down Expand Up @@ -479,7 +477,7 @@ void update_const_pi( Ntk const& ntk, unordered_node_map<kitty::partial_truth_ta

} // namespace detail

/*! \brief (re-)simulate `n` and its transitive fanin cone.
/*! \brief (Re-)simulate `n` and its transitive fanin cone.
*
* Note that re-simulation (when `node_to_value.has( n ) == false`) is only done
* for the last block, no matter how many bits are used in this block.
Expand All @@ -496,8 +494,8 @@ void simulate_node( Ntk const& ntk, typename Ntk::node const& n, unordered_node_
static_assert( has_get_node_v<Ntk>, "Ntk does not implement the get_node method" );
static_assert( has_foreach_pi_v<Ntk>, "Ntk does not implement the foreach_pi method" );
static_assert( has_foreach_fanin_v<Ntk>, "Ntk does not implement the foreach_fanin method" );
static_assert( has_compute_v<Ntk, kitty::partial_truth_table>, "Ntk does not implement the compute method for kitty::partial_truth_table" );
static_assert( std::is_same_v<typename Ntk::base_type, aig_network> || std::is_same_v<typename Ntk::base_type, xag_network>, "The partial_truth_table specialized ntk.compute is currently only implemented in AIG and XAG" );
static_assert( has_compute_v<Ntk, kitty::partial_truth_table>, "Ntk does not implement the compute specialization for kitty::partial_truth_table" );
static_assert( has_compute_inplace_v<Ntk, kitty::partial_truth_table>, "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() )
{
Expand Down Expand Up @@ -545,8 +543,8 @@ void simulate_nodes( Ntk const& ntk, unordered_node_map<kitty::partial_truth_tab
static_assert( has_foreach_pi_v<Ntk>, "Ntk does not implement the foreach_pi method" );
static_assert( has_foreach_gate_v<Ntk>, "Ntk does not implement the foreach_gate method" );
static_assert( has_foreach_fanin_v<Ntk>, "Ntk does not implement the foreach_fanin method" );
static_assert( has_compute_v<Ntk, kitty::partial_truth_table>, "Ntk does not implement the compute method for kitty::partial_truth_table" );
static_assert( std::is_same_v<typename Ntk::base_type, aig_network> || std::is_same_v<typename Ntk::base_type, xag_network>, "The partial_truth_table specialized ntk.compute is currently only implemented in AIG and XAG" );
static_assert( has_compute_v<Ntk, kitty::partial_truth_table>, "Ntk does not implement the compute specialization for kitty::partial_truth_table" );
static_assert( has_compute_inplace_v<Ntk, kitty::partial_truth_table>, "Ntk does not implement the in-place compute specialization for kitty::partial_truth_table" );

detail::update_const_pi( ntk, node_to_value, sim );

Expand Down
5 changes: 3 additions & 2 deletions include/mockturtle/networks/aig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1028,9 +1028,9 @@ class aig_network
template<typename Iterator>
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<Iterator, kitty::partial_truth_table>, "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];
Expand All @@ -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 ) );
Expand Down
31 changes: 31 additions & 0 deletions include/mockturtle/networks/mig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1095,6 +1095,37 @@ 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<typename Iterator>
void compute( node const& n, kitty::partial_truth_table& result, Iterator begin, Iterator end ) const
{
static_assert( iterates_over_v<Iterator, kitty::partial_truth_table>, "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];
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() > 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() );
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
Expand Down
5 changes: 3 additions & 2 deletions include/mockturtle/networks/xag.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1088,9 +1088,9 @@ class xag_network
template<typename Iterator>
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<Iterator, kitty::partial_truth_table>, "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];
Expand All @@ -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 ) );
Expand Down
18 changes: 18 additions & 0 deletions include/mockturtle/traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1553,6 +1553,21 @@ template<class Ntk, typename T>
inline constexpr bool has_compute_v = has_compute<Ntk, T>::value;
#pragma endregion

#pragma region has_compute_inplace
template<class Ntk, typename T, class = void>
struct has_compute_inplace : std::false_type
{
};

template<class Ntk, typename T>
struct has_compute_inplace<Ntk, T, std::void_t<decltype( std::declval<Ntk>().compute( std::declval<node<Ntk>>(), std::declval<T&>(), std::begin( std::vector<T>() ), std::end( std::vector<T>() ) ) )>> : std::true_type
{
};

template<class Ntk, typename T>
inline constexpr bool has_compute_inplace_v = has_compute_inplace<Ntk, T>::value;
#pragma endregion

#pragma region has_has_mapping
template<class Ntk, class = void>
struct has_has_mapping : std::false_type
Expand Down Expand Up @@ -1938,4 +1953,7 @@ using iterates_over_t = std::enable_if_t<std::is_same_v<typename Iterator::value
template<typename Iterator>
using iterates_over_truth_table_t = std::enable_if_t<kitty::is_truth_table<typename Iterator::value_type>::value, typename Iterator::value_type>;

template<class Iterator, typename T>
inline constexpr bool iterates_over_v = std::is_same_v<typename Iterator::value_type, T>;

} /* namespace mockturtle */
2 changes: 1 addition & 1 deletion test/algorithms/pattern_generation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include <mockturtle/algorithms/simulation.hpp>
#include <mockturtle/algorithms/pattern_generation.hpp>
#include <mockturtle/networks/aig.hpp>
#include <mockturtle/networks/aig.hpp>
#include <mockturtle/networks/xag.hpp>

#include <kitty/bit_operations.hpp>

Expand Down
75 changes: 67 additions & 8 deletions test/networks/aig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <mockturtle/algorithms/cleanup.hpp>
#include <mockturtle/algorithms/simulation.hpp>
#include <mockturtle/networks/aig.hpp>
#include <mockturtle/networks/xmg.hpp>
#include <mockturtle/traits.hpp>

using namespace mockturtle;
Expand Down Expand Up @@ -437,6 +438,8 @@ TEST_CASE( "compute values in AIGs", "[aig]" )

CHECK( has_compute_v<aig_network, bool> );
CHECK( has_compute_v<aig_network, kitty::dynamic_truth_table> );
CHECK( has_compute_v<aig_network, kitty::partial_truth_table> );
CHECK( has_compute_inplace_v<aig_network, kitty::partial_truth_table> );

const auto x1 = aig.create_pi();
const auto x2 = aig.create_pi();
Expand All @@ -445,17 +448,73 @@ TEST_CASE( "compute values in AIGs", "[aig]" )
aig.create_po( f1 );
aig.create_po( f2 );

std::vector<bool> values{{true, false}};
{
std::vector<bool> 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<kitty::dynamic_truth_table> xs{2, kitty::dynamic_truth_table( 2 )};
kitty::create_nth_var( xs[0], 0 );
kitty::create_nth_var( xs[1], 1 );
{
std::vector<kitty::dynamic_truth_table> 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<kitty::partial_truth_table> 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] ) );

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] ) );
}

{
std::vector<kitty::partial_truth_table> 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]" )
Expand Down
Loading