blob: 03a2ac10c58da04cdc7669bd1646f23a1fe31051 [file] [log] [blame]
/**CFile****************************************************************
FileName [fraigTable.c]
PackageName [FRAIG: Functionally reduced AND-INV graphs.]
Synopsis [Structural and functional hash tables.]
Author [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
Affiliation [UC Berkeley]
Date [Ver. 2.0. Started - October 1, 2004]
Revision [$Id: fraigTable.c,v 1.7 2005/07/08 01:01:34 alanmi Exp $]
***********************************************************************/
#include "fraigInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static void Fraig_TableResizeS( Fraig_HashTable_t * p );
static void Fraig_TableResizeF( Fraig_HashTable_t * p, int fUseSimR );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Allocates the hash table.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Fraig_HashTable_t * Fraig_HashTableCreate( int nSize )
{
Fraig_HashTable_t * p;
// allocate the table
p = ABC_ALLOC( Fraig_HashTable_t, 1 );
memset( p, 0, sizeof(Fraig_HashTable_t) );
// allocate and clean the bins
p->nBins = Abc_PrimeCudd(nSize);
p->pBins = ABC_ALLOC( Fraig_Node_t *, p->nBins );
memset( p->pBins, 0, sizeof(Fraig_Node_t *) * p->nBins );
return p;
}
/**Function*************************************************************
Synopsis [Deallocates the supergate hash table.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Fraig_HashTableFree( Fraig_HashTable_t * p )
{
ABC_FREE( p->pBins );
ABC_FREE( p );
}
/**Function*************************************************************
Synopsis [Looks up an entry in the structural hash table.]
Description [If the entry with the same children does not exists,
creates it, inserts it into the table, and returns 0. If the entry
with the same children exists, finds it, and return 1. In both cases,
the new/old entry is returned in ppNodeRes.]
SideEffects []
SeeAlso []
***********************************************************************/
int Fraig_HashTableLookupS( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2, Fraig_Node_t ** ppNodeRes )
{
Fraig_HashTable_t * p = pMan->pTableS;
Fraig_Node_t * pEnt;
unsigned Key;
// order the arguments
if ( Fraig_Regular(p1)->Num > Fraig_Regular(p2)->Num )
pEnt = p1, p1 = p2, p2 = pEnt;
Key = Fraig_HashKey2( p1, p2, p->nBins );
Fraig_TableBinForEachEntryS( p->pBins[Key], pEnt )
if ( pEnt->p1 == p1 && pEnt->p2 == p2 )
{
*ppNodeRes = pEnt;
return 1;
}
// check if it is a good time for table resizing
if ( p->nEntries >= 2 * p->nBins )
{
Fraig_TableResizeS( p );
Key = Fraig_HashKey2( p1, p2, p->nBins );
}
// create the new node
pEnt = Fraig_NodeCreate( pMan, p1, p2 );
// add the node to the corresponding linked list in the table
pEnt->pNextS = p->pBins[Key];
p->pBins[Key] = pEnt;
*ppNodeRes = pEnt;
p->nEntries++;
return 0;
}
/**Function*************************************************************
Synopsis [Insert the entry in the functional hash table.]
Description [If the entry with the same key exists, return it right away.
If the entry with the same key does not exists, inserts it and returns NULL. ]
SideEffects []
SeeAlso []
***********************************************************************/
Fraig_Node_t * Fraig_HashTableLookupF( Fraig_Man_t * pMan, Fraig_Node_t * pNode )
{
Fraig_HashTable_t * p = pMan->pTableF;
Fraig_Node_t * pEnt, * pEntD;
unsigned Key;
// go through the hash table entries
Key = pNode->uHashR % p->nBins;
Fraig_TableBinForEachEntryF( p->pBins[Key], pEnt )
{
// if their simulation info differs, skip
if ( !Fraig_CompareSimInfo( pNode, pEnt, pMan->nWordsRand, 1 ) )
continue;
// equivalent up to the complement
Fraig_TableBinForEachEntryD( pEnt, pEntD )
{
// if their simulation info differs, skip
if ( !Fraig_CompareSimInfo( pNode, pEntD, pMan->iWordStart, 0 ) )
continue;
// found a simulation-equivalent node
return pEntD;
}
// did not find a simulation equivalent node
// add the node to the corresponding linked list
pNode->pNextD = pEnt->pNextD;
pEnt->pNextD = pNode;
// return NULL, because there is no functional equivalence in this case
return NULL;
}
// check if it is a good time for table resizing
if ( p->nEntries >= 2 * p->nBins )
{
Fraig_TableResizeF( p, 1 );
Key = pNode->uHashR % p->nBins;
}
// add the node to the corresponding linked list in the table
pNode->pNextF = p->pBins[Key];
p->pBins[Key] = pNode;
p->nEntries++;
// return NULL, because there is no functional equivalence in this case
return NULL;
}
/**Function*************************************************************
Synopsis [Insert the entry in the functional hash table.]
Description [If the entry with the same key exists, return it right away.
If the entry with the same key does not exists, inserts it and returns NULL. ]
SideEffects []
SeeAlso []
***********************************************************************/
Fraig_Node_t * Fraig_HashTableLookupF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode )
{
Fraig_HashTable_t * p = pMan->pTableF0;
Fraig_Node_t * pEnt;
unsigned Key;
// go through the hash table entries
Key = pNode->uHashD % p->nBins;
Fraig_TableBinForEachEntryF( p->pBins[Key], pEnt )
{
// if their simulation info differs, skip
if ( !Fraig_CompareSimInfo( pNode, pEnt, pMan->iWordStart, 0 ) )
continue;
// found a simulation-equivalent node
return pEnt;
}
// check if it is a good time for table resizing
if ( p->nEntries >= 2 * p->nBins )
{
Fraig_TableResizeF( p, 0 );
Key = pNode->uHashD % p->nBins;
}
// add the node to the corresponding linked list in the table
pNode->pNextF = p->pBins[Key];
p->pBins[Key] = pNode;
p->nEntries++;
// return NULL, because there is no functional equivalence in this case
return NULL;
}
/**Function*************************************************************
Synopsis [Insert the entry in the functional hash table.]
Description [Unconditionally add the node to the corresponding
linked list in the table.]
SideEffects []
SeeAlso []
***********************************************************************/
void Fraig_HashTableInsertF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode )
{
Fraig_HashTable_t * p = pMan->pTableF0;
unsigned Key = pNode->uHashD % p->nBins;
pNode->pNextF = p->pBins[Key];
p->pBins[Key] = pNode;
p->nEntries++;
}
/**Function*************************************************************
Synopsis [Resizes the table.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Fraig_TableResizeS( Fraig_HashTable_t * p )
{
Fraig_Node_t ** pBinsNew;
Fraig_Node_t * pEnt, * pEnt2;
int nBinsNew, Counter, i;
abctime clk;
unsigned Key;
clk = Abc_Clock();
// get the new table size
nBinsNew = Abc_PrimeCudd(2 * p->nBins);
// allocate a new array
pBinsNew = ABC_ALLOC( Fraig_Node_t *, nBinsNew );
memset( pBinsNew, 0, sizeof(Fraig_Node_t *) * nBinsNew );
// rehash the entries from the old table
Counter = 0;
for ( i = 0; i < p->nBins; i++ )
Fraig_TableBinForEachEntrySafeS( p->pBins[i], pEnt, pEnt2 )
{
Key = Fraig_HashKey2( pEnt->p1, pEnt->p2, nBinsNew );
pEnt->pNextS = pBinsNew[Key];
pBinsNew[Key] = pEnt;
Counter++;
}
assert( Counter == p->nEntries );
// printf( "Increasing the structural table size from %6d to %6d. ", p->nBins, nBinsNew );
// ABC_PRT( "Time", Abc_Clock() - clk );
// replace the table and the parameters
ABC_FREE( p->pBins );
p->pBins = pBinsNew;
p->nBins = nBinsNew;
}
/**Function*************************************************************
Synopsis [Resizes the table.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Fraig_TableResizeF( Fraig_HashTable_t * p, int fUseSimR )
{
Fraig_Node_t ** pBinsNew;
Fraig_Node_t * pEnt, * pEnt2;
int nBinsNew, Counter, i;
abctime clk;
unsigned Key;
clk = Abc_Clock();
// get the new table size
nBinsNew = Abc_PrimeCudd(2 * p->nBins);
// allocate a new array
pBinsNew = ABC_ALLOC( Fraig_Node_t *, nBinsNew );
memset( pBinsNew, 0, sizeof(Fraig_Node_t *) * nBinsNew );
// rehash the entries from the old table
Counter = 0;
for ( i = 0; i < p->nBins; i++ )
Fraig_TableBinForEachEntrySafeF( p->pBins[i], pEnt, pEnt2 )
{
if ( fUseSimR )
Key = pEnt->uHashR % nBinsNew;
else
Key = pEnt->uHashD % nBinsNew;
pEnt->pNextF = pBinsNew[Key];
pBinsNew[Key] = pEnt;
Counter++;
}
assert( Counter == p->nEntries );
// printf( "Increasing the functional table size from %6d to %6d. ", p->nBins, nBinsNew );
// ABC_PRT( "Time", Abc_Clock() - clk );
// replace the table and the parameters
ABC_FREE( p->pBins );
p->pBins = pBinsNew;
p->nBins = nBinsNew;
}
/**Function*************************************************************
Synopsis [Compares two pieces of simulation info.]
Description [Returns 1 if they are equal.]
SideEffects []
SeeAlso []
***********************************************************************/
int Fraig_CompareSimInfo( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand )
{
int i;
assert( !Fraig_IsComplement(pNode1) );
assert( !Fraig_IsComplement(pNode2) );
if ( fUseRand )
{
// if their signatures differ, skip
if ( pNode1->uHashR != pNode2->uHashR )
return 0;
// check the simulation info
for ( i = 0; i < iWordLast; i++ )
if ( pNode1->puSimR[i] != pNode2->puSimR[i] )
return 0;
}
else
{
// if their signatures differ, skip
if ( pNode1->uHashD != pNode2->uHashD )
return 0;
// check the simulation info
for ( i = 0; i < iWordLast; i++ )
if ( pNode1->puSimD[i] != pNode2->puSimD[i] )
return 0;
}
return 1;
}
/**Function*************************************************************
Synopsis [Find the number of the different pattern.]
Description [Returns -1 if there is no such pattern]
SideEffects []
SeeAlso []
***********************************************************************/
int Fraig_FindFirstDiff( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int fCompl, int iWordLast, int fUseRand )
{
int i, v;
assert( !Fraig_IsComplement(pNode1) );
assert( !Fraig_IsComplement(pNode2) );
// take into account possible internal complementation
fCompl ^= pNode1->fInv;
fCompl ^= pNode2->fInv;
// find the pattern
if ( fCompl )
{
if ( fUseRand )
{
for ( i = 0; i < iWordLast; i++ )
if ( pNode1->puSimR[i] != ~pNode2->puSimR[i] )
for ( v = 0; v < 32; v++ )
if ( (pNode1->puSimR[i] ^ ~pNode2->puSimR[i]) & (1 << v) )
return i * 32 + v;
}
else
{
for ( i = 0; i < iWordLast; i++ )
if ( pNode1->puSimD[i] != ~pNode2->puSimD[i] )
for ( v = 0; v < 32; v++ )
if ( (pNode1->puSimD[i] ^ ~pNode2->puSimD[i]) & (1 << v) )
return i * 32 + v;
}
}
else
{
if ( fUseRand )
{
for ( i = 0; i < iWordLast; i++ )
if ( pNode1->puSimR[i] != pNode2->puSimR[i] )
for ( v = 0; v < 32; v++ )
if ( (pNode1->puSimR[i] ^ pNode2->puSimR[i]) & (1 << v) )
return i * 32 + v;
}
else
{
for ( i = 0; i < iWordLast; i++ )
if ( pNode1->puSimD[i] != pNode2->puSimD[i] )
for ( v = 0; v < 32; v++ )
if ( (pNode1->puSimD[i] ^ pNode2->puSimD[i]) & (1 << v) )
return i * 32 + v;
}
}
return -1;
}
/**Function*************************************************************
Synopsis [Compares two pieces of simulation info.]
Description [Returns 1 if they are equal.]
SideEffects []
SeeAlso []
***********************************************************************/
int Fraig_CompareSimInfoUnderMask( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask )
{
unsigned * pSims1, * pSims2;
int i;
assert( !Fraig_IsComplement(pNode1) );
assert( !Fraig_IsComplement(pNode2) );
// get hold of simulation info
pSims1 = fUseRand? pNode1->puSimR : pNode1->puSimD;
pSims2 = fUseRand? pNode2->puSimR : pNode2->puSimD;
// check the simulation info
for ( i = 0; i < iWordLast; i++ )
if ( (pSims1[i] & puMask[i]) != (pSims2[i] & puMask[i]) )
return 0;
return 1;
}
/**Function*************************************************************
Synopsis [Compares two pieces of simulation info.]
Description [Returns 1 if they are equal.]
SideEffects []
SeeAlso []
***********************************************************************/
void Fraig_CollectXors( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask )
{
unsigned * pSims1, * pSims2;
int i;
assert( !Fraig_IsComplement(pNode1) );
assert( !Fraig_IsComplement(pNode2) );
// get hold of simulation info
pSims1 = fUseRand? pNode1->puSimR : pNode1->puSimD;
pSims2 = fUseRand? pNode2->puSimR : pNode2->puSimD;
// check the simulation info
for ( i = 0; i < iWordLast; i++ )
puMask[i] = ( pSims1[i] ^ pSims2[i] );
}
/**Function*************************************************************
Synopsis [Prints stats of the structural table.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Fraig_TablePrintStatsS( Fraig_Man_t * pMan )
{
Fraig_HashTable_t * pT = pMan->pTableS;
Fraig_Node_t * pNode;
int i, Counter;
printf( "Structural table. Table size = %d. Number of entries = %d.\n", pT->nBins, pT->nEntries );
for ( i = 0; i < pT->nBins; i++ )
{
Counter = 0;
Fraig_TableBinForEachEntryS( pT->pBins[i], pNode )
Counter++;
if ( Counter > 1 )
{
printf( "%d ", Counter );
if ( Counter > 50 )
printf( "{%d} ", i );
}
}
printf( "\n" );
}
/**Function*************************************************************
Synopsis [Prints stats of the structural table.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Fraig_TablePrintStatsF( Fraig_Man_t * pMan )
{
Fraig_HashTable_t * pT = pMan->pTableF;
Fraig_Node_t * pNode;
int i, Counter;
printf( "Functional table. Table size = %d. Number of entries = %d.\n", pT->nBins, pT->nEntries );
for ( i = 0; i < pT->nBins; i++ )
{
Counter = 0;
Fraig_TableBinForEachEntryF( pT->pBins[i], pNode )
Counter++;
if ( Counter > 1 )
printf( "{%d} ", Counter );
}
printf( "\n" );
}
/**Function*************************************************************
Synopsis [Prints stats of the structural table.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Fraig_TablePrintStatsF0( Fraig_Man_t * pMan )
{
Fraig_HashTable_t * pT = pMan->pTableF0;
Fraig_Node_t * pNode;
int i, Counter;
printf( "Zero-node table. Table size = %d. Number of entries = %d.\n", pT->nBins, pT->nEntries );
for ( i = 0; i < pT->nBins; i++ )
{
Counter = 0;
Fraig_TableBinForEachEntryF( pT->pBins[i], pNode )
Counter++;
if ( Counter == 0 )
continue;
/*
printf( "\nBin = %4d : Number of entries = %4d\n", i, Counter );
Fraig_TableBinForEachEntryF( pT->pBins[i], pNode )
printf( "Node %5d. Hash = %10d.\n", pNode->Num, pNode->uHashD );
*/
}
printf( "\n" );
}
/**Function*************************************************************
Synopsis [Rehashes the table after the simulation info has changed.]
Description [Assumes that the hash values have been updated after performing
additional simulation. Rehashes the table using the new hash values.
Uses pNextF to link the entries in the bins. Uses pNextD to link the entries
with identical hash values. Returns 1 if the identical entries have been found.
Note that identical hash values may mean that the simulation data is different.]
SideEffects []
SeeAlso []
***********************************************************************/
int Fraig_TableRehashF0( Fraig_Man_t * pMan, int fLinkEquiv )
{
Fraig_HashTable_t * pT = pMan->pTableF0;
Fraig_Node_t ** pBinsNew;
Fraig_Node_t * pEntF, * pEntF2, * pEnt, * pEntD2, * pEntN;
int ReturnValue, Counter, i;
unsigned Key;
// allocate a new array of bins
pBinsNew = ABC_ALLOC( Fraig_Node_t *, pT->nBins );
memset( pBinsNew, 0, sizeof(Fraig_Node_t *) * pT->nBins );
// rehash the entries in the table
// go through all the nodes in the F-lists (and possible in D-lists, if used)
Counter = 0;
ReturnValue = 0;
for ( i = 0; i < pT->nBins; i++ )
Fraig_TableBinForEachEntrySafeF( pT->pBins[i], pEntF, pEntF2 )
Fraig_TableBinForEachEntrySafeD( pEntF, pEnt, pEntD2 )
{
// decide where to put entry pEnt
Key = pEnt->uHashD % pT->nBins;
if ( fLinkEquiv )
{
// go through the entries in the new bin
Fraig_TableBinForEachEntryF( pBinsNew[Key], pEntN )
{
// if they have different values skip
if ( pEnt->uHashD != pEntN->uHashD )
continue;
// they have the same hash value, add pEnt to the D-list pEnt3
pEnt->pNextD = pEntN->pNextD;
pEntN->pNextD = pEnt;
ReturnValue = 1;
Counter++;
break;
}
if ( pEntN != NULL ) // already linked
continue;
// we did not find equal entry
}
// link the new entry
pEnt->pNextF = pBinsNew[Key];
pBinsNew[Key] = pEnt;
pEnt->pNextD = NULL;
Counter++;
}
assert( Counter == pT->nEntries );
// replace the table and the parameters
ABC_FREE( pT->pBins );
pT->pBins = pBinsNew;
return ReturnValue;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END