mirror of https://github.com/YosysHQ/abc.git
commit
b10d000c7a
|
|
@ -19541,7 +19541,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
If_ManSetDefaultPars( pPars );
|
||||
pPars->pLutLib = (If_LibLut_t *)Abc_FrameReadLibLut();
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYZDEWSJqaflepmrsdbgxyuojiktncvh" ) ) != EOF )
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYUZDEWSJqaflepmrsdbgxyuojiktncvh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
|
|
@ -19657,6 +19657,18 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
if ( pPars->nAndDelay < 0 )
|
||||
goto usage;
|
||||
break;
|
||||
case 'U':
|
||||
if ( globalUtilOptind >= argc )
|
||||
{
|
||||
Abc_Print( -1, "Command line switch \"-U\" should be followed by a positive integer 3, 4, 5, or 6.\n" );
|
||||
goto usage;
|
||||
}
|
||||
pPars->nLutDecSize = atoi(argv[globalUtilOptind]);
|
||||
pPars->fUserLut2D = 1;
|
||||
globalUtilOptind++;
|
||||
if ( pPars->nLutDecSize < 3 || pPars->nLutDecSize > 6 )
|
||||
goto usage;
|
||||
break;
|
||||
case 'Z':
|
||||
if ( globalUtilOptind >= argc )
|
||||
{
|
||||
|
|
@ -19727,7 +19739,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
globalUtilOptind++;
|
||||
if ( strlen(pPars->pLutStruct) != 2 && strlen(pPars->pLutStruct) != 3 )
|
||||
{
|
||||
Abc_Print( -1, "Command line switch \"-J\" should be followed by a 2- or 3-char string (e.g. \"66\" or \"666\").\n" );
|
||||
Abc_Print( -1, "Command line switch \"-J\" should be followed by a 2-char string (e.g. \"44\" or \"66\" \").\n" );
|
||||
goto usage;
|
||||
}
|
||||
break;
|
||||
|
|
@ -19910,7 +19922,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
}
|
||||
if ( pPars->fEnableStructN )
|
||||
{
|
||||
pPars->pFuncCell = pPars->fDelayOptLut ? NULL : If_CutPerformCheck66;
|
||||
pPars->pFuncCell = pPars->fDelayOptLut ? NULL : If_CutPerformCheckXX;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -19919,7 +19931,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
pPars->fCutMin = 1;
|
||||
}
|
||||
|
||||
if ( pPars->fUserLutDec )
|
||||
if ( pPars->fUserLutDec || pPars->fUserLut2D )
|
||||
{
|
||||
if ( pPars->nLutDecSize == 0 )
|
||||
{
|
||||
|
|
@ -19954,7 +19966,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
pPars->pLutLib = NULL;
|
||||
}
|
||||
// modify for delay optimization
|
||||
if ( pPars->fDelayOpt || pPars->fDsdBalance || pPars->fDelayOptLut || pPars->fUserLutDec )
|
||||
if ( pPars->fDelayOpt || pPars->fDsdBalance || pPars->fDelayOptLut || pPars->fUserLutDec || pPars->fUserLut2D )
|
||||
{
|
||||
pPars->fTruth = 1;
|
||||
pPars->fCutMin = 1;
|
||||
|
|
@ -20100,7 +20112,7 @@ usage:
|
|||
sprintf(LutSize, "library" );
|
||||
else
|
||||
sprintf(LutSize, "%d", pPars->nLutSize );
|
||||
Abc_Print( -2, "usage: if [-KCFAGRNTXYZ num] [-DEW float] [-S str] [-qarlepmsdbgxyuojiktncvh]\n" );
|
||||
Abc_Print( -2, "usage: if [-KCFAGRNTXYUZ num] [-DEW float] [-SJ str] [-qarlepmsdbgxyuojiktncvh]\n" );
|
||||
Abc_Print( -2, "\t performs FPGA technology mapping of the network\n" );
|
||||
Abc_Print( -2, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize );
|
||||
Abc_Print( -2, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax );
|
||||
|
|
@ -20112,6 +20124,7 @@ usage:
|
|||
Abc_Print( -2, "\t-T num : the type of LUT structures [default = any]\n" );
|
||||
Abc_Print( -2, "\t-X num : delay of AND-gate in LUT library units [default = %d]\n", pPars->nAndDelay );
|
||||
Abc_Print( -2, "\t-Y num : area of AND-gate in LUT library units [default = %d]\n", pPars->nAndArea );
|
||||
Abc_Print( -2, "\t-U num : the number of LUT inputs for delay-driven LUT decomposition [default = not used]\n" );
|
||||
Abc_Print( -2, "\t-Z num : the number of LUT inputs for delay-driven LUT decomposition [default = not used]\n" );
|
||||
Abc_Print( -2, "\t-D float : sets the delay constraint for the mapping [default = %s]\n", Buffer );
|
||||
Abc_Print( -2, "\t-E float : sets epsilon used for tie-breaking [default = %f]\n", pPars->Epsilon );
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars )
|
|||
pPars->pTimesReq = Abc_NtkGetCoRequiredFloats(pNtk);
|
||||
|
||||
// update timing info to reflect logic level
|
||||
if ( (pPars->fDelayOpt || pPars->fDsdBalance || pPars->fUserRecLib || pPars->fUserSesLib || pPars->fUserLutDec) && pNtk->pManTime )
|
||||
if ( (pPars->fDelayOpt || pPars->fDsdBalance || pPars->fUserRecLib || pPars->fUserSesLib || pPars->fUserLutDec || pPars->fUserLut2D ) && pNtk->pManTime )
|
||||
{
|
||||
int c;
|
||||
if ( pNtk->AndGateDelay == 0.0 )
|
||||
|
|
@ -433,8 +433,8 @@ Hop_Obj_t * Abc_NodeBuildFromMini( Hop_Man_t * pMan, If_Man_t * p, If_Cut_t * pC
|
|||
SideEffects []
|
||||
SeeAlso []
|
||||
***********************************************************************/
|
||||
void Abc_DecRecordToHop( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Cut_t * pCutBest, If_Obj_t * pIfObj, Vec_Int_t * vCover, Abc_Obj_t * pNodeTop )
|
||||
{
|
||||
void Abc_DecRecordToHop( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Cut_t * pCutBest, If_Obj_t * pIfObj, Vec_Int_t * vCover, Abc_Obj_t * pNodeTop )
|
||||
{
|
||||
extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory );
|
||||
assert( !pIfMan->pPars->fUseTtPerm );
|
||||
|
||||
|
|
@ -460,7 +460,15 @@ Hop_Obj_t * Abc_NodeBuildFromMini( Hop_Man_t * pMan, If_Man_t * p, If_Cut_t * pC
|
|||
|
||||
// perform LUT-decomposition and return the LUT-structure
|
||||
unsigned char decompArray[92];
|
||||
int val = acd_decompose( pTruth, pCutBest->nLeaves, pIfMan->pPars->nLutDecSize, &(delayProfile), decompArray );
|
||||
int val;
|
||||
if ( pIfMan->pPars->fUserLutDec )
|
||||
{
|
||||
val = acd_decompose( pTruth, pCutBest->nLeaves, pIfMan->pPars->nLutDecSize, &(delayProfile), decompArray );
|
||||
}
|
||||
else
|
||||
{
|
||||
val = acd2_decompose( pTruth, pCutBest->nLeaves, pIfMan->pPars->nLutDecSize, &(delayProfile), decompArray );
|
||||
}
|
||||
assert( val == 0 );
|
||||
|
||||
// convert the LUT-structure into a set of logic nodes in Abc_Ntk_t
|
||||
|
|
@ -473,7 +481,7 @@ Hop_Obj_t * Abc_NodeBuildFromMini( Hop_Man_t * pMan, If_Man_t * p, If_Cut_t * pC
|
|||
word *tt;
|
||||
Abc_Obj_t *pNewNodes[5];
|
||||
|
||||
/* create intermediate LUTs*/
|
||||
/* create intermediate LUTs */
|
||||
assert( decompArray[1] <= 6 );
|
||||
Abc_Obj_t * pFanin;
|
||||
for ( i = 0; i < decompArray[1]; ++i )
|
||||
|
|
@ -537,7 +545,7 @@ Hop_Obj_t * Abc_NodeBuildFromMini( Hop_Man_t * pMan, If_Man_t * p, If_Cut_t * pC
|
|||
|
||||
/* check correct read */
|
||||
assert( byte_p == decompArray[0] );
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
|
|
@ -577,14 +585,15 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t
|
|||
pNodeNew = Abc_NtkCreateNode( pNtkNew );
|
||||
// if ( pIfMan->pPars->pLutLib && pIfMan->pPars->pLutLib->fVarPinDelays )
|
||||
if ( !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDelayOptLut && !pIfMan->pPars->fDsdBalance && !pIfMan->pPars->fUseTtPerm &&
|
||||
!pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserLutDec && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->fUserSesLib && !pIfMan->pPars->nGateSize )
|
||||
!pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserLutDec && !pIfMan->pPars->fUserLut2D && !pIfMan->pPars->fUserRecLib &&
|
||||
!pIfMan->pPars->fUserSesLib && !pIfMan->pPars->nGateSize )
|
||||
If_CutRotatePins( pIfMan, pCutBest );
|
||||
if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
|
||||
{
|
||||
If_CutForEachLeafReverse( pIfMan, pCutBest, pIfLeaf, i )
|
||||
Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) );
|
||||
}
|
||||
else if ( pIfMan->pPars->fUserLutDec )
|
||||
else if ( pIfMan->pPars->fUserLutDec || pIfMan->pPars->fUserLut2D )
|
||||
{
|
||||
If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i )
|
||||
Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover);
|
||||
|
|
@ -642,7 +651,7 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t
|
|||
extern Hop_Obj_t * Abc_RecToHop3( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj );
|
||||
pNodeNew->pData = Abc_RecToHop3( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, pIfObj );
|
||||
}
|
||||
else if ( pIfMan->pPars->fUserLutDec )
|
||||
else if ( pIfMan->pPars->fUserLutDec || pIfMan->pPars->fUserLut2D )
|
||||
{
|
||||
extern void Abc_DecRecordToHop( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj, Vec_Int_t * vMemory, Abc_Obj_t * pNodeTop );
|
||||
Abc_DecRecordToHop( pNtkNew, pIfMan, pCutBest, pIfObj, vCover, pNodeNew );
|
||||
|
|
|
|||
|
|
@ -118,11 +118,12 @@ public:
|
|||
}
|
||||
if ( late_arriving > ps.max_free_set_vars )
|
||||
{
|
||||
ps.max_free_set_vars = late_arriving;
|
||||
return -1; /* on average avoiding this computation leads to better quality */
|
||||
// ps.max_free_set_vars = late_arriving;
|
||||
}
|
||||
|
||||
/* return a high cost if too many late arriving variables */
|
||||
if ( late_arriving > ps.lut_size - 1 || late_arriving > ps.max_free_set_vars )
|
||||
if ( late_arriving > ps.lut_size - 1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -231,7 +232,7 @@ private:
|
|||
best_cost = multiplicity + additional_cost;
|
||||
best_free_set = i;
|
||||
|
||||
if ( !ps.use_first )
|
||||
if ( !ps.use_first && multiplicity > 2 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
@ -269,7 +270,7 @@ private:
|
|||
best_cost = multiplicity + additional_cost;
|
||||
best_free_set = i;
|
||||
|
||||
if ( !ps.use_first )
|
||||
if ( !ps.use_first && multiplicity > 2 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
@ -477,6 +478,13 @@ private:
|
|||
pComb[i] = pInvPerm[i] = i;
|
||||
}
|
||||
|
||||
/* early bail-out conditions */
|
||||
uint32_t bail_multiplicity = 2;
|
||||
if ( best_multiplicity < UINT32_MAX )
|
||||
{
|
||||
bail_multiplicity = ( best_multiplicity >> 1 ) + ( best_multiplicity & 1 );
|
||||
}
|
||||
|
||||
/* enumerate combinations */
|
||||
do
|
||||
{
|
||||
|
|
@ -489,6 +497,11 @@ private:
|
|||
{
|
||||
bestPerm[i] = pComb[i];
|
||||
}
|
||||
|
||||
if ( best_cost <= bail_multiplicity )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while ( combinations_offset_next( free_set_size, offset, pComb, pInvPerm, tt ) );
|
||||
|
||||
|
|
@ -632,13 +645,10 @@ private:
|
|||
uint32_t k = 0;
|
||||
for ( uint32_t j = 0; j < num_vars - best_free_set; ++j )
|
||||
{
|
||||
if ( !kitty::has_var( tt, j ) )
|
||||
continue;
|
||||
|
||||
if ( !kitty::has_var( tt, care, j ) )
|
||||
{
|
||||
/* fix truth table */
|
||||
adjust_truth_table_on_dc( tt, care, j );
|
||||
adjust_truth_table_on_dc( tt, care, tt.num_vars(), j );
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -788,7 +798,14 @@ private:
|
|||
}
|
||||
}
|
||||
support_minimization_encodings = std::vector<std::array<uint32_t, 2>>( num_combs );
|
||||
generate_support_minimization_encodings_rec<false>( 0, 0, 0, count );
|
||||
generate_support_minimization_encodings_rec<false, true>( 0, 0, 0, count );
|
||||
}
|
||||
else if ( best_multiplicity > 8 )
|
||||
{
|
||||
/* combinations are 2^(mu - 1) */
|
||||
num_combs = 1u << ( best_multiplicity - 1 );
|
||||
support_minimization_encodings = std::vector<std::array<uint32_t, 2>>( num_combs );
|
||||
generate_support_minimization_encodings_rec<false, false>( 0, 0, 0, count );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -798,18 +815,18 @@ private:
|
|||
num_combs = ( num_combs << 1 ) + num_combs;
|
||||
}
|
||||
support_minimization_encodings = std::vector<std::array<uint32_t, 2>>( num_combs );
|
||||
generate_support_minimization_encodings_rec<true>( 0, 0, 0, count );
|
||||
generate_support_minimization_encodings_rec<true, false>( 0, 0, 0, count );
|
||||
}
|
||||
|
||||
assert( count == num_combs );
|
||||
}
|
||||
|
||||
template<bool enable_dcset>
|
||||
template<bool enable_dcset, bool equal_size_partition>
|
||||
void generate_support_minimization_encodings_rec( uint32_t onset, uint32_t offset, uint32_t var, uint32_t& count )
|
||||
{
|
||||
if ( var == best_multiplicity )
|
||||
{
|
||||
if ( !enable_dcset )
|
||||
if ( equal_size_partition )
|
||||
{
|
||||
/* sets must be equally populated */
|
||||
if ( __builtin_popcount( onset ) != __builtin_popcount( offset ) )
|
||||
|
|
@ -827,12 +844,12 @@ private:
|
|||
/* var in DCSET */
|
||||
if ( enable_dcset )
|
||||
{
|
||||
generate_support_minimization_encodings_rec<enable_dcset>( onset, offset, var + 1, count );
|
||||
generate_support_minimization_encodings_rec<enable_dcset, equal_size_partition>( onset, offset, var + 1, count );
|
||||
}
|
||||
|
||||
/* move var in ONSET */
|
||||
onset |= 1 << var;
|
||||
generate_support_minimization_encodings_rec<enable_dcset>( onset, offset, var + 1, count );
|
||||
generate_support_minimization_encodings_rec<enable_dcset, equal_size_partition>( onset, offset, var + 1, count );
|
||||
onset &= ~( 1 << var );
|
||||
|
||||
/* remove symmetries */
|
||||
|
|
@ -843,7 +860,7 @@ private:
|
|||
|
||||
/* move var in OFFSET */
|
||||
offset |= 1 << var;
|
||||
generate_support_minimization_encodings_rec<enable_dcset>( onset, offset, var + 1, count );
|
||||
generate_support_minimization_encodings_rec<enable_dcset, equal_size_partition>( onset, offset, var + 1, count );
|
||||
offset &= ~( 1 << var );
|
||||
}
|
||||
|
||||
|
|
@ -1042,6 +1059,13 @@ private:
|
|||
for ( uint32_t j = 0; j < iset_support; ++j )
|
||||
{
|
||||
cost += has_var_support( tt, care, iset_support, j ) ? 1 : 0;
|
||||
// if ( !has_var_support( tt, care, iset_support, j ) )
|
||||
// {
|
||||
// /* adjust truth table and care set */
|
||||
// adjust_truth_table_on_dc( tt, care, iset_support, j );
|
||||
// continue;
|
||||
// }
|
||||
// ++cost;
|
||||
}
|
||||
|
||||
/* discard solutions with support over LUT size */
|
||||
|
|
@ -1186,7 +1210,7 @@ private:
|
|||
return res;
|
||||
}
|
||||
|
||||
bool covering_improve( std::vector<encoding_column>& matrix, std::array<uint32_t, 6>& solution )
|
||||
bool covering_improve( std::vector<encoding_column> const& matrix, std::array<uint32_t, 6>& solution )
|
||||
{
|
||||
/* performs one iteration of local search */
|
||||
uint32_t best_cost = 0, local_cost = 0;
|
||||
|
|
@ -1233,21 +1257,23 @@ private:
|
|||
return improved;
|
||||
}
|
||||
|
||||
void adjust_truth_table_on_dc( STT& tt, STT& care, uint32_t var_index )
|
||||
void adjust_truth_table_on_dc( STT& tt, STT& care, uint32_t real_num_vars, uint32_t var_index )
|
||||
{
|
||||
assert( var_index < tt.num_vars() );
|
||||
assert( var_index < real_num_vars );
|
||||
assert( tt.num_vars() == care.num_vars() );
|
||||
|
||||
if ( tt.num_vars() <= 6 || var_index < 6 )
|
||||
const uint32_t num_blocks = real_num_vars <= 6 ? 1 : ( 1 << ( real_num_vars - 6 ) );
|
||||
if ( real_num_vars <= 6 || var_index < 6 )
|
||||
{
|
||||
auto it_tt = std::begin( tt._bits );
|
||||
auto it_care = std::begin( care._bits );
|
||||
while ( it_tt != std::end( tt._bits ) )
|
||||
while ( it_tt != std::begin( tt._bits ) + num_blocks )
|
||||
{
|
||||
uint64_t new_bits = *it_tt & *it_care;
|
||||
*it_tt = ( ( new_bits | ( new_bits >> ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections_neg[var_index] ) |
|
||||
( ( new_bits | ( new_bits << ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections[var_index] );
|
||||
*it_care = *it_care | ( *it_care >> ( uint64_t( 1 ) << var_index ) );
|
||||
*it_care = ( *it_care | ( *it_care >> ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections_neg[var_index];
|
||||
*it_care = *it_care | ( *it_care << ( uint64_t( 1 ) << var_index ) );
|
||||
|
||||
++it_tt;
|
||||
++it_care;
|
||||
|
|
@ -1256,7 +1282,7 @@ private:
|
|||
}
|
||||
|
||||
const auto step = 1 << ( var_index - 6 );
|
||||
for ( auto i = 0u; i < static_cast<uint32_t>( tt.num_blocks() ); i += 2 * step )
|
||||
for ( auto i = 0u; i < static_cast<uint32_t>( num_blocks ); i += 2 * step )
|
||||
{
|
||||
for ( auto j = 0; j < step; ++j )
|
||||
{
|
||||
|
|
@ -1343,10 +1369,15 @@ private:
|
|||
std::swap( var_index1, var_index2 );
|
||||
}
|
||||
|
||||
assert( num_vars > 6 );
|
||||
const uint32_t num_blocks = 1 << ( num_vars - 6 );
|
||||
const uint32_t num_blocks = num_vars <= 6 ? 1 : 1 << ( num_vars - 6 );
|
||||
|
||||
if ( var_index2 <= 5 )
|
||||
if ( num_vars <= 6 )
|
||||
{
|
||||
const auto& pmask = kitty::detail::ppermutation_masks[var_index1][var_index2];
|
||||
const auto shift = ( 1 << var_index2 ) - ( 1 << var_index1 );
|
||||
tt._bits[0] = ( tt._bits[0] & pmask[0] ) | ( ( tt._bits[0] & pmask[1] ) << shift ) | ( ( tt._bits[0] & pmask[2] ) >> shift );
|
||||
}
|
||||
else if ( var_index2 <= 5 )
|
||||
{
|
||||
const auto& pmask = kitty::detail::ppermutation_masks[var_index1][var_index2];
|
||||
const auto shift = ( 1 << var_index2 ) - ( 1 << var_index1 );
|
||||
|
|
|
|||
|
|
@ -19,155 +19,148 @@
|
|||
#include "ac_wrapper.h"
|
||||
#include "ac_decomposition.hpp"
|
||||
#include "acd66.hpp"
|
||||
#include "acd666.hpp"
|
||||
#include "acdXX.hpp"
|
||||
|
||||
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;
|
||||
|
||||
if ( use_generic_acd )
|
||||
ac_decomposition_params ps;
|
||||
ps.lut_size = lutSize;
|
||||
ps.use_first = false;
|
||||
ps.try_no_late_arrival = static_cast<bool>( try_no_late_arrival );
|
||||
ac_decomposition_stats st;
|
||||
|
||||
ac_decomposition_impl acd( nVars, ps, &st );
|
||||
int val = acd.run( pTruth, *pdelay );
|
||||
|
||||
if ( val < 0 )
|
||||
{
|
||||
ac_decomposition_params ps;
|
||||
ps.lut_size = lutSize;
|
||||
ps.use_first = false;
|
||||
ps.try_no_late_arrival = static_cast<bool>( try_no_late_arrival );
|
||||
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 = st.num_luts;
|
||||
|
||||
return val;
|
||||
*pdelay = 0;
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
acd66_impl acd( nVars );
|
||||
int val = acd.run( pTruth, *pdelay );
|
||||
|
||||
if ( val == 0 )
|
||||
{
|
||||
*pdelay = 0;
|
||||
return -1;
|
||||
}
|
||||
*pdelay = acd.get_profile();
|
||||
*cost = st.num_luts;
|
||||
|
||||
*pdelay = acd.get_profile();
|
||||
*cost = 2;
|
||||
|
||||
return val;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition )
|
||||
{
|
||||
using namespace acd;
|
||||
|
||||
if ( use_generic_acd )
|
||||
{
|
||||
ac_decomposition_params ps;
|
||||
ps.lut_size = lutSize;
|
||||
ps.use_first = true;
|
||||
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();
|
||||
|
||||
if ( val != 0 )
|
||||
{
|
||||
*pdelay = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*pdelay = acd.get_profile();
|
||||
|
||||
acd.get_decomposition( decomposition );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int acd66_evaluate( word * pTruth, unsigned nVars, int compute_decomposition )
|
||||
{
|
||||
using namespace acd;
|
||||
|
||||
acd66_impl acd( nVars, true, false );
|
||||
|
||||
if ( acd.run( pTruth ) == 0 )
|
||||
return 0;
|
||||
|
||||
if ( !compute_decomposition )
|
||||
return 1;
|
||||
ac_decomposition_params ps;
|
||||
ps.lut_size = lutSize;
|
||||
ps.use_first = true;
|
||||
ac_decomposition_stats st;
|
||||
|
||||
ac_decomposition_impl acd( nVars, ps, &st );
|
||||
acd.run( pTruth, *pdelay );
|
||||
int val = acd.compute_decomposition();
|
||||
if ( val != 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int acd66_decompose( word * pTruth, unsigned nVars, unsigned char *decomposition )
|
||||
{
|
||||
using namespace acd;
|
||||
|
||||
acd66_impl acd( nVars, true, false );
|
||||
acd.run( pTruth );
|
||||
|
||||
int val = acd.compute_decomposition();
|
||||
if ( val != 0 )
|
||||
|
||||
if ( val < 0 )
|
||||
{
|
||||
*pdelay = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*pdelay = acd.get_profile();
|
||||
acd.get_decomposition( decomposition );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int acd2_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival )
|
||||
{
|
||||
using namespace acd;
|
||||
|
||||
acdXX_params ps;
|
||||
ps.lut_size = lutSize;
|
||||
ps.max_shared_vars = lutSize - 2;
|
||||
acdXX_impl acd( nVars, ps );
|
||||
int val = acd.run( pTruth, *pdelay );
|
||||
|
||||
if ( val == 0 )
|
||||
{
|
||||
*pdelay = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
acd.compute_decomposition();
|
||||
*pdelay = acd.get_profile();
|
||||
*cost = 2;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
int acd2_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition )
|
||||
{
|
||||
using namespace acd;
|
||||
|
||||
acdXX_params ps;
|
||||
ps.lut_size = lutSize;
|
||||
ps.max_shared_vars = lutSize - 2;
|
||||
acdXX_impl acd( nVars, ps );
|
||||
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;
|
||||
}
|
||||
|
||||
int acd666_evaluate( word * pTruth, unsigned nVars, int compute_decomposition )
|
||||
inline int acd66_decompose( word * pTruth, unsigned nVars, unsigned char *decomposition )
|
||||
{
|
||||
using namespace acd;
|
||||
|
||||
acd666_impl acd( nVars, false );
|
||||
acd66_impl acd( nVars, true, false );
|
||||
|
||||
if ( acd.run( pTruth ) == 0 )
|
||||
return 0;
|
||||
|
||||
if ( !compute_decomposition )
|
||||
if ( decomposition == NULL )
|
||||
return 1;
|
||||
|
||||
int val = acd.compute_decomposition();
|
||||
if ( val != 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
acd.get_decomposition( decomposition );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int acdXX_decompose( word * pTruth, unsigned lutSize, unsigned nVars, unsigned char *decomposition )
|
||||
{
|
||||
using namespace acd;
|
||||
|
||||
if ( lutSize == 6 )
|
||||
{
|
||||
return acd66_decompose( pTruth, nVars, decomposition );
|
||||
}
|
||||
|
||||
acdXX_params ps;
|
||||
ps.lut_size = lutSize;
|
||||
ps.max_shared_vars = lutSize - 2;
|
||||
acdXX_impl acd( nVars, ps );
|
||||
|
||||
if ( acd.run( pTruth ) == 0 )
|
||||
return 0;
|
||||
if ( decomposition == NULL )
|
||||
return 1;
|
||||
int val = acd.compute_decomposition();
|
||||
if ( val != 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
acd.get_decomposition( decomposition );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,11 +34,10 @@ ABC_NAMESPACE_HEADER_START
|
|||
|
||||
int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival );
|
||||
int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition );
|
||||
int acd2_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival );
|
||||
int acd2_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition );
|
||||
|
||||
int acd66_evaluate( word * pTruth, unsigned nVars, int compute_decomposition );
|
||||
int acd66_decompose( word * pTruth, unsigned nVars, unsigned char *decomposition );
|
||||
|
||||
int acd666_evaluate( word * pTruth, unsigned nVars, int compute_decomposition );
|
||||
int acdXX_decompose( word * pTruth, unsigned lutSize, unsigned nVars, unsigned char *decomposition );
|
||||
|
||||
ABC_NAMESPACE_HEADER_END
|
||||
|
||||
|
|
|
|||
|
|
@ -138,9 +138,20 @@ public:
|
|||
if ( best_multiplicity == UINT32_MAX )
|
||||
return -1;
|
||||
|
||||
for ( uint32_t i = 0; i < best_free_set; ++i )
|
||||
if ( bs_support_size == UINT32_MAX )
|
||||
{
|
||||
profile |= 1 << permutations[i];
|
||||
for ( uint32_t i = 0; i < best_free_set; ++i )
|
||||
{
|
||||
profile |= 1 << permutations[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( uint32_t i = 0; i < bs_support_size; ++i )
|
||||
{
|
||||
profile |= 1 << permutations[bs_support[i] + best_free_set];
|
||||
}
|
||||
profile = ~profile & ( ( 1u << num_vars ) - 1 );
|
||||
}
|
||||
|
||||
return profile;
|
||||
|
|
@ -215,7 +226,7 @@ private:
|
|||
local_extend_to( start_tt, num_vars );
|
||||
}
|
||||
|
||||
uint32_t column_multiplicity( STT const& tt, uint32_t free_set_size )
|
||||
uint32_t column_multiplicity( STT const& tt, uint32_t const free_set_size )
|
||||
{
|
||||
assert( free_set_size <= 5 );
|
||||
|
||||
|
|
@ -250,7 +261,7 @@ private:
|
|||
return size;
|
||||
}
|
||||
|
||||
uint32_t column_multiplicity2( STT const& tt, uint32_t free_set_size, uint32_t const limit )
|
||||
uint32_t column_multiplicity2( STT const& tt, uint32_t const free_set_size, uint32_t const limit )
|
||||
{
|
||||
assert( free_set_size <= 5 );
|
||||
|
||||
|
|
@ -544,6 +555,7 @@ private:
|
|||
}
|
||||
} while ( combinations_next( free_set_size, 0, pComb, pInvPerm, tt ) );
|
||||
|
||||
best_multiplicity = UINT32_MAX;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -591,6 +603,8 @@ private:
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
best_multiplicity = UINT32_MAX;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -654,6 +668,7 @@ private:
|
|||
}
|
||||
} while ( combinations_next( free_set_size, offset, pComb, pInvPerm, tt ) );
|
||||
|
||||
best_multiplicity = UINT32_MAX;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -732,7 +747,7 @@ private:
|
|||
uint32_t p = 0;
|
||||
for ( uint32_t k = 0; k < num_shared_vars; ++k )
|
||||
{
|
||||
p += ( ( iteration_counter >> shared_vars[k] ) & 1 ) << k;
|
||||
p |= ( ( iteration_counter >> shared_vars[k] ) & 1 ) << k;
|
||||
}
|
||||
|
||||
uint32_t k;
|
||||
|
|
@ -787,97 +802,10 @@ private:
|
|||
|
||||
void compute_decomposition_impl( bool verbose = false )
|
||||
{
|
||||
if ( num_shared_vars > 1 )
|
||||
return compute_decomposition_impl_multi_ss( verbose );
|
||||
|
||||
bool has_shared_set = num_shared_vars > 0;
|
||||
|
||||
/* construct isets involved in multiplicity */
|
||||
LTT isets0[2];
|
||||
LTT isets1[2];
|
||||
|
||||
/* construct isets */
|
||||
uint32_t offset = 0;
|
||||
uint32_t num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1;
|
||||
uint64_t const shift = UINT64_C( 1 ) << best_free_set;
|
||||
uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1;
|
||||
|
||||
/* limit analysis on 0 cofactor of the shared variable */
|
||||
if ( has_shared_set )
|
||||
num_blocks >>= 1;
|
||||
|
||||
uint64_t fs_fun[4] = { best_tt._bits[0] & mask, 0, 0, 0 };
|
||||
|
||||
for ( auto i = 0u; i < num_blocks; ++i )
|
||||
{
|
||||
uint64_t cof = best_tt._bits[i];
|
||||
for ( auto j = 0; j < ( 64 >> best_free_set ); ++j )
|
||||
{
|
||||
uint64_t val = cof & mask;
|
||||
if ( val == fs_fun[0] )
|
||||
{
|
||||
isets0[0]._bits |= UINT64_C( 1 ) << ( j + offset );
|
||||
}
|
||||
else
|
||||
{
|
||||
isets0[1]._bits |= UINT64_C( 1 ) << ( j + offset );
|
||||
fs_fun[1] = val;
|
||||
}
|
||||
cof >>= shift;
|
||||
}
|
||||
offset = ( offset + ( 64 >> best_free_set ) ) & 0x3F;
|
||||
}
|
||||
|
||||
/* continue on the 1 cofactor if shared set */
|
||||
if ( has_shared_set )
|
||||
{
|
||||
fs_fun[2] = best_tt._bits[num_blocks] & mask;
|
||||
for ( auto i = num_blocks; i < ( num_blocks << 1 ); ++i )
|
||||
{
|
||||
uint64_t cof = best_tt._bits[i];
|
||||
for ( auto j = 0; j < ( 64 >> best_free_set ); ++j )
|
||||
{
|
||||
uint64_t val = cof & mask;
|
||||
if ( val == fs_fun[2] )
|
||||
{
|
||||
isets1[0]._bits |= UINT64_C( 1 ) << ( j + offset );
|
||||
}
|
||||
else
|
||||
{
|
||||
isets1[1]._bits |= UINT64_C( 1 ) << ( j + offset );
|
||||
fs_fun[3] = val;
|
||||
}
|
||||
cof >>= shift;
|
||||
}
|
||||
offset = ( offset + ( 64 >> best_free_set ) ) & 0x3F;
|
||||
}
|
||||
}
|
||||
|
||||
/* find the support minimizing combination with shared set */
|
||||
compute_functions( isets0, isets1, fs_fun );
|
||||
|
||||
/* print functions */
|
||||
if ( verbose )
|
||||
{
|
||||
LTT f;
|
||||
f._bits = dec_funcs[0];
|
||||
std::cout << "BS function : ";
|
||||
kitty::print_hex( f );
|
||||
std::cout << "\n";
|
||||
f._bits = dec_funcs[1];
|
||||
std::cout << "Composition function: ";
|
||||
kitty::print_hex( f );
|
||||
std::cout << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void compute_decomposition_impl_multi_ss( bool verbose = false )
|
||||
{
|
||||
/* due to the high multiplicity value this method does not perform support minimization */
|
||||
|
||||
/* construct isets involved in multiplicity */
|
||||
LTT composition;
|
||||
LTT bs;
|
||||
LTT bs_dc;
|
||||
|
||||
/* construct isets */
|
||||
uint32_t offset = 0;
|
||||
|
|
@ -888,10 +816,12 @@ private:
|
|||
uint32_t const next_group = 1 << ( num_vars - best_free_set - num_shared_vars );
|
||||
|
||||
uint64_t fs_fun[32] = { 0 };
|
||||
uint64_t dc_mask = ( ( UINT64_C( 1 ) << next_group ) - 1 );
|
||||
|
||||
uint32_t group_index = 0;
|
||||
uint32_t set_index = 0;
|
||||
fs_fun[0] = best_tt._bits[0] & mask;
|
||||
bool set_dc = true;
|
||||
for ( auto i = 0u; i < num_blocks; ++i )
|
||||
{
|
||||
uint64_t cof = best_tt._bits[i];
|
||||
|
|
@ -901,15 +831,25 @@ private:
|
|||
/* move to next block */
|
||||
if ( set_index == next_group )
|
||||
{
|
||||
if ( set_dc )
|
||||
{
|
||||
/* only one cofactor can be found in the group --> encoding can be 0 or 1 */
|
||||
fs_fun[group_index + 1] = fs_fun[group_index];
|
||||
bs_dc._bits |= dc_mask;
|
||||
}
|
||||
/* set don't care */
|
||||
set_dc = true;
|
||||
group_index += 2;
|
||||
set_index = 0;
|
||||
fs_fun[group_index] = val;
|
||||
dc_mask <<= next_group;
|
||||
}
|
||||
/* gather encoding */
|
||||
if ( val != fs_fun[group_index] )
|
||||
{
|
||||
bs._bits |= UINT64_C( 1 ) << ( j + offset );
|
||||
fs_fun[group_index + 1] = val;
|
||||
set_dc = false; // two cofactors are present
|
||||
}
|
||||
cof >>= shift;
|
||||
++set_index;
|
||||
|
|
@ -917,6 +857,13 @@ private:
|
|||
offset = ( offset + ( 64 >> best_free_set ) ) & 0x3F;
|
||||
}
|
||||
|
||||
if ( set_dc )
|
||||
{
|
||||
/* only one cofactor can be found in the group --> encoding can be 0 or 1 */
|
||||
fs_fun[group_index + 1] = fs_fun[group_index];
|
||||
bs_dc._bits |= dc_mask;
|
||||
}
|
||||
|
||||
/* create composition function */
|
||||
for ( uint32_t i = 0; i < 2 * num_groups; ++i )
|
||||
{
|
||||
|
|
@ -927,11 +874,12 @@ private:
|
|||
LTT care;
|
||||
bs_support_size = 0;
|
||||
uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF, UINT64_MAX };
|
||||
care._bits = masks[num_vars - best_free_set];
|
||||
care._bits = masks[num_vars - best_free_set] & ~bs_dc._bits;
|
||||
for ( uint32_t i = 0; i < num_vars - best_free_set; ++i )
|
||||
{
|
||||
if ( !has_var6( bs, care, i ) )
|
||||
{
|
||||
adjust_truth_table_on_dc( bs, care, i );
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -963,150 +911,6 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
inline void compute_functions( LTT isets0[2], LTT isets1[2], uint64_t fs_fun[4] )
|
||||
{
|
||||
/* u = 2 no support minimization */
|
||||
if ( best_multiplicity < 3 )
|
||||
{
|
||||
dec_funcs[0] = isets0[0]._bits;
|
||||
bs_support_size = num_vars - best_free_set;
|
||||
for ( uint32_t i = 0; i < num_vars - best_free_set; ++i )
|
||||
{
|
||||
bs_support[i] = i;
|
||||
}
|
||||
compute_composition( fs_fun );
|
||||
return;
|
||||
}
|
||||
|
||||
/* u = 4 two possibilities */
|
||||
if ( best_multiplicity == 4 )
|
||||
{
|
||||
compute_functions4( isets0, isets1, fs_fun );
|
||||
return;
|
||||
}
|
||||
|
||||
/* u = 3 if both sets have multiplicity 2 there are no don't cares */
|
||||
if ( best_multiplicity0 == best_multiplicity1 )
|
||||
{
|
||||
compute_functions4( isets0, isets1, fs_fun );
|
||||
return;
|
||||
}
|
||||
|
||||
/* u = 3 one set has multiplicity 1, use don't cares */
|
||||
compute_functions3( isets0, isets1, fs_fun );
|
||||
}
|
||||
|
||||
inline void compute_functions4( LTT isets0[2], LTT isets1[2], uint64_t fs_fun[4] )
|
||||
{
|
||||
uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF, UINT64_MAX };
|
||||
LTT f = isets0[0] | isets1[1];
|
||||
LTT care;
|
||||
care._bits = masks[num_vars - best_free_set];
|
||||
|
||||
/* count the number of support variables */
|
||||
uint32_t support_vars1 = 0;
|
||||
for ( uint32_t i = 0; i < num_vars - best_free_set; ++i )
|
||||
{
|
||||
support_vars1 += has_var6( f, care, i ) ? 1 : 0;
|
||||
bs_support[i] = i;
|
||||
}
|
||||
|
||||
/* use a different set */
|
||||
f = isets0[0] | isets1[0];
|
||||
|
||||
uint32_t support_vars2 = 0;
|
||||
for ( uint32_t i = 0; i < num_vars - best_free_set; ++i )
|
||||
{
|
||||
support_vars2 += has_var6( f, care, i ) ? 1 : 0;
|
||||
}
|
||||
|
||||
bs_support_size = support_vars2;
|
||||
if ( support_vars2 > support_vars1 )
|
||||
{
|
||||
f = isets0[0] | isets1[1];
|
||||
std::swap( fs_fun[3], fs_fun[4] );
|
||||
bs_support_size = support_vars1;
|
||||
}
|
||||
|
||||
/* move variables */
|
||||
if ( bs_support_size < num_vars - best_free_set )
|
||||
{
|
||||
support_vars1 = 0;
|
||||
for ( uint32_t i = 0; i < num_vars - best_free_set; ++i )
|
||||
{
|
||||
if ( !has_var6( f, care, i ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( support_vars1 < i )
|
||||
{
|
||||
kitty::swap_inplace( f, support_vars1, i );
|
||||
}
|
||||
|
||||
bs_support[support_vars1] = i;
|
||||
++support_vars1;
|
||||
}
|
||||
}
|
||||
|
||||
dec_funcs[0] = f._bits;
|
||||
compute_composition( fs_fun );
|
||||
}
|
||||
|
||||
inline void compute_functions3( LTT isets0[2], LTT isets1[2], uint64_t fs_fun[4] )
|
||||
{
|
||||
uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF, UINT64_MAX };
|
||||
LTT f = isets0[0] | isets1[0];
|
||||
LTT care;
|
||||
|
||||
/* init the care set */
|
||||
if ( best_multiplicity0 == 1 )
|
||||
{
|
||||
care._bits = masks[num_vars - best_free_set] & ( ~isets0[0]._bits );
|
||||
fs_fun[1] = fs_fun[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
care._bits = masks[num_vars - best_free_set] & ( ~isets1[0]._bits );
|
||||
fs_fun[3] = fs_fun[2];
|
||||
}
|
||||
|
||||
/* count the number of support variables */
|
||||
uint32_t support_vars = 0;
|
||||
for ( uint32_t i = 0; i < num_vars - best_free_set; ++i )
|
||||
{
|
||||
if ( !has_var6( f, care, i ) )
|
||||
{
|
||||
adjust_truth_table_on_dc( f, care, i );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( support_vars < i )
|
||||
{
|
||||
kitty::swap_inplace( f, support_vars, i );
|
||||
}
|
||||
|
||||
bs_support[support_vars] = i;
|
||||
++support_vars;
|
||||
}
|
||||
|
||||
bs_support_size = support_vars;
|
||||
dec_funcs[0] = f._bits;
|
||||
compute_composition( fs_fun );
|
||||
}
|
||||
|
||||
void compute_composition( uint64_t fs_fun[4] )
|
||||
{
|
||||
dec_funcs[1] = fs_fun[0] << ( 1 << best_free_set );
|
||||
dec_funcs[1] |= fs_fun[1];
|
||||
|
||||
if ( best_multiplicity > 2 )
|
||||
{
|
||||
dec_funcs[1] |= fs_fun[2] << ( ( 2 << best_free_set ) + ( 1 << best_free_set ) );
|
||||
dec_funcs[1] |= fs_fun[3] << ( 2 << best_free_set );
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TT_type>
|
||||
void local_extend_to( TT_type& tt, uint32_t real_num_vars )
|
||||
{
|
||||
|
|
@ -1227,7 +1031,8 @@ private:
|
|||
uint64_t new_bits = tt._bits & care._bits;
|
||||
tt._bits = ( ( new_bits | ( new_bits >> ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections_neg[var_index] ) |
|
||||
( ( new_bits | ( new_bits << ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections[var_index] );
|
||||
care._bits = care._bits | ( care._bits >> ( uint64_t( 1 ) << var_index ) );
|
||||
care._bits = ( care._bits | ( care._bits >> ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections_neg[var_index];
|
||||
care._bits = care._bits | ( care._bits << ( uint64_t( 1 ) << var_index ) );
|
||||
}
|
||||
|
||||
/* Decomposition format for ABC
|
||||
|
|
@ -1284,7 +1089,7 @@ private:
|
|||
++bytes;
|
||||
|
||||
/* write support */
|
||||
for ( uint32_t i = best_free_set; i < best_free_set; ++i )
|
||||
for ( uint32_t i = 0; i < best_free_set; ++i )
|
||||
{
|
||||
*pArray = (unsigned char)permutations[i];
|
||||
pArray++;
|
||||
|
|
@ -1408,8 +1213,6 @@ private:
|
|||
private:
|
||||
uint32_t best_multiplicity{ UINT32_MAX };
|
||||
uint32_t best_free_set{ UINT32_MAX };
|
||||
uint32_t best_multiplicity0{ UINT32_MAX };
|
||||
uint32_t best_multiplicity1{ UINT32_MAX };
|
||||
uint32_t bs_support_size{ UINT32_MAX };
|
||||
uint32_t num_shared_vars{ 0 };
|
||||
STT best_tt;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -147,7 +147,8 @@ struct If_Par_t_
|
|||
int fDeriveLuts; // enables deriving LUT structures
|
||||
int fDoAverage; // optimize average rather than maximum level
|
||||
int fHashMapping; // perform AIG hashing after mapping
|
||||
int fUserLutDec; // perform AIG hashing after mapping
|
||||
int fUserLutDec; // perform Boolean decomposition during mapping
|
||||
int fUserLut2D; // perform Boolean decomposition during mapping
|
||||
int fVerbose; // the verbosity flag
|
||||
int fVerboseTrace; // the verbosity flag
|
||||
char * pLutStruct; // LUT structure
|
||||
|
|
@ -552,7 +553,7 @@ extern int If_CutPerformCheck07( If_Man_t * p, unsigned * pTruth, in
|
|||
extern int If_CutPerformCheck08( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr );
|
||||
extern int If_CutPerformCheck10( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr );
|
||||
extern int If_CutPerformCheck16( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr );
|
||||
extern int If_CutPerformCheck66( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr );
|
||||
extern int If_CutPerformCheckXX( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr );
|
||||
extern int If_CutPerformCheck45( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr );
|
||||
extern int If_CutPerformCheck54( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr );
|
||||
extern int If_CutPerformCheck75( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr );
|
||||
|
|
@ -573,6 +574,7 @@ extern int If_CutSopBalancePinDelays( If_Man_t * p, If_Cut_t * pCut,
|
|||
extern int If_CutLutBalanceEval( If_Man_t * p, If_Cut_t * pCut );
|
||||
extern int If_CutLutBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm );
|
||||
extern int If_LutDecEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay, int fFirst );
|
||||
extern int If_Lut2DecEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay, int fFirst );
|
||||
extern int If_LutDecReEval( If_Man_t * p, If_Cut_t * pCut );
|
||||
extern float If_LutDecPinRequired( If_Man_t * p, If_Cut_t * pCut, int i, float required );
|
||||
/*=== ifDsd.c =============================================================*/
|
||||
|
|
@ -704,6 +706,8 @@ extern void If_ObjPrint( If_Obj_t * pObj );
|
|||
|
||||
extern int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival );
|
||||
extern int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition );
|
||||
extern int acd2_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost, int try_no_late_arrival );
|
||||
extern int acd2_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition );
|
||||
|
||||
ABC_NAMESPACE_HEADER_END
|
||||
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ void If_ManSetDefaultPars( If_Par_t * pPars )
|
|||
pPars->fCutMin = 0;
|
||||
pPars->fBidec = 0;
|
||||
pPars->fUserLutDec = 0;
|
||||
pPars->fUserLut2D = 0;
|
||||
pPars->fVerbose = 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -761,7 +761,7 @@ void If_CutSort( If_Man_t * p, If_Set_t * pCutSet, If_Cut_t * pCut )
|
|||
|
||||
if ( !pCut->fUseless &&
|
||||
(p->pPars->fUseDsd || p->pPars->pFuncCell2 || p->pPars->fUseBat ||
|
||||
p->pPars->pLutStruct || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUserLutDec ||
|
||||
p->pPars->pLutStruct || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUserLutDec || p->pPars->fUserLut2D ||
|
||||
p->pPars->fEnableCheck07 || p->pPars->fUseCofVars || p->pPars->fUseAndVars || p->pPars->fUse34Spec ||
|
||||
p->pPars->fUseDsdTune || p->pPars->fEnableCheck75 || p->pPars->fEnableCheck75u || p->pPars->fUseCheck1 || p->pPars->fUseCheck2) )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
#define CLU_VAR_MAX 16
|
||||
#define CLU_VAR_MAX 11
|
||||
#define CLU_MEM_MAX 1000 // 1 GB
|
||||
#define CLU_UNUSED 0xff
|
||||
|
||||
|
|
@ -252,7 +252,7 @@ unsigned * If_CluHashLookup2( If_Man_t * p, word * pTruth, int t )
|
|||
}
|
||||
|
||||
// returns if successful
|
||||
int If_CluCheck66( If_Man_t * p, word * pTruth0, int nVars, int fHashing )
|
||||
int If_CluCheckXX( If_Man_t * p, word * pTruth0, int lutSize, int nVars, int fHashing )
|
||||
{
|
||||
If_Grp_t G1 = {0};
|
||||
unsigned * pHashed = NULL;
|
||||
|
|
@ -267,32 +267,7 @@ int If_CluCheck66( If_Man_t * p, word * pTruth0, int nVars, int fHashing )
|
|||
/* new entry */
|
||||
if ( G1.nVars == 0 )
|
||||
{
|
||||
G1.nVars = acd66_evaluate( pTruth0, nVars, 0 );
|
||||
}
|
||||
|
||||
if ( pHashed )
|
||||
*pHashed = If_CluGrp2Uns2( &G1 );
|
||||
|
||||
return G1.nVars;
|
||||
}
|
||||
|
||||
// returns if successful
|
||||
int If_CluCheck666( If_Man_t * p, word * pTruth0, int nVars, int fHashing )
|
||||
{
|
||||
If_Grp_t G1 = {0};
|
||||
unsigned * pHashed = NULL;
|
||||
|
||||
if ( p && fHashing )
|
||||
{
|
||||
pHashed = If_CluHashLookup2( p, pTruth0, 0 );
|
||||
if ( pHashed && *pHashed != CLU_UNUSED )
|
||||
If_CluUns2Grp2( *pHashed, &G1 );
|
||||
}
|
||||
|
||||
/* new entry */
|
||||
if ( G1.nVars == 0 )
|
||||
{
|
||||
G1.nVars = acd666_evaluate( pTruth0, nVars, 0 );
|
||||
G1.nVars = acdXX_decompose( pTruth0, lutSize, nVars, NULL );
|
||||
}
|
||||
|
||||
if ( pHashed )
|
||||
|
|
@ -312,12 +287,11 @@ int If_CluCheck666( If_Man_t * p, word * pTruth0, int nVars, int fHashing )
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int If_CutPerformCheck66( If_Man_t * p, unsigned * pTruth0, int nVars, int nLeaves, char * pStr )
|
||||
int If_CutPerformCheckXX( If_Man_t * p, unsigned * pTruth0, int nVars, int nLeaves, char * pStr )
|
||||
{
|
||||
unsigned pTruth[IF_MAX_FUNC_LUTSIZE > 5 ? 1 << (IF_MAX_FUNC_LUTSIZE - 5) : 1];
|
||||
int i, Length;
|
||||
int Length;
|
||||
// stretch the truth table
|
||||
assert( nVars >= 6 );
|
||||
memcpy( pTruth, pTruth0, sizeof(word) * Abc_TtWordNum(nVars) );
|
||||
Abc_TtStretch6( (word *)pTruth, nLeaves, p->pPars->nLutSize );
|
||||
|
||||
|
|
@ -327,35 +301,30 @@ int If_CutPerformCheck66( If_Man_t * p, unsigned * pTruth0, int nVars, int nLeav
|
|||
|
||||
// quit if parameters are wrong
|
||||
Length = strlen(pStr);
|
||||
if ( Length != 2 && Length != 3 )
|
||||
if ( Length != 2 )
|
||||
{
|
||||
printf( "Wrong LUT struct (%s)\n", pStr );
|
||||
return 0;
|
||||
}
|
||||
for ( i = 0; i < Length; i++ )
|
||||
|
||||
int lutSize = pStr[0] - '0';
|
||||
if ( lutSize < 3 || lutSize > 6 )
|
||||
{
|
||||
if ( pStr[i] != '6' )
|
||||
{
|
||||
printf( "The LUT size (%d) should belong to {6}.\n", pStr[i] - '0' );
|
||||
return 0;
|
||||
}
|
||||
printf( "The LUT size (%d) should belong to {3,4,5,6}.\n", lutSize );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( ( Length == 2 && nLeaves > 11 ) || ( Length == 3 && nLeaves > 16 ) )
|
||||
if ( nLeaves >= 2 * lutSize )
|
||||
{
|
||||
printf( "The cut size (%d) is too large for the LUT structure %s.\n", nLeaves, pStr );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// consider easy case
|
||||
if ( nLeaves <= 6 )
|
||||
// consider trivial case
|
||||
if ( nLeaves <= lutSize )
|
||||
return 1;
|
||||
|
||||
// derive the decomposition
|
||||
if ( Length == 2 )
|
||||
return If_CluCheck66(p, (word*)pTruth, nVars, 1);
|
||||
else
|
||||
return If_CluCheck666(p, (word*)pTruth, nVars, 1);
|
||||
return If_CluCheckXX(p, (word*)pTruth, lutSize, nVars, 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -505,6 +505,95 @@ int If_LutDecEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay,
|
|||
return DelayMax + val;
|
||||
}
|
||||
|
||||
int If_Lut2DecEval( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj, int optDelay, int fFirst )
|
||||
{
|
||||
pCut->fUser = 1;
|
||||
pCut->Cost = pCut->nLeaves > 1 ? 1 : 0;
|
||||
pCut->decDelay = 0;
|
||||
if ( pCut->nLeaves == 0 ) // const
|
||||
{
|
||||
assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 0 );
|
||||
return 0;
|
||||
}
|
||||
if ( pCut->nLeaves == 1 ) // variable
|
||||
{
|
||||
assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 1 );
|
||||
return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay;
|
||||
}
|
||||
|
||||
int LutSize = p->pPars->nLutDecSize;
|
||||
int i, leaf_delay;
|
||||
int DelayMax = -1, nLeafMax = 0;
|
||||
unsigned uLeafMask = 0;
|
||||
for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
|
||||
{
|
||||
leaf_delay = If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay;
|
||||
|
||||
if ( DelayMax < leaf_delay )
|
||||
{
|
||||
DelayMax = leaf_delay;
|
||||
nLeafMax = 1;
|
||||
uLeafMask = (1 << i);
|
||||
}
|
||||
else if ( DelayMax == leaf_delay )
|
||||
{
|
||||
nLeafMax++;
|
||||
uLeafMask |= (1 << i);
|
||||
}
|
||||
}
|
||||
if ( If_CutLeaveNum(pCut) <= LutSize )
|
||||
{
|
||||
pCut->decDelay = ( 1 << LutSize ) - 1;
|
||||
return DelayMax + 1;
|
||||
}
|
||||
|
||||
/* compute the decomposition */
|
||||
int use_late_arrival = 0;
|
||||
unsigned cost = 1;
|
||||
|
||||
if ( !fFirst )
|
||||
{
|
||||
if ( optDelay )
|
||||
{
|
||||
/* checks based on delay: must be better than the previous best cut */
|
||||
use_late_arrival = DelayMax + 2 >= If_ObjCutBest(pObj)->Delay;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* checks based on delay: look at the required time */
|
||||
use_late_arrival = DelayMax + 2 > pObj->Required + p->fEpsilon;
|
||||
}
|
||||
}
|
||||
|
||||
/* Too many late-arriving signals */
|
||||
if ( nLeafMax == LutSize && use_late_arrival )
|
||||
{
|
||||
/* unfeasible decomposition */
|
||||
pCut->Cost = IF_COST_MAX;
|
||||
return ABC_INFINITY;
|
||||
}
|
||||
|
||||
if ( !use_late_arrival )
|
||||
{
|
||||
uLeafMask = 0;
|
||||
}
|
||||
|
||||
/* returns the delay of the decomposition */
|
||||
word *pTruth = If_CutTruthW( p, pCut );
|
||||
int val = acd2_evaluate( pTruth, pCut->nLeaves, LutSize, &uLeafMask, &cost, !use_late_arrival );
|
||||
|
||||
/* not feasible decomposition */
|
||||
pCut->decDelay = uLeafMask;
|
||||
if ( val < 0 )
|
||||
{
|
||||
pCut->Cost = IF_COST_MAX;
|
||||
return ABC_INFINITY;
|
||||
}
|
||||
|
||||
pCut->Cost = 2;
|
||||
return DelayMax + val;
|
||||
}
|
||||
|
||||
int If_LutDecReEval( If_Man_t * p, If_Cut_t * pCut )
|
||||
{
|
||||
// pCut->fUser = 1;
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep
|
|||
If_Cut_t * pCut0R, * pCut1R;
|
||||
int fFunc0R, fFunc1R;
|
||||
int i, k, v, iCutDsd, fChange;
|
||||
int fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUserLutDec ||
|
||||
int fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUserLutDec || p->pPars->fUserLut2D ||
|
||||
p->pPars->fUseDsdTune || p->pPars->fUseCofVars || p->pPars->fUseAndVars || p->pPars->fUse34Spec || p->pPars->pLutStruct || p->pPars->pFuncCell2 || p->pPars->fUseCheck1 || p->pPars->fUseCheck2;
|
||||
int fUseAndCut = (p->pPars->nAndDelay > 0) || (p->pPars->nAndArea > 0);
|
||||
assert( !If_ObjIsAnd(pObj->pFanin0) || pObj->pFanin0->pCutSet->nCuts > 0 );
|
||||
|
|
@ -208,7 +208,7 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep
|
|||
pCut->fUseless = 1;
|
||||
}
|
||||
}
|
||||
else if ( p->pPars->fUserLutDec )
|
||||
else if ( p->pPars->fUserLutDec || p->pPars->fUserLut2D )
|
||||
{
|
||||
pCut->Delay = If_LutDecReEval( p, pCut );
|
||||
}
|
||||
|
|
@ -434,6 +434,11 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep
|
|||
pCut->Delay = If_LutDecEval( p, pCut, pObj, Mode == 0, fFirst );
|
||||
pCut->fUseless = pCut->Delay == ABC_INFINITY;
|
||||
}
|
||||
else if ( p->pPars->fUserLut2D )
|
||||
{
|
||||
pCut->Delay = If_Lut2DecEval( p, pCut, pObj, Mode == 0, fFirst );
|
||||
pCut->fUseless = pCut->Delay == ABC_INFINITY;
|
||||
}
|
||||
else if ( p->pPars->fUserSesLib )
|
||||
{
|
||||
int Cost = 0;
|
||||
|
|
@ -518,7 +523,7 @@ void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fP
|
|||
If_Set_t * pCutSet;
|
||||
If_Obj_t * pTemp;
|
||||
If_Cut_t * pCutTemp, * pCut;
|
||||
int i, fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUse34Spec || p->pPars->fUserLutDec;
|
||||
int i, fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUse34Spec || p->pPars->fUserLutDec || p->pPars->fUserLut2D;
|
||||
assert( pObj->pEquiv != NULL );
|
||||
|
||||
// prepare
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ void If_CutPropagateRequired( If_Man_t * p, If_Obj_t * pObj, If_Cut_t * pCut, fl
|
|||
pLeaf->Required = IF_MIN( pLeaf->Required, Required - pLutDelays[0] );
|
||||
}
|
||||
}
|
||||
else if ( p->pPars->fUserLutDec )
|
||||
else if ( p->pPars->fUserLutDec || p->pPars->fUserLut2D )
|
||||
{
|
||||
Required = ObjRequired;
|
||||
If_CutForEachLeaf( p, pCut, pLeaf, i )
|
||||
|
|
|
|||
Loading…
Reference in New Issue