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,10 +23,14 @@
|
||||||
|
|
||||||
ABC_NAMESPACE_IMPL_START
|
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 )
|
int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival )
|
||||||
{
|
{
|
||||||
using namespace acd;
|
using namespace acd;
|
||||||
|
|
||||||
|
if ( use_generic_acd )
|
||||||
|
{
|
||||||
ac_decomposition_params ps;
|
ac_decomposition_params ps;
|
||||||
ps.lut_size = lutSize;
|
ps.lut_size = lutSize;
|
||||||
ps.try_no_late_arrival = static_cast<bool>( try_no_late_arrival ); /* TODO: additional tests */
|
ps.try_no_late_arrival = static_cast<bool>( try_no_late_arrival ); /* TODO: additional tests */
|
||||||
|
|
@ -42,15 +46,34 @@ int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay,
|
||||||
}
|
}
|
||||||
|
|
||||||
*pdelay = acd.get_profile();
|
*pdelay = acd.get_profile();
|
||||||
*cost = st.num_luts;
|
*cost = 2;
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
acd66_impl acd( nVars );
|
||||||
|
int val = acd.run( pTruth, *pdelay );
|
||||||
|
|
||||||
|
if ( val == 0 )
|
||||||
|
{
|
||||||
|
*pdelay = 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pdelay = acd.get_profile();
|
||||||
|
*cost = 2;
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition )
|
int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition )
|
||||||
{
|
{
|
||||||
using namespace acd;
|
using namespace acd;
|
||||||
|
|
||||||
|
if ( use_generic_acd )
|
||||||
|
{
|
||||||
ac_decomposition_params ps;
|
ac_decomposition_params ps;
|
||||||
ps.lut_size = lutSize;
|
ps.lut_size = lutSize;
|
||||||
ac_decomposition_stats st;
|
ac_decomposition_stats st;
|
||||||
|
|
@ -65,11 +88,28 @@ int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay,
|
||||||
return -1;
|
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();
|
||||||
|
|
||||||
|
if ( val != 0 )
|
||||||
|
{
|
||||||
|
*pdelay = 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
*pdelay = acd.get_profile();
|
*pdelay = acd.get_profile();
|
||||||
|
|
||||||
acd.get_decomposition( decomposition );
|
acd.get_decomposition( decomposition );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int acd66_evaluate( word * pTruth, unsigned nVars, int compute_decomposition )
|
int acd66_evaluate( word * pTruth, unsigned nVars, int compute_decomposition )
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,34 @@ public:
|
||||||
return find_decomposition() ? 1 : 0;
|
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()
|
int compute_decomposition()
|
||||||
{
|
{
|
||||||
if ( best_multiplicity == UINT32_MAX )
|
if ( best_multiplicity == UINT32_MAX )
|
||||||
|
|
@ -102,17 +130,17 @@ public:
|
||||||
return bs_support_size + best_free_set + 1 + ( best_multiplicity > 2 ? 1 : 0 );
|
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 get_profile()
|
||||||
{
|
{
|
||||||
unsigned profile = 0;
|
unsigned profile = 0;
|
||||||
|
|
||||||
if ( bs_support_size == UINT32_MAX )
|
if ( best_multiplicity == UINT32_MAX )
|
||||||
return -1;
|
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;
|
return profile;
|
||||||
|
|
@ -143,6 +171,22 @@ private:
|
||||||
return false;
|
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 )
|
void init_truth_table( word* ptt )
|
||||||
{
|
{
|
||||||
uint32_t const num_blocks = ( num_vars <= 6 ) ? 1 : ( 1 << ( num_vars - 6 ) );
|
uint32_t const num_blocks = ( num_vars <= 6 ) ? 1 : ( 1 << ( num_vars - 6 ) );
|
||||||
|
|
@ -190,13 +234,13 @@ private:
|
||||||
return size;
|
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;
|
uint32_t i;
|
||||||
|
|
||||||
for ( i = k - 1; pComb[i] == num_vars - k + i; --i )
|
for ( i = k - 1; pComb[i] == num_vars - k + i; --i )
|
||||||
{
|
{
|
||||||
if ( i == 0 )
|
if ( i == offset )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -254,7 +298,7 @@ private:
|
||||||
best_multiplicity = cost;
|
best_multiplicity = cost;
|
||||||
int res = check_shared_set( tt );
|
int res = check_shared_set( tt );
|
||||||
|
|
||||||
if ( res > 0 )
|
if ( res >= 0 )
|
||||||
{
|
{
|
||||||
best_tt = tt;
|
best_tt = tt;
|
||||||
for ( uint32_t i = 0; i < num_vars; ++i )
|
for ( uint32_t i = 0; i < num_vars; ++i )
|
||||||
|
|
@ -267,7 +311,96 @@ private:
|
||||||
return true;
|
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;
|
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>
|
template<typename TT_type>
|
||||||
void local_extend_to( TT_type& tt, uint32_t real_num_vars )
|
void local_extend_to( TT_type& tt, uint32_t real_num_vars )
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue