mirror of https://github.com/YosysHQ/abc.git
Adding hash table to reduce computations
This commit is contained in:
parent
2d9af6c9a4
commit
2afaeac823
|
|
@ -70,18 +70,18 @@ int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int acd66_evaluate( word * pTruth, unsigned nVars, int verify )
|
||||
int acd66_evaluate( word * pTruth, unsigned nVars, int compute_decomposition )
|
||||
{
|
||||
using namespace acd;
|
||||
|
||||
acd66_params ps;
|
||||
ps.verify = static_cast<bool>( verify );
|
||||
ps.verify = false;
|
||||
acd66_impl acd( nVars, ps );
|
||||
|
||||
if ( acd.run( pTruth ) == 0 )
|
||||
return 0;
|
||||
|
||||
if ( !verify )
|
||||
if ( !compute_decomposition )
|
||||
return 1;
|
||||
|
||||
int val = acd.compute_decomposition();
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ 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 acd66_evaluate( word * pTruth, unsigned nVars, int verify );
|
||||
int acd66_evaluate( word * pTruth, unsigned nVars, int compute_decomposition );
|
||||
int acd66_decompose( word * pTruth, unsigned nVars, unsigned char *decomposition );
|
||||
|
||||
ABC_NAMESPACE_HEADER_END
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ struct acd66_params
|
|||
uint32_t max_evaluations{ 3 };
|
||||
|
||||
/*! \brief Run verification before returning. */
|
||||
bool verify{ true };
|
||||
bool verify{ false };
|
||||
};
|
||||
|
||||
/*! \brief Statistics for acd66 */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [ifDec16.c]
|
||||
FileName [ifDec66.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
|
|
@ -8,13 +8,13 @@
|
|||
|
||||
Synopsis [Fast checking procedures.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
Author [Alessandro Tempia Calvino]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
Affiliation [EPFL]
|
||||
|
||||
Date [Ver. 1.0. Started - November 21, 2006.]
|
||||
Date [Ver. 1.0. Started - Feb 8, 2024.]
|
||||
|
||||
Revision [$Id: ifDec16.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
|
||||
Revision [$Id: ifDec66.c,v 1.00 2008/02/08 00:00:00 tempia Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
|
|
@ -24,10 +24,258 @@
|
|||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
#define CLU_VAR_MAX 16
|
||||
#define CLU_MEM_MAX 1000 // 1 GB
|
||||
#define CLU_UNUSED 0xff
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// decomposition
|
||||
typedef struct If_Grp_t_ If_Grp_t;
|
||||
struct If_Grp_t_
|
||||
{
|
||||
char nVars;
|
||||
char nMyu;
|
||||
char pVars[CLU_VAR_MAX];
|
||||
};
|
||||
|
||||
// hash table entry
|
||||
typedef struct If_Hte_t_ If_Hte_t;
|
||||
struct If_Hte_t_
|
||||
{
|
||||
If_Hte_t * pNext;
|
||||
unsigned Group;
|
||||
unsigned Counter;
|
||||
word pTruth[1];
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static inline unsigned If_CluGrp2Uns2( If_Grp_t * pG )
|
||||
{
|
||||
char * pChar = (char *)pG;
|
||||
unsigned Res = 0;
|
||||
int i;
|
||||
for ( i = 0; i < 8; i++ )
|
||||
Res |= ((pChar[i] & 15) << (i << 2));
|
||||
return Res;
|
||||
}
|
||||
|
||||
static inline void If_CluUns2Grp2( unsigned Group, If_Grp_t * pG )
|
||||
{
|
||||
char * pChar = (char *)pG;
|
||||
int i;
|
||||
for ( i = 0; i < 8; i++ )
|
||||
pChar[i] = ((Group >> (i << 2)) & 15);
|
||||
}
|
||||
|
||||
unsigned int If_CluPrimeCudd2( unsigned int p )
|
||||
{
|
||||
int i,pn;
|
||||
|
||||
p--;
|
||||
do {
|
||||
p++;
|
||||
if (p&1) {
|
||||
pn = 1;
|
||||
i = 3;
|
||||
while ((unsigned) (i * i) <= p) {
|
||||
if (p % i == 0) {
|
||||
pn = 0;
|
||||
break;
|
||||
}
|
||||
i += 2;
|
||||
}
|
||||
} else {
|
||||
pn = 0;
|
||||
}
|
||||
} while (!pn);
|
||||
return(p);
|
||||
|
||||
} /* end of Cudd_Prime */
|
||||
|
||||
// hash table
|
||||
static inline int If_CluWordNum2( int nVars )
|
||||
{
|
||||
return nVars <= 6 ? 1 : 1 << (nVars-6);
|
||||
}
|
||||
|
||||
int If_CluHashFindMedian2( If_Man_t * p, int t )
|
||||
{
|
||||
If_Hte_t * pEntry;
|
||||
Vec_Int_t * vCounters;
|
||||
int i, Max = 0, Total = 0, Half = 0;
|
||||
vCounters = Vec_IntStart( 1000 );
|
||||
for ( i = 0; i < p->nTableSize[t]; i++ )
|
||||
{
|
||||
for ( pEntry = ((If_Hte_t **)p->pHashTable[t])[i]; pEntry; pEntry = pEntry->pNext )
|
||||
{
|
||||
if ( Max < (int)pEntry->Counter )
|
||||
{
|
||||
Max = pEntry->Counter;
|
||||
Vec_IntSetEntry( vCounters, pEntry->Counter, 0 );
|
||||
}
|
||||
Vec_IntAddToEntry( vCounters, pEntry->Counter, 1 );
|
||||
Total++;
|
||||
}
|
||||
}
|
||||
for ( i = Max; i > 0; i-- )
|
||||
{
|
||||
Half += Vec_IntEntry( vCounters, i );
|
||||
if ( Half > Total/2 )
|
||||
break;
|
||||
}
|
||||
/*
|
||||
printf( "total = %d ", Total );
|
||||
printf( "half = %d ", Half );
|
||||
printf( "i = %d ", i );
|
||||
printf( "Max = %d.\n", Max );
|
||||
*/
|
||||
Vec_IntFree( vCounters );
|
||||
return Abc_MaxInt( i, 1 );
|
||||
}
|
||||
|
||||
int If_CluHashKey2( word * pTruth, int nWords, int Size )
|
||||
{
|
||||
static unsigned BigPrimes[8] = {12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741};
|
||||
unsigned Value = 0;
|
||||
int i;
|
||||
if ( nWords < 4 )
|
||||
{
|
||||
unsigned char * s = (unsigned char *)pTruth;
|
||||
for ( i = 0; i < 8 * nWords; i++ )
|
||||
Value ^= BigPrimes[i % 7] * s[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned * s = (unsigned *)pTruth;
|
||||
for ( i = 0; i < 2 * nWords; i++ )
|
||||
Value ^= BigPrimes[i % 7] * s[i];
|
||||
}
|
||||
return Value % Size;
|
||||
}
|
||||
|
||||
unsigned * If_CluHashLookup2( If_Man_t * p, word * pTruth, int t )
|
||||
{
|
||||
If_Hte_t * pEntry, * pPrev;
|
||||
int nWords, HashKey;
|
||||
if ( p == NULL )
|
||||
return NULL;
|
||||
nWords = If_CluWordNum2(p->pPars->nLutSize);
|
||||
if ( p->pMemEntries == NULL )
|
||||
p->pMemEntries = Mem_FixedStart( sizeof(If_Hte_t) + sizeof(word) * (If_CluWordNum2(p->pPars->nLutSize) - 1) );
|
||||
if ( p->pHashTable[t] == NULL )
|
||||
{
|
||||
// decide how large should be the table
|
||||
int nEntriesMax1 = 4 * If_CluPrimeCudd2( Vec_PtrSize(p->vObjs) * p->pPars->nCutsMax );
|
||||
int nEntriesMax2 = (int)(((double)CLU_MEM_MAX * (1 << 20)) / If_CluWordNum2(p->pPars->nLutSize) / 8);
|
||||
// int nEntriesMax2 = 10000;
|
||||
// create table
|
||||
p->nTableSize[t] = If_CluPrimeCudd2( Abc_MinInt(nEntriesMax1, nEntriesMax2)/2 );
|
||||
p->pHashTable[t] = ABC_CALLOC( void *, p->nTableSize[t] );
|
||||
}
|
||||
// check if this entry exists
|
||||
HashKey = If_CluHashKey2( pTruth, nWords, p->nTableSize[t] );
|
||||
for ( pEntry = ((If_Hte_t **)p->pHashTable[t])[HashKey]; pEntry; pEntry = pEntry->pNext )
|
||||
if ( memcmp(pEntry->pTruth, pTruth, sizeof(word) * nWords) == 0 )
|
||||
{
|
||||
pEntry->Counter++;
|
||||
return &pEntry->Group;
|
||||
}
|
||||
// resize the hash table
|
||||
if ( p->nTableEntries[t] >= 2 * p->nTableSize[t] )
|
||||
{
|
||||
// collect useful entries
|
||||
If_Hte_t * pPrev;
|
||||
Vec_Ptr_t * vUseful = Vec_PtrAlloc( p->nTableEntries[t] );
|
||||
int i, Median = If_CluHashFindMedian2( p, t );
|
||||
for ( i = 0; i < p->nTableSize[t]; i++ )
|
||||
{
|
||||
for ( pEntry = ((If_Hte_t **)p->pHashTable[t])[i]; pEntry; )
|
||||
{
|
||||
if ( (int)pEntry->Counter > Median )
|
||||
{
|
||||
Vec_PtrPush( vUseful, pEntry );
|
||||
pEntry = pEntry->pNext;
|
||||
}
|
||||
else
|
||||
{
|
||||
pPrev = pEntry->pNext;
|
||||
Mem_FixedEntryRecycle( p->pMemEntries, (char *)pEntry );
|
||||
pEntry = pPrev;
|
||||
}
|
||||
}
|
||||
}
|
||||
// add useful entries
|
||||
memset( p->pHashTable[t], 0, sizeof(void *) * p->nTableSize[t] );
|
||||
Vec_PtrForEachEntry( If_Hte_t *, vUseful, pEntry, i )
|
||||
{
|
||||
HashKey = If_CluHashKey2( pEntry->pTruth, nWords, p->nTableSize[t] );
|
||||
pPrev = ((If_Hte_t **)p->pHashTable[t])[HashKey];
|
||||
if ( pPrev == NULL || pEntry->Counter >= pPrev->Counter )
|
||||
{
|
||||
pEntry->pNext = pPrev;
|
||||
((If_Hte_t **)p->pHashTable[t])[HashKey] = pEntry;
|
||||
}
|
||||
else
|
||||
{
|
||||
while ( pPrev->pNext && pEntry->Counter < pPrev->pNext->Counter )
|
||||
pPrev = pPrev->pNext;
|
||||
pEntry->pNext = pPrev->pNext;
|
||||
pPrev->pNext = pEntry;
|
||||
}
|
||||
}
|
||||
p->nTableEntries[t] = Vec_PtrSize( vUseful );
|
||||
Vec_PtrFree( vUseful );
|
||||
}
|
||||
// create entry
|
||||
p->nTableEntries[t]++;
|
||||
pEntry = (If_Hte_t *)Mem_FixedEntryFetch( p->pMemEntries );
|
||||
memcpy( pEntry->pTruth, pTruth, sizeof(word) * nWords );
|
||||
pEntry->Group = CLU_UNUSED;
|
||||
pEntry->Counter = 1;
|
||||
// insert at the beginning
|
||||
// pEntry->pNext = ((If_Hte_t **)p->pHashTable[t])[HashKey];
|
||||
// ((If_Hte_t **)p->pHashTable[t])[HashKey] = pEntry;
|
||||
// insert at the end
|
||||
pEntry->pNext = NULL;
|
||||
for ( pPrev = ((If_Hte_t **)p->pHashTable[t])[HashKey]; pPrev && pPrev->pNext; pPrev = pPrev->pNext );
|
||||
if ( pPrev == NULL )
|
||||
((If_Hte_t **)p->pHashTable[t])[HashKey] = pEntry;
|
||||
else
|
||||
pPrev->pNext = pEntry;
|
||||
return &pEntry->Group;
|
||||
}
|
||||
|
||||
// returns if successful
|
||||
int If_CluCheck66( 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 = acd66_evaluate( pTruth0, nVars, 0 );
|
||||
}
|
||||
|
||||
if ( pHashed )
|
||||
*pHashed = If_CluGrp2Uns2( &G1 );
|
||||
|
||||
return G1.nVars;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Performs ACD into 66 cascade.]
|
||||
|
|
@ -79,7 +327,7 @@ int If_CutPerformCheck66( If_Man_t * p, unsigned * pTruth0, int nVars, int nLeav
|
|||
return 1;
|
||||
|
||||
// derive the decomposition
|
||||
return (int)(acd66_evaluate( (word *)pTruth, nVars, 1 ) > 0 );
|
||||
return If_CluCheck66(p, (word*)pTruth, nVars, 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
Loading…
Reference in New Issue