Skip to content

Commit

Permalink
Fixing non-simplified gates handling in networks (#632)
Browse files Browse the repository at this point in the history
* Improving scalability of AIG and XAG balancing

* Fixing issues in substitute_node_no_restrash that may create buffer nodes, which are seen as PIs
  • Loading branch information
aletempiac authored Feb 19, 2024
1 parent c65f3f6 commit 6efb33b
Show file tree
Hide file tree
Showing 8 changed files with 374 additions and 31 deletions.
67 changes: 62 additions & 5 deletions include/mockturtle/algorithms/aig_balancing.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ struct aig_balancing_params
{
/*! \brief Minimizes the number of levels. */
bool minimize_levels{ true };

/*! \brief Use fast version, it may not find some area optimizations. */
bool fast_mode{ true };
};

namespace detail
Expand Down Expand Up @@ -131,10 +134,20 @@ class aig_balance_impl
while ( storage[level].size() > 1 )
{
/* explore multiple possibilities to find logic sharing */
if ( ps.minimize_levels )
pick_nodes( storage[level], find_left_most_at_level( storage[level] ) );
if ( ps.fast_mode )
{
if ( ps.minimize_levels )
pick_nodes_fast( storage[level], find_left_most_at_level( storage[level] ) );
else
pick_nodes_area_fast( storage[level] );
}
else
pick_nodes_area( storage[level] );
{
if ( ps.minimize_levels )
pick_nodes( storage[level], find_left_most_at_level( storage[level] ) );
else
pick_nodes_area( storage[level] );
}

/* pop the two selected nodes to create the new AND gate */
signal child1 = storage[level].back();
Expand Down Expand Up @@ -235,7 +248,7 @@ class aig_balance_impl
return pointer;
}

void pick_nodes( std::vector<signal>& leaves, size_t left_most )
inline void pick_nodes( std::vector<signal>& leaves, size_t left_most )
{
size_t right_most = leaves.size() - 2;

Expand Down Expand Up @@ -269,7 +282,29 @@ class aig_balance_impl
}
}

void pick_nodes_area( std::vector<signal>& leaves )
inline void pick_nodes_fast( std::vector<signal>& leaves, size_t left_most )
{
size_t left_pointer = leaves.size() - 1;
while ( left_pointer-- > left_most )
{
/* select if node exists */
std::optional<signal> pnode = ntk.has_and( leaves.back(), leaves[left_pointer] );
if ( pnode.has_value() )
{
/* already present in TFI */
if ( ntk.visited( ntk.get_node( *pnode ) ) == ntk.trav_id() )
{
continue;
}

if ( leaves[left_pointer] != leaves[leaves.size() - 2] )
std::swap( leaves[left_pointer], leaves[leaves.size() - 2] );
break;
}
}
}

inline void pick_nodes_area( std::vector<signal>& leaves )
{
for ( size_t right_pointer = leaves.size() - 1; right_pointer > 0; --right_pointer )
{
Expand All @@ -296,6 +331,28 @@ class aig_balance_impl
}
}

inline void pick_nodes_area_fast( std::vector<signal>& leaves )
{
size_t left_pointer = leaves.size() - 1;
while ( left_pointer-- > 0 )
{
/* select if node exists */
std::optional<signal> pnode = ntk.has_and( leaves.back(), leaves[left_pointer] );
if ( pnode.has_value() )
{
/* already present in TFI */
if ( ntk.visited( ntk.get_node( *pnode ) ) == ntk.trav_id() )
{
continue;
}

if ( leaves[left_pointer] != leaves[leaves.size() - 2] )
std::swap( leaves[left_pointer], leaves[leaves.size() - 2] );
break;
}
}
}

void insert_node_sorted( std::vector<signal>& leaves, signal const& f )
{
node n = ntk.get_node( f );
Expand Down
131 changes: 121 additions & 10 deletions include/mockturtle/algorithms/xag_balancing.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ struct xag_balancing_params
{
/*! \brief Minimizes the number of levels. */
bool minimize_levels{ true };

/*! \brief Use fast version, it may not find some area optimizations. */
bool fast_mode{ true };
};

namespace detail
Expand Down Expand Up @@ -150,10 +153,20 @@ class xag_balance_impl
while ( storage[level].size() > 1 )
{
/* explore multiple possibilities to find logic sharing */
if ( ps.minimize_levels )
pick_nodes_and( storage[level], find_left_most_at_level( storage[level] ) );
if ( ps.fast_mode )
{
if ( ps.minimize_levels )
pick_nodes_and_fast( storage[level], find_left_most_at_level( storage[level] ) );
else
pick_nodes_and_area_fast( storage[level] );
}
else
pick_nodes_and_area( storage[level] );
{
if ( ps.minimize_levels )
pick_nodes_and( storage[level], find_left_most_at_level( storage[level] ) );
else
pick_nodes_and_area( storage[level] );
}

/* pop the two selected nodes to create the new AND gate */
signal child1 = storage[level].back();
Expand All @@ -174,10 +187,20 @@ class xag_balance_impl
while ( storage[level].size() > 1 )
{
/* explore multiple possibilities to find logic sharing */
if ( ps.minimize_levels )
pick_nodes_xor( storage[level], find_left_most_at_level( storage[level] ) );
if ( ps.fast_mode )
{
if ( ps.minimize_levels )
pick_nodes_xor_fast( storage[level], find_left_most_at_level( storage[level] ) );
else
pick_nodes_xor_area_fast( storage[level] );
}
else
pick_nodes_xor_area( storage[level] );
{
if ( ps.minimize_levels )
pick_nodes_xor( storage[level], find_left_most_at_level( storage[level] ) );
else
pick_nodes_xor_area( storage[level] );
}

/* pop the two selected nodes to create the new XOR gate */
signal child1 = storage[level].back();
Expand Down Expand Up @@ -332,7 +355,7 @@ class xag_balance_impl
return pointer;
}

void pick_nodes_and( std::vector<signal>& leaves, size_t left_most )
inline void pick_nodes_and( std::vector<signal>& leaves, size_t left_most )
{
size_t right_most = leaves.size() - 2;

Expand Down Expand Up @@ -366,7 +389,29 @@ class xag_balance_impl
}
}

void pick_nodes_and_area( std::vector<signal>& leaves )
inline void pick_nodes_and_fast( std::vector<signal>& leaves, size_t left_most )
{
size_t left_pointer = leaves.size() - 1;
while ( left_pointer-- > left_most )
{
/* select if node exists */
std::optional<signal> pnode = ntk.has_and( leaves.back(), leaves[left_pointer] );
if ( pnode.has_value() )
{
/* already present in TFI */
if ( ntk.visited( ntk.get_node( *pnode ) ) == ntk.trav_id() )
{
continue;
}

if ( leaves[left_pointer] != leaves[leaves.size() - 2] )
std::swap( leaves[left_pointer], leaves[leaves.size() - 2] );
break;
}
}
}

inline void pick_nodes_and_area( std::vector<signal>& leaves )
{
for ( size_t right_pointer = leaves.size() - 1; right_pointer > 0; --right_pointer )
{
Expand All @@ -393,7 +438,29 @@ class xag_balance_impl
}
}

void pick_nodes_xor( std::vector<signal>& leaves, size_t left_most )
inline void pick_nodes_and_area_fast( std::vector<signal>& leaves )
{
size_t left_pointer = leaves.size() - 1;
while ( left_pointer-- > 0 )
{
/* select if node exists */
std::optional<signal> pnode = ntk.has_and( leaves.back(), leaves[left_pointer] );
if ( pnode.has_value() )
{
/* already present in TFI */
if ( ntk.visited( ntk.get_node( *pnode ) ) == ntk.trav_id() )
{
continue;
}

if ( leaves[left_pointer] != leaves[leaves.size() - 2] )
std::swap( leaves[left_pointer], leaves[leaves.size() - 2] );
break;
}
}
}

inline void pick_nodes_xor( std::vector<signal>& leaves, size_t left_most )
{
size_t right_most = leaves.size() - 2;

Expand Down Expand Up @@ -427,7 +494,29 @@ class xag_balance_impl
}
}

void pick_nodes_xor_area( std::vector<signal>& leaves )
inline void pick_nodes_xor_fast( std::vector<signal>& leaves, size_t left_most )
{
size_t left_pointer = leaves.size() - 1;
while ( left_pointer-- > left_most )
{
/* select if node exists */
std::optional<signal> pnode = ntk.has_xor( leaves.back(), leaves[left_pointer] );
if ( pnode.has_value() )
{
/* already present in TFI */
if ( ntk.visited( ntk.get_node( *pnode ) ) == ntk.trav_id() )
{
continue;
}

if ( leaves[left_pointer] != leaves[leaves.size() - 2] )
std::swap( leaves[left_pointer], leaves[leaves.size() - 2] );
break;
}
}
}

inline void pick_nodes_xor_area( std::vector<signal>& leaves )
{
for ( size_t right_pointer = leaves.size() - 1; right_pointer > 0; --right_pointer )
{
Expand All @@ -454,6 +543,28 @@ class xag_balance_impl
}
}

inline void pick_nodes_xor_area_fast( std::vector<signal>& leaves )
{
size_t left_pointer = leaves.size() - 1;
while ( left_pointer-- > 0 )
{
/* select if node exists */
std::optional<signal> pnode = ntk.has_xor( leaves.back(), leaves[left_pointer] );
if ( pnode.has_value() )
{
/* already present in TFI */
if ( ntk.visited( ntk.get_node( *pnode ) ) == ntk.trav_id() )
{
continue;
}

if ( leaves[left_pointer] != leaves[leaves.size() - 2] )
std::swap( leaves[left_pointer], leaves[leaves.size() - 2] );
break;
}
}
}

void insert_node_sorted_and( std::vector<signal>& leaves, signal const& f )
{
node n = ntk.get_node( f );
Expand Down
6 changes: 4 additions & 2 deletions include/mockturtle/networks/aig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ struct aig_hash
`data[0].h1`: Fan-out size (we use MSB to indicate whether a node is dead)
`data[0].h2`: Application-specific value
`data[1].h1`: Visited flag
`data[1].h2`: Is terminal node (PI or CI)
*/
using aig_storage = storage<regular_node<2, 2, 1>,
empty_storage_data,
Expand Down Expand Up @@ -206,6 +207,7 @@ class aig_network
const auto index = _storage->nodes.size();
auto& node = _storage->nodes.emplace_back();
node.children[0].data = node.children[1].data = _storage->inputs.size();
node.data[1].h2 = 1; // mark as PI
_storage->inputs.emplace_back( index );
return { index, 0 };
}
Expand All @@ -231,12 +233,12 @@ class aig_network

bool is_ci( node const& n ) const
{
return _storage->nodes[n].children[0].data == _storage->nodes[n].children[1].data;
return _storage->nodes[n].data[1].h2 == 1;
}

bool is_pi( node const& n ) const
{
return _storage->nodes[n].children[0].data == _storage->nodes[n].children[1].data && !is_constant( n );
return _storage->nodes[n].data[1].h2 == 1 && !is_constant( n );
}

bool constant_value( node const& n ) const
Expand Down
6 changes: 4 additions & 2 deletions include/mockturtle/networks/mig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ namespace mockturtle
`data[0].h1`: Fan-out size (we use MSB to indicate whether a node is dead)
`data[0].h2`: Application-specific value
`data[1].h1`: Visited flag
`data[1].h2`: Is terminal node (PI or CI)
*/
using mig_storage = storage<regular_node<3, 2, 1>>;

Expand Down Expand Up @@ -187,6 +188,7 @@ class mig_network
const auto index = _storage->nodes.size();
auto& node = _storage->nodes.emplace_back();
node.children[0].data = node.children[1].data = node.children[2].data = _storage->inputs.size();
node.data[1].h2 = 1; // mark as PI
_storage->inputs.emplace_back( index );
return { index, 0 };
}
Expand All @@ -212,12 +214,12 @@ class mig_network

bool is_ci( node const& n ) const
{
return _storage->nodes[n].children[0].data == _storage->nodes[n].children[1].data && _storage->nodes[n].children[0].data == _storage->nodes[n].children[2].data;
return _storage->nodes[n].data[1].h2 == 1;
}

bool is_pi( node const& n ) const
{
return _storage->nodes[n].children[0].data == _storage->nodes[n].children[1].data && _storage->nodes[n].children[0].data == _storage->nodes[n].children[2].data && !is_constant( n );
return _storage->nodes[n].data[1].h2 == 1 && !is_constant( n );
}

bool constant_value( node const& n ) const
Expand Down
Loading

0 comments on commit 6efb33b

Please sign in to comment.