mirror of https://github.com/YosysHQ/abc.git
Adding bindings to use ACD66 instead of generic ACD
This commit is contained in:
parent
44a65c23ed
commit
75abcd376b
|
|
@ -23,52 +23,92 @@
|
|||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
static constexpr bool use_generic_acd = true;
|
||||
|
||||
int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival )
|
||||
{
|
||||
using namespace acd;
|
||||
|
||||
ac_decomposition_params ps;
|
||||
ps.lut_size = lutSize;
|
||||
ps.try_no_late_arrival = static_cast<bool>( try_no_late_arrival ); /* TODO: additional tests */
|
||||
ac_decomposition_stats st;
|
||||
|
||||
ac_decomposition_impl acd( nVars, ps, &st );
|
||||
int val = acd.run( pTruth, *pdelay );
|
||||
|
||||
if ( val < 0 )
|
||||
if ( use_generic_acd )
|
||||
{
|
||||
*pdelay = 0;
|
||||
return -1;
|
||||
ac_decomposition_params ps;
|
||||
ps.lut_size = lutSize;
|
||||
ps.try_no_late_arrival = static_cast<bool>( try_no_late_arrival ); /* TODO: additional tests */
|
||||
ac_decomposition_stats st;
|
||||
|
||||
ac_decomposition_impl acd( nVars, ps, &st );
|
||||
int val = acd.run( pTruth, *pdelay );
|
||||
|
||||
if ( val < 0 )
|
||||
{
|
||||
*pdelay = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*pdelay = acd.get_profile();
|
||||
*cost = 2;
|
||||
|
||||
return val;
|
||||
}
|
||||
else
|
||||
{
|
||||
acd66_impl acd( nVars );
|
||||
int val = acd.run( pTruth, *pdelay );
|
||||
|
||||
*pdelay = acd.get_profile();
|
||||
*cost = st.num_luts;
|
||||
if ( val == 0 )
|
||||
{
|
||||
*pdelay = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return val;
|
||||
*pdelay = acd.get_profile();
|
||||
*cost = 2;
|
||||
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition )
|
||||
{
|
||||
using namespace acd;
|
||||
|
||||
ac_decomposition_params ps;
|
||||
ps.lut_size = lutSize;
|
||||
ac_decomposition_stats st;
|
||||
|
||||
ac_decomposition_impl acd( nVars, ps, &st );
|
||||
acd.run( pTruth, *pdelay );
|
||||
int val = acd.compute_decomposition();
|
||||
|
||||
if ( val < 0 )
|
||||
if ( use_generic_acd )
|
||||
{
|
||||
*pdelay = 0;
|
||||
return -1;
|
||||
ac_decomposition_params ps;
|
||||
ps.lut_size = lutSize;
|
||||
ac_decomposition_stats st;
|
||||
|
||||
ac_decomposition_impl acd( nVars, ps, &st );
|
||||
acd.run( pTruth, *pdelay );
|
||||
int val = acd.compute_decomposition();
|
||||
|
||||
if ( val < 0 )
|
||||
{
|
||||
*pdelay = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*pdelay = acd.get_profile();
|
||||
acd.get_decomposition( decomposition );
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
acd66_impl acd( nVars );
|
||||
acd.run( pTruth, *pdelay );
|
||||
int val = acd.compute_decomposition();
|
||||
|
||||
*pdelay = acd.get_profile();
|
||||
if ( val != 0 )
|
||||
{
|
||||
*pdelay = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
acd.get_decomposition( decomposition );
|
||||
return 0;
|
||||
*pdelay = acd.get_profile();
|
||||
|
||||
acd.get_decomposition( decomposition );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int acd66_evaluate( word * pTruth, unsigned nVars, int compute_decomposition )
|
||||
|
|
|
|||
|
|
@ -76,6 +76,34 @@ public:
|
|||
return find_decomposition() ? 1 : 0;
|
||||
}
|
||||
|
||||
/*! \brief Runs ACD 66 */
|
||||
int run( word* ptt, unsigned delay_profile )
|
||||
{
|
||||
assert( num_vars > 6 );
|
||||
|
||||
/* truth table is too large for the settings */
|
||||
if ( num_vars > max_num_vars || num_vars > 11 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t late_arriving = __builtin_popcount( delay_profile );
|
||||
|
||||
/* too many late arriving variables */
|
||||
if ( late_arriving > 5 )
|
||||
return 0;
|
||||
|
||||
/* convert to static TT */
|
||||
init_truth_table( ptt );
|
||||
best_tt = start_tt;
|
||||
|
||||
/* permute late arriving variables to be the least significant */
|
||||
reposition_late_arriving_variables( delay_profile, late_arriving );
|
||||
|
||||
/* run ACD trying different bound sets and free sets */
|
||||
return find_decomposition_offset( late_arriving ) ? ( delay_profile == 0 ? 2 : 1 ) : 0;
|
||||
}
|
||||
|
||||
int compute_decomposition()
|
||||
{
|
||||
if ( best_multiplicity == UINT32_MAX )
|
||||
|
|
@ -102,17 +130,17 @@ public:
|
|||
return bs_support_size + best_free_set + 1 + ( best_multiplicity > 2 ? 1 : 0 );
|
||||
}
|
||||
|
||||
/* contains a 1 for BS variables */
|
||||
/* contains a 1 for FS variables */
|
||||
unsigned get_profile()
|
||||
{
|
||||
unsigned profile = 0;
|
||||
|
||||
if ( bs_support_size == UINT32_MAX )
|
||||
if ( best_multiplicity == UINT32_MAX )
|
||||
return -1;
|
||||
|
||||
for ( uint32_t i = 0; i < bs_support_size; ++i )
|
||||
for ( uint32_t i = 0; i < best_free_set; ++i )
|
||||
{
|
||||
profile |= 1 << permutations[best_free_set + bs_support[i]];
|
||||
profile |= 1 << permutations[i];
|
||||
}
|
||||
|
||||
return profile;
|
||||
|
|
@ -143,6 +171,22 @@ private:
|
|||
return false;
|
||||
}
|
||||
|
||||
bool find_decomposition_offset( uint32_t offset )
|
||||
{
|
||||
best_multiplicity = UINT32_MAX;
|
||||
best_free_set = UINT32_MAX;
|
||||
|
||||
/* find ACD "66" for different number of variables in the free set */
|
||||
for ( uint32_t i = std::max( num_vars - 6, offset ); i <= 5; ++i )
|
||||
{
|
||||
if ( find_decomposition_bs_offset( i, offset ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
best_multiplicity = UINT32_MAX;
|
||||
return false;
|
||||
}
|
||||
|
||||
void init_truth_table( word* ptt )
|
||||
{
|
||||
uint32_t const num_blocks = ( num_vars <= 6 ) ? 1 : ( 1 << ( num_vars - 6 ) );
|
||||
|
|
@ -190,13 +234,13 @@ private:
|
|||
return size;
|
||||
}
|
||||
|
||||
inline bool combinations_next( uint32_t k, uint32_t* pComb, uint32_t* pInvPerm, STT& tt )
|
||||
inline bool combinations_next( uint32_t k, uint32_t offset, uint32_t* pComb, uint32_t* pInvPerm, STT& tt )
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for ( i = k - 1; pComb[i] == num_vars - k + i; --i )
|
||||
{
|
||||
if ( i == 0 )
|
||||
if ( i == offset )
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -254,7 +298,7 @@ private:
|
|||
best_multiplicity = cost;
|
||||
int res = check_shared_set( tt );
|
||||
|
||||
if ( res > 0 )
|
||||
if ( res >= 0 )
|
||||
{
|
||||
best_tt = tt;
|
||||
for ( uint32_t i = 0; i < num_vars; ++i )
|
||||
|
|
@ -267,7 +311,96 @@ private:
|
|||
return true;
|
||||
}
|
||||
}
|
||||
} while ( combinations_next( free_set_size, pComb, pInvPerm, tt ) );
|
||||
} while ( combinations_next( free_set_size, 0, pComb, pInvPerm, tt ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool find_decomposition_bs_offset( uint32_t free_set_size, uint32_t offset )
|
||||
{
|
||||
STT tt = best_tt;
|
||||
|
||||
/* works up to 16 input truth tables */
|
||||
assert( num_vars <= 16 );
|
||||
best_free_set = free_set_size;
|
||||
|
||||
/* special case */
|
||||
if ( free_set_size == offset )
|
||||
{
|
||||
uint32_t cost = column_multiplicity( tt, free_set_size );
|
||||
if ( cost == 2 )
|
||||
{
|
||||
best_tt = tt;
|
||||
best_multiplicity = cost;
|
||||
return true;
|
||||
}
|
||||
else if ( cost <= 4 && free_set_size < 5 )
|
||||
{
|
||||
/* look for a shared variable */
|
||||
best_multiplicity = cost;
|
||||
int res = check_shared_set( tt );
|
||||
|
||||
if ( res >= 0 )
|
||||
{
|
||||
best_tt = tt;
|
||||
/* move shared variable as the most significative one */
|
||||
swap_inplace_local( best_tt, res, num_vars - 1 );
|
||||
std::swap( permutations[res], permutations[num_vars - 1] );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* init combinations */
|
||||
uint32_t pComb[16], pInvPerm[16];
|
||||
for ( uint32_t i = 0; i < num_vars; ++i )
|
||||
{
|
||||
pComb[i] = pInvPerm[i] = i;
|
||||
}
|
||||
|
||||
/* enumerate combinations */
|
||||
do
|
||||
{
|
||||
uint32_t cost = column_multiplicity( tt, free_set_size );
|
||||
if ( cost == 2 )
|
||||
{
|
||||
best_tt = tt;
|
||||
best_multiplicity = cost;
|
||||
for ( uint32_t i = 0; i < num_vars; ++i )
|
||||
{
|
||||
pInvPerm[i] = permutations[pComb[i]];
|
||||
}
|
||||
for ( uint32_t i = 0; i < num_vars; ++i )
|
||||
{
|
||||
permutations[i] = pInvPerm[i];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if ( cost <= 4 && free_set_size < 5 )
|
||||
{
|
||||
/* look for a shared variable */
|
||||
best_multiplicity = cost;
|
||||
int res = check_shared_set( tt );
|
||||
|
||||
if ( res >= 0 )
|
||||
{
|
||||
best_tt = tt;
|
||||
for ( uint32_t i = 0; i < num_vars; ++i )
|
||||
{
|
||||
pInvPerm[i] = permutations[pComb[i]];
|
||||
}
|
||||
for ( uint32_t i = 0; i < num_vars; ++i )
|
||||
{
|
||||
permutations[i] = pInvPerm[i];
|
||||
}
|
||||
/* move shared variable as the most significative one */
|
||||
swap_inplace_local( best_tt, res, num_vars - 1 );
|
||||
std::swap( permutations[res], permutations[num_vars - 1] );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} while ( combinations_next( free_set_size, offset, pComb, pInvPerm, tt ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -552,6 +685,26 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
inline void reposition_late_arriving_variables( unsigned delay_profile, uint32_t late_arriving )
|
||||
{
|
||||
uint32_t k = 0;
|
||||
for ( uint32_t i = 0; i < late_arriving; ++i )
|
||||
{
|
||||
while ( ( ( delay_profile >> k ) & 1 ) == 0 )
|
||||
++k;
|
||||
|
||||
if ( permutations[i] == k )
|
||||
{
|
||||
++k;
|
||||
continue;
|
||||
}
|
||||
|
||||
std::swap( permutations[i], permutations[k] );
|
||||
swap_inplace_local( best_tt, i, k );
|
||||
++k;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TT_type>
|
||||
void local_extend_to( TT_type& tt, uint32_t real_num_vars )
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue