Skip to content

Commit

Permalink
flexible assumptions in aqfp_view (lsils#447)
Browse files Browse the repository at this point in the history
  • Loading branch information
lee30sonia authored Apr 23, 2021
1 parent 72906aa commit 7a772af
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 10 deletions.
77 changes: 69 additions & 8 deletions include/mockturtle/views/aqfp_view.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,15 @@ struct aqfp_view_params
bool update_on_modified{true};
bool update_on_delete{true};

/*! \brief Whether PIs need to be branched with splitters */
bool branch_pis{false};

/*! \brief Whether PIs need to be path-balanced */
bool balance_pis{false};

/*! \brief Whether POs need to be path-balanced */
bool balance_pos{true};

uint32_t splitter_capacity{4u};
uint32_t max_splitter_levels{2u};
};
Expand All @@ -75,9 +84,9 @@ struct aqfp_view_params
* fanin path is shorter, buffers have to be inserted to balance it.
* Buffers and splitters are essentially the same component in this technology.
*
* Some assumptions are made: (1) PIs do not need to be balanced (they are
* always available). (2) POs count toward the fanout sizes and have to be
* balanced.
* POs count toward the fanout sizes and always have to be branched. The assumptions
* on whether PIs should be branched and whether PIs and POs have to be balanced
* can be set in the parameters.
*
* The number of fanouts of each buffer is restricted to `splitter_capacity`.
* The additional depth of a node introduced by splitters is limited to at
Expand Down Expand Up @@ -125,7 +134,7 @@ class aqfp_view : public Ntk
};

aqfp_view( Ntk const& ntk, aqfp_view_params const& ps = {} )
: Ntk( ntk ), _fanout( ntk ), _external_ref_count( ntk ), _ps( ps ), _max_fanout( std::pow( ps.splitter_capacity, ps.max_splitter_levels ) ), _node_depth( this ), _depth_view( ntk, _node_depth )
: Ntk( ntk ), _fanout( ntk ), _external_ref_count( ntk ), _ps( ps ), _max_fanout( std::pow( ps.splitter_capacity, ps.max_splitter_levels ) ), _node_depth( this ), _depth_view( ntk, _node_depth, {/*count_complements*/false, /*pi_cost*/ps.branch_pis} )
{
static_assert( !has_foreach_fanout_v<Ntk> && "Ntk already has fanout interfaces" );
static_assert( !has_depth_v<Ntk> && !has_level_v<Ntk> && !has_update_levels_v<Ntk>, "Ntk already has depth interfaces" );
Expand Down Expand Up @@ -211,6 +220,12 @@ class aqfp_view : public Ntk
uint32_t num_buffers() const
{
uint32_t count = 0u;
if ( _ps.branch_pis )
{
this->foreach_pi( [&]( auto const& n ){
count += num_buffers( n );
});
}
this->foreach_gate( [&]( auto const& n ){
count += num_buffers( n );
});
Expand All @@ -226,7 +241,26 @@ class aqfp_view : public Ntk
if ( fanout_size( n ) > 0u )
{
assert( fanout_size( n ) == 1u );
return _external_ref_count[n] > 0u ? depth() - level( n ) : level( _fanout[n][0] ) - level( n ) - 1u;
if ( this->is_pi( n ) )
{
assert( level( n ) == 0u );
if ( _external_ref_count[n] > 0u ) /* PI -- PO */
{
return _ps.balance_pis && _ps.balance_pos ? depth() : 0u;
}
else /* PI -- gate */
{
return _ps.balance_pis ? level( _fanout[n][0] ) - 1u : 0u;
}
}
else if ( _external_ref_count[n] > 0u ) /* gate -- PO */
{
return _ps.balance_pos ? depth() - level( n ) : 0u;
}
else /* gate -- gate */
{
return level( _fanout[n][0] ) - level( n ) - 1u;
}
}
/* dangling */
return 0u;
Expand All @@ -251,10 +285,21 @@ class aqfp_view : public Ntk
}
if ( _external_ref_count[n] > 0u )
{
fanout_sizes.emplace_back( std::make_pair( depth() + 1u, _external_ref_count[n] ) );
if ( _ps.balance_pos )
{
fanout_sizes.emplace_back( std::make_pair( depth() + 1u, _external_ref_count[n] ) );
}
else /* don't balance POs, just need enough signals */
{
if ( _fanout[n].size() == 0u ) /* multiple PO refs but no gate fanout */
{
return std::ceil( float( _external_ref_count[n] - 1 ) / float( _ps.splitter_capacity - 1 ) );
}
/* else: check there are enough slots for POs later */
}
}
assert( fanout_sizes.size() > 1u );
assert( fanout_sizes[0].second == 0u );
assert( fanout_sizes[0].second == 0u ); // the first element should be (level(n)+1, 0)

/* count buffers from the highest level */
uint32_t count = 0u;
Expand Down Expand Up @@ -283,7 +328,23 @@ class aqfp_view : public Ntk
}
}
}
assert( fanout_sizes[0].second == 1 );
assert( fanout_sizes[0].second == 1 ); // the first element should be (level(n)+1, 1)

if ( !_ps.balance_pis && this->is_pi( n ) ) /* only branch PIs, but don't balance them */
{
/* remove the lowest balancing buffers, if any */
count -= fanout_sizes[1].first - fanout_sizes[0].first - 1;
}

if ( !_ps.balance_pos && _external_ref_count[n] > 0u )
{
auto slots = count * ( _ps.splitter_capacity - 1 ) + 1;
int32_t needed = fanout_size( n ) - slots;
if ( needed > 0 )
{
count += std::ceil( float( needed ) / float( _ps.splitter_capacity - 1 ) );
}
}

return count;
}
Expand Down
12 changes: 10 additions & 2 deletions include/mockturtle/views/depth_view.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ struct depth_view_params
{
/*! \brief Take complemented edges into account for depth computation. */
bool count_complements{false};

/*! \brief Whether PIs have costs. */
bool pi_cost{false};
};

/*! \brief Implements `depth` and `level` methods for networks.
Expand Down Expand Up @@ -213,10 +216,15 @@ class depth_view<Ntk, NodeCostFn, false> : public Ntk
}
this->set_visited( n, this->trav_id() );

if ( this->is_constant( n ) || this->is_pi( n ) )
if ( this->is_constant( n ) )
{
return _levels[n] = 0;
}
if ( this->is_pi( n ) )
{
assert( !_ps.pi_cost || _cost_fn( *this, n ) >= 1 );
return _levels[n] = _ps.pi_cost ? _cost_fn( *this, n ) - 1 : 0;
}

uint32_t level{0};
this->foreach_fanin( n, [&]( auto const& f ) {
Expand Down Expand Up @@ -255,7 +263,7 @@ class depth_view<Ntk, NodeCostFn, false> : public Ntk
void set_critical_path( node const& n )
{
_crit_path[n] = true;
if ( !this->is_constant( n ) && !this->is_pi( n ) )
if ( !this->is_constant( n ) && !( _ps.pi_cost && this->is_pi( n ) ) )
{
const auto lvl = _levels[n];
this->foreach_fanin( n, [&]( auto const& f ) {
Expand Down
37 changes: 37 additions & 0 deletions test/views/aqfp_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,40 @@ TEST_CASE( "chain of fanouts", "[aqfp_view]" )
CHECK( view.depth() == 8u );
CHECK( view.num_buffers() == 11u );
}

TEST_CASE( "branch but not balance PIs", "[aqfp_view]" )
{
mig_network mig;
auto const a = mig.create_pi();
auto const b = mig.create_pi(); // shared
auto const c = mig.create_pi(); // shared
auto const d = mig.create_pi();
auto const e = mig.create_pi(); // shared at higher level
auto const f = mig.create_pi(); // connects to two POs

auto const f1 = mig.create_maj( a, b, c );
auto const f2 = mig.create_maj( b, c, d );
auto const f3 = mig.create_and( f1, e );
auto const f4 = mig.create_and( f2, e );
mig.create_po( f3 );
mig.create_po( f4 );
mig.create_po( f );
mig.create_po( !f );

aqfp_view_params ps;
ps.branch_pis = true;
ps.balance_pis = false;
aqfp_view view( mig, ps );

CHECK( view.level( view.get_node( f1 ) ) == 2u );
CHECK( view.level( view.get_node( f2 ) ) == 2u );
CHECK( view.level( view.get_node( f3 ) ) == 3u );
CHECK( view.level( view.get_node( f4 ) ) == 3u );
CHECK( view.depth() == 3u );

CHECK( view.num_buffers( view.get_node( b ) ) == 1u );
CHECK( view.num_buffers( view.get_node( c ) ) == 1u );
CHECK( view.num_buffers( view.get_node( e ) ) == 1u );
CHECK( view.num_buffers( view.get_node( f ) ) == 1u );
CHECK( view.num_buffers() == 4u );
}

0 comments on commit 7a772af

Please sign in to comment.