Skip to content

Commit

Permalink
Improved code quality and enabled the use of statistics in both new M…
Browse files Browse the repository at this point in the history
…IG inverter algorithms (lsils#613)

* Improved code quality and enabled the use of statistics

* Added newlines at the end of files
  • Loading branch information
marcelwa committed Jun 28, 2023
1 parent 84711b2 commit 975cd50
Show file tree
Hide file tree
Showing 4 changed files with 232 additions and 117 deletions.
139 changes: 89 additions & 50 deletions include/mockturtle/algorithms/mig_inv_optimization.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,22 @@
\brief MIG inverter optimization
\author Bugra Eryilmaz
\author Marcel Walter
*/

#pragma once

#include "../networks/mig.hpp"
#include "../networks/storage.hpp"
#include "../utils/stopwatch.hpp"
#include "../views/fanout_view.hpp"

#include <algorithm>
#include <cstdint>
#include <iostream>
#include <optional>
#include <memory>
#include <type_traits>
#include <vector>

namespace mockturtle
{
Expand All @@ -49,13 +55,13 @@ struct mig_inv_optimization_stats
stopwatch<>::duration time_total{ 0 };

/*! \brief Number of one level inverted nodes. */
int num_inverted{ 0 };
int32_t num_inverted{ 0 };

/*! \brief Number of two level inverted nodes. */
int num_two_level_inverted{ 0 };
int32_t num_two_level_inverted{ 0 };

/*! \brief Total gain in terms of number of inverters. */
int total_gain{ 0 };
int32_t total_gain{ 0 };
};

namespace detail
Expand Down Expand Up @@ -85,39 +91,43 @@ class mig_inv_optimization_impl
while ( changed )
{
changed = false;
ntk.foreach_gate( [&]( auto const& f ) {
int _gain = gain( f );
if ( _gain > 0 )
ntk.foreach_gate( [this, &changed]( auto const& f ) {
int32_t gain = calculate_gain( f );
if ( gain > 0 )
{
st.num_inverted++;
st.total_gain += _gain;
st.total_gain += gain;
changed = true;
invert_node( f );
}
else if ( two_level_gain( f ) > 0 )
{
st.num_two_level_inverted++;
st.total_gain += _gain;
st.total_gain += gain;
changed = true;
std::vector<node<Ntk>> _nodes_to_invert;
ntk.foreach_fanout( f, [&]( auto const& parent ) {
std::vector<node<Ntk>> nodes_to_invert{};
ntk.foreach_fanout( f, [this, &f, &nodes_to_invert]( auto const& parent ) {
// convert each fanout if inverting it makes sense
int _subgain = 0;
_subgain += gain( parent );
int32_t sub_gain = 0;
sub_gain += calculate_gain( parent );
if ( is_complemented_parent( parent, f ) )
{
// if the connection between f and parent is complemented, we counted the same gain twice which will not be inverted at all
_subgain -= 2;
sub_gain -= 2;
}
else
{
// if the connection between f and parent is not complemented, we counted the same negative gain twice which will not be inverted at all
_subgain += 2;
if ( _subgain > 0 )
sub_gain += 2;
}
if ( sub_gain > 0 )
{
st.total_gain += _subgain;
_nodes_to_invert.push_back( parent );
st.total_gain += sub_gain;
nodes_to_invert.push_back( parent );
}
} );
invert_node( f );
for ( auto const& n : _nodes_to_invert )
for ( auto const& n : nodes_to_invert )
{
invert_node( n );
}
Expand All @@ -127,79 +137,95 @@ class mig_inv_optimization_impl
}

/*! \brief calculates the decrease in the number of inverters if this node is inverted and all fanouts that is beneficial also inverted */
int two_level_gain( node<Ntk> n )
int32_t two_level_gain( node<Ntk> n )
{
int _gain = 0;
_gain += gain( n );
int32_t gain = 0;
gain += calculate_gain( n );

ntk.foreach_fanout( n, [&]( auto const& f ) {
int _subgain = 0;
_subgain += gain( f );
ntk.foreach_fanout( n, [this, &gain, &n]( auto const& f ) {
int32_t sub_gain = 0;
sub_gain += calculate_gain( f );
if ( is_complemented_parent( f, n ) )
{
// if the connection between f and parent is complemented, we counted the same gain twice which will not be inverted at all
_subgain -= 2;
sub_gain -= 2;
}
else
{
// if the connection between f and parent is not complemented, we counted the same negative gain twice which will not be inverted at all
_subgain += 2;
sub_gain += 2;
}

// convert each fanout if inverting it makes sense
if ( _subgain > 0 )
if ( sub_gain > 0 )
{
_gain += _subgain;
gain += sub_gain;
}
} );

return _gain;
return gain;
}

/*! \brief calculates the decrease in the number of inverters if this node is inverted */
int gain( node<Ntk> n )
int32_t calculate_gain( node<Ntk> n )
{
if ( ntk.is_dead( n ) )
{
std::cerr << "node" << n << " is dead\n";
return 0;
}
int _gain = 0;
int32_t gain = 0;

// count the inverted and non-inverted fanins
ntk.foreach_fanin( n, [&]( auto const& f ) {
ntk.foreach_fanin( n, [this, &gain]( auto const& f ) {
if ( ntk.is_constant( ntk.get_node( f ) ) )
{
return;
update_gain_is_complemented( f, _gain );
}
update_gain_is_complemented( f, gain );
} );

// count the inverted and non-inverted fanouts
ntk.foreach_fanout( n, [&]( auto const& parent ) {
ntk.foreach_fanout( n, [this, &n, &gain]( auto const& parent ) {
if ( is_complemented_parent( parent, n ) )
_gain++;
{
gain++;
}
else
_gain--;
{
gain--;
}
} );

// count the inverted and non-inverted POs
ntk.foreach_po( [&]( auto const& f ) {
ntk.foreach_po( [this, &n, &gain]( auto const& f ) {
if ( ntk.get_node( f ) == n )
update_gain_is_complemented( f, _gain );
{
update_gain_is_complemented( f, gain );
}
} );
return _gain;
return gain;
}

/*! \brief increases the gain if signal f is complemented, decreases otherwise. */
void update_gain_is_complemented( signal<Ntk> f, int& _gain )
void update_gain_is_complemented( signal<Ntk> f, int32_t& gain )
{
if ( ntk.is_complemented( f ) )
_gain++;
{
gain++;
}
else
_gain--;
{
gain--;
}
}

/*! \brief checks if parent is parent of child and returns if the connection is complemented. */
bool is_complemented_parent( node<Ntk> parent, node<Ntk> child )
{
bool ret = false;
bool changed = false;
ntk.foreach_fanin( parent, [&]( auto const& f ) {
ntk.foreach_fanin( parent, [this, &child, &ret, &changed]( auto const& f ) {
if ( ntk.get_node( f ) == child )
{
changed = true;
Expand All @@ -219,11 +245,17 @@ class mig_inv_optimization_impl
signal<Ntk> a, b, c;
ntk.foreach_fanin( n, [&]( auto const& f, auto idx ) {
if ( idx == 0 )
{
a = f;
}
else if ( idx == 1 )
{
b = f;
}
else if ( idx == 2 )
{
c = f;
}
} );
signal<Ntk> new_node = !create_maj_directly( !a, !b, !c );
ntk.substitute_node( n, new_node );
Expand All @@ -240,24 +272,32 @@ class mig_inv_optimization_impl
{
std::swap( a, b );
if ( b.index > c.index )
{
std::swap( b, c );
}
if ( a.index > b.index )
{
std::swap( a, b );
}
}
else
{
if ( b.index > c.index )
{
std::swap( b, c );
}
if ( a.index > b.index )
{
std::swap( a, b );
}
}

/* trivial cases */
if ( a.index == b.index )
{
return ( a.complement == b.complement ) ? a : c;
}
else if ( b.index == c.index )
if ( b.index == c.index )
{
return ( b.complement == c.complement ) ? b : a;
}
Expand All @@ -268,13 +308,12 @@ class mig_inv_optimization_impl
nd.children[2] = c;

/* structural hashing */
const auto it = ntk._storage->hash.find( nd );
if ( it != ntk._storage->hash.end() )
if ( auto const it = ntk._storage->hash.find( nd ); it != ntk._storage->hash.end() )
{
return { it->second, 0 };
}

const auto index = ntk._storage->nodes.size();
auto const index = ntk._storage->nodes.size();

if ( index >= .9 * ntk._storage->nodes.capacity() )
{
Expand All @@ -300,7 +339,7 @@ class mig_inv_optimization_impl
}

private:
Ntk& ntk;
fanout_view<Ntk> ntk;
mig_inv_optimization_stats& st;
};

Expand Down Expand Up @@ -332,8 +371,8 @@ template<class Ntk>
void mig_inv_optimization( Ntk& ntk, mig_inv_optimization_stats* pst = nullptr )
{
static_assert( is_network_type_v<Ntk>, "Ntk is not a network type" );
static_assert( std::is_same_v<typename Ntk::base_type, mig_network>, "Ntk is not an MIG network" );
static_assert( has_foreach_fanin_v<Ntk>, "Ntk does not implement the foreach_fanin method" );
static_assert( has_foreach_fanout_v<Ntk>, "Ntk does not implement the foreach_fanout method" );
static_assert( has_substitute_node_v<Ntk>, "Ntk does not implement the substitute_node method" );
static_assert( has_replace_in_outputs_v<Ntk>, "Ntk does not implement the replace_in_outputs method" );
static_assert( has_is_complemented_v<Ntk>, "Ntk does not implement the is_complemented method" );
Expand Down
Loading

0 comments on commit 975cd50

Please sign in to comment.