blob: d9873d76bb412402d78c06977d95940dedc738e9 [file] [log] [blame]
/**CFile****************************************************************
FileName [giaHash.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Scalable AIG package.]
Synopsis [Structural hashing.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: giaHash.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "gia.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Returns the place where this node is stored (or should be stored).]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Gia_ManHashOne( int iLit0, int iLit1, int iLitC, int TableSize )
{
unsigned Key = iLitC * 2011;
Key += Abc_Lit2Var(iLit0) * 7937;
Key += Abc_Lit2Var(iLit1) * 2971;
Key += Abc_LitIsCompl(iLit0) * 911;
Key += Abc_LitIsCompl(iLit1) * 353;
return (int)(Key % TableSize);
}
static inline int * Gia_ManHashFind( Gia_Man_t * p, int iLit0, int iLit1, int iLitC )
{
int iThis, * pPlace = Vec_IntEntryP( &p->vHTable, Gia_ManHashOne( iLit0, iLit1, iLitC, Vec_IntSize(&p->vHTable) ) );
assert( Vec_IntSize(&p->vHash) == Gia_ManObjNum(p) );
assert( p->pMuxes || iLit0 < iLit1 );
assert( iLit0 < iLit1 || (!Abc_LitIsCompl(iLit0) && !Abc_LitIsCompl(iLit1)) );
assert( iLitC == -1 || !Abc_LitIsCompl(iLit1) );
for ( ; (iThis = *pPlace); pPlace = Vec_IntEntryP(&p->vHash, iThis) )
{
Gia_Obj_t * pThis = Gia_ManObj( p, iThis );
if ( Gia_ObjFaninLit0(pThis, iThis) == iLit0 && Gia_ObjFaninLit1(pThis, iThis) == iLit1 && (p->pMuxes == NULL || Gia_ObjFaninLit2p(p, pThis) == iLitC) )
break;
}
return pPlace;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManHashLookupInt( Gia_Man_t * p, int iLit0, int iLit1 )
{
if ( iLit0 > iLit1 )
iLit0 ^= iLit1, iLit1 ^= iLit0, iLit0 ^= iLit1;
return Abc_Var2Lit( *Gia_ManHashFind( p, iLit0, iLit1, -1 ), 0 );
}
int Gia_ManHashLookup( Gia_Man_t * p, Gia_Obj_t * p0, Gia_Obj_t * p1 )
{
int iLit0 = Gia_ObjToLit( p, p0 );
int iLit1 = Gia_ObjToLit( p, p1 );
return Gia_ManHashLookupInt( p, iLit0, iLit1 );
}
/**Function*************************************************************
Synopsis [Starts the hash table.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManHashAlloc( Gia_Man_t * p )
{
assert( Vec_IntSize(&p->vHTable) == 0 );
Vec_IntFill( &p->vHTable, Abc_PrimeCudd( Gia_ManAndNum(p) ? Gia_ManAndNum(p) + 1000 : p->nObjsAlloc ), 0 );
Vec_IntGrow( &p->vHash, Abc_MaxInt(Vec_IntSize(&p->vHTable), Gia_ManObjNum(p)) );
Vec_IntFill( &p->vHash, Gia_ManObjNum(p), 0 );
//printf( "Alloced table with %d entries.\n", Vec_IntSize(&p->vHTable) );
}
/**Function*************************************************************
Synopsis [Starts the hash table.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManHashStart( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int * pPlace, i;
Gia_ManHashAlloc( p );
Gia_ManForEachAnd( p, pObj, i )
{
pPlace = Gia_ManHashFind( p, Gia_ObjFaninLit0(pObj, i), Gia_ObjFaninLit1(pObj, i), Gia_ObjFaninLit2(p, i) );
assert( *pPlace == 0 );
*pPlace = i;
}
}
/**Function*************************************************************
Synopsis [Stops the hash table.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManHashStop( Gia_Man_t * p )
{
Vec_IntErase( &p->vHTable );
Vec_IntErase( &p->vHash );
}
/**Function*************************************************************
Synopsis [Resizes the hash table.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManHashResize( Gia_Man_t * p )
{
int i, iThis, iNext, Counter, Counter2, * pPlace;
Vec_Int_t vOld = p->vHTable;
assert( Vec_IntSize(&vOld) > 0 );
// replace the table
Vec_IntZero( &p->vHTable );
Vec_IntFill( &p->vHTable, Abc_PrimeCudd( 2 * Gia_ManAndNum(p) ), 0 );
// rehash the entries from the old table
Counter = 0;
Vec_IntForEachEntry( &vOld, iThis, i )
for ( iNext = Vec_IntEntry(&p->vHash, iThis);
iThis; iThis = iNext,
iNext = Vec_IntEntry(&p->vHash, iThis) )
{
Gia_Obj_t * pThis0 = Gia_ManObj( p, iThis );
Vec_IntWriteEntry( &p->vHash, iThis, 0 );
pPlace = Gia_ManHashFind( p, Gia_ObjFaninLit0(pThis0, iThis), Gia_ObjFaninLit1(pThis0, iThis), Gia_ObjFaninLit2p(p, pThis0) );
assert( *pPlace == 0 ); // should not be there
*pPlace = iThis;
assert( *pPlace != 0 );
Counter++;
}
Counter2 = Gia_ManAndNum(p) - Gia_ManBufNum(p);
assert( Counter == Counter2 );
// if ( p->fVerbose )
// printf( "Resizing GIA hash table: %d -> %d.\n", Vec_IntSize(&vOld), Vec_IntSize(&p->vHTable) );
Vec_IntErase( &vOld );
}
/**Function********************************************************************
Synopsis [Profiles the hash table.]
Description []
SideEffects []
SeeAlso []
******************************************************************************/
void Gia_ManHashProfile( Gia_Man_t * p )
{
int iEntry;
int i, Counter, Limit;
printf( "Table size = %d. Entries = %d. ", Vec_IntSize(&p->vHTable), Gia_ManAndNum(p) );
printf( "Hits = %d. Misses = %d.\n", (int)p->nHashHit, (int)p->nHashMiss );
Limit = Abc_MinInt( 1000, Vec_IntSize(&p->vHTable) );
for ( i = 0; i < Limit; i++ )
{
Counter = 0;
for ( iEntry = Vec_IntEntry(&p->vHTable, i);
iEntry;
iEntry = iEntry? Vec_IntEntry(&p->vHash, iEntry) : 0 )
Counter++;
if ( Counter )
printf( "%d ", Counter );
}
printf( "\n" );
}
/**Function*************************************************************
Synopsis [Recognizes what nodes are control and data inputs of a MUX.]
Description [If the node is a MUX, returns the control variable C.
Assigns nodes T and E to be the then and else variables of the MUX.
Node C is never complemented. Nodes T and E can be complemented.
This function also recognizes EXOR/NEXOR gates as MUXes.]
SideEffects []
SeeAlso []
***********************************************************************/
static inline Gia_Obj_t * Gia_ObjRecognizeMuxTwo( Gia_Obj_t * pNode0, Gia_Obj_t * pNode1, Gia_Obj_t ** ppNodeT, Gia_Obj_t ** ppNodeE )
{
assert( !Gia_IsComplement(pNode0) );
assert( !Gia_IsComplement(pNode1) );
// find the control variable
if ( Gia_ObjFanin1(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC1(pNode1)) )
{
// if ( FrGia_IsComplement(pNode1->p2) )
if ( Gia_ObjFaninC1(pNode0) )
{ // pNode2->p2 is positive phase of C
*ppNodeT = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1);
*ppNodeE = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1);
return Gia_ObjChild1(pNode1);//pNode2->p2;
}
else
{ // pNode1->p2 is positive phase of C
*ppNodeT = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1);
*ppNodeE = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1);
return Gia_ObjChild1(pNode0);//pNode1->p2;
}
}
else if ( Gia_ObjFanin0(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC0(pNode1)) )
{
// if ( FrGia_IsComplement(pNode1->p1) )
if ( Gia_ObjFaninC0(pNode0) )
{ // pNode2->p1 is positive phase of C
*ppNodeT = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2);
*ppNodeE = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2);
return Gia_ObjChild0(pNode1);//pNode2->p1;
}
else
{ // pNode1->p1 is positive phase of C
*ppNodeT = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2);
*ppNodeE = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2);
return Gia_ObjChild0(pNode0);//pNode1->p1;
}
}
else if ( Gia_ObjFanin0(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC1(pNode1)) )
{
// if ( FrGia_IsComplement(pNode1->p1) )
if ( Gia_ObjFaninC0(pNode0) )
{ // pNode2->p2 is positive phase of C
*ppNodeT = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1);
*ppNodeE = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2);
return Gia_ObjChild1(pNode1);//pNode2->p2;
}
else
{ // pNode1->p1 is positive phase of C
*ppNodeT = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2);
*ppNodeE = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1);
return Gia_ObjChild0(pNode0);//pNode1->p1;
}
}
else if ( Gia_ObjFanin1(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC0(pNode1)) )
{
// if ( FrGia_IsComplement(pNode1->p2) )
if ( Gia_ObjFaninC1(pNode0) )
{ // pNode2->p1 is positive phase of C
*ppNodeT = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2);
*ppNodeE = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1);
return Gia_ObjChild0(pNode1);//pNode2->p1;
}
else
{ // pNode1->p2 is positive phase of C
*ppNodeT = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1);
*ppNodeE = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2);
return Gia_ObjChild1(pNode0);//pNode1->p2;
}
}
assert( 0 ); // this is not MUX
return NULL;
}
/**Function*************************************************************
Synopsis [Rehashes AIG with mapping.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Gia_Obj_t * Gia_ManHashAndP( Gia_Man_t * p, Gia_Obj_t * p0, Gia_Obj_t * p1 )
{
return Gia_ObjFromLit( p, Gia_ManHashAnd( p, Gia_ObjToLit(p, p0), Gia_ObjToLit(p, p1) ) );
}
/**Function*************************************************************
Synopsis [Rehashes AIG with mapping.]
Description [http://fmv.jku.at/papers/BrummayerBiere-MEMICS06.pdf]
SideEffects []
SeeAlso []
***********************************************************************/
static inline Gia_Obj_t * Gia_ManAddStrash( Gia_Man_t * p, Gia_Obj_t * p0, Gia_Obj_t * p1 )
{
Gia_Obj_t * pNode0, * pNode1, * pFanA, * pFanB, * pFanC, * pFanD;
assert( p->fAddStrash );
pNode0 = Gia_Regular(p0);
pNode1 = Gia_Regular(p1);
if ( !Gia_ObjIsAnd(pNode0) && !Gia_ObjIsAnd(pNode1) )
return NULL;
pFanA = Gia_ObjIsAnd(pNode0) ? Gia_ObjChild0(pNode0) : NULL;
pFanB = Gia_ObjIsAnd(pNode0) ? Gia_ObjChild1(pNode0) : NULL;
pFanC = Gia_ObjIsAnd(pNode1) ? Gia_ObjChild0(pNode1) : NULL;
pFanD = Gia_ObjIsAnd(pNode1) ? Gia_ObjChild1(pNode1) : NULL;
if ( Gia_IsComplement(p0) )
{
if ( pFanA == Gia_Not(p1) || pFanB == Gia_Not(p1) )
return p1;
if ( pFanB == p1 )
return Gia_ManHashAndP( p, Gia_Not(pFanA), pFanB );
if ( pFanA == p1 )
return Gia_ManHashAndP( p, Gia_Not(pFanB), pFanA );
}
else
{
if ( pFanA == Gia_Not(p1) || pFanB == Gia_Not(p1) )
return Gia_ManConst0(p);
if ( pFanA == p1 || pFanB == p1 )
return p0;
}
if ( Gia_IsComplement(p1) )
{
if ( pFanC == Gia_Not(p0) || pFanD == Gia_Not(p0) )
return p0;
if ( pFanD == p0 )
return Gia_ManHashAndP( p, Gia_Not(pFanC), pFanD );
if ( pFanC == p0 )
return Gia_ManHashAndP( p, Gia_Not(pFanD), pFanC );
}
else
{
if ( pFanC == Gia_Not(p0) || pFanD == Gia_Not(p0) )
return Gia_ManConst0(p);
if ( pFanC == p0 || pFanD == p0 )
return p1;
}
if ( !Gia_IsComplement(p0) && !Gia_IsComplement(p1) )
{
if ( pFanA == Gia_Not(pFanC) || pFanA == Gia_Not(pFanD) || pFanB == Gia_Not(pFanC) || pFanB == Gia_Not(pFanD) )
return Gia_ManConst0(p);
if ( pFanA == pFanC || pFanB == pFanC )
return Gia_ManHashAndP( p, p0, pFanD );
if ( pFanB == pFanC || pFanB == pFanD )
return Gia_ManHashAndP( p, pFanA, p1 );
if ( pFanA == pFanD || pFanB == pFanD )
return Gia_ManHashAndP( p, p0, pFanC );
if ( pFanA == pFanC || pFanA == pFanD )
return Gia_ManHashAndP( p, pFanB, p1 );
}
else if ( Gia_IsComplement(p0) && !Gia_IsComplement(p1) )
{
if ( pFanA == Gia_Not(pFanC) || pFanA == Gia_Not(pFanD) || pFanB == Gia_Not(pFanC) || pFanB == Gia_Not(pFanD) )
return p1;
if ( pFanB == pFanC || pFanB == pFanD )
return Gia_ManHashAndP( p, Gia_Not(pFanA), p1 );
if ( pFanA == pFanC || pFanA == pFanD )
return Gia_ManHashAndP( p, Gia_Not(pFanB), p1 );
}
else if ( !Gia_IsComplement(p0) && Gia_IsComplement(p1) )
{
if ( pFanC == Gia_Not(pFanA) || pFanC == Gia_Not(pFanB) || pFanD == Gia_Not(pFanA) || pFanD == Gia_Not(pFanB) )
return p0;
if ( pFanD == pFanA || pFanD == pFanB )
return Gia_ManHashAndP( p, Gia_Not(pFanC), p0 );
if ( pFanC == pFanA || pFanC == pFanB )
return Gia_ManHashAndP( p, Gia_Not(pFanD), p0 );
}
else // if ( Gia_IsComplement(p0) && Gia_IsComplement(p1) )
{
if ( pFanA == pFanD && pFanB == Gia_Not(pFanC) )
return Gia_Not(pFanA);
if ( pFanB == pFanC && pFanA == Gia_Not(pFanD) )
return Gia_Not(pFanB);
if ( pFanA == pFanC && pFanB == Gia_Not(pFanD) )
return Gia_Not(pFanA);
if ( pFanB == pFanD && pFanA == Gia_Not(pFanC) )
return Gia_Not(pFanB);
}
/*
if ( !Gia_IsComplement(p0) || !Gia_IsComplement(p1) )
return NULL;
if ( !Gia_ObjIsAnd(pNode0) || !Gia_ObjIsAnd(pNode1) )
return NULL;
if ( (Gia_ObjFanin0(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC0(pNode1))) ||
(Gia_ObjFanin0(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC1(pNode1))) ||
(Gia_ObjFanin1(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC0(pNode1))) ||
(Gia_ObjFanin1(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC1(pNode1))) )
{
Gia_Obj_t * pNodeC, * pNodeT, * pNodeE;
int fCompl;
pNodeC = Gia_ObjRecognizeMuxTwo( pNode0, pNode1, &pNodeT, &pNodeE );
// using non-standard canonical rule for MUX (d0 is not compl; d1 may be compl)
if ( (fCompl = Gia_IsComplement(pNodeE)) )
{
pNodeE = Gia_Not(pNodeE);
pNodeT = Gia_Not(pNodeT);
}
pNode0 = Gia_ManHashAndP( p, Gia_Not(pNodeC), pNodeE );
pNode1 = Gia_ManHashAndP( p, pNodeC, pNodeT );
p->fAddStrash = 0;
pNodeC = Gia_NotCond( Gia_ManHashAndP( p, Gia_Not(pNode0), Gia_Not(pNode1) ), !fCompl );
p->fAddStrash = 1;
return pNodeC;
}
*/
return NULL;
}
/**Function*************************************************************
Synopsis [Hashes XOR gate.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManHashXorReal( Gia_Man_t * p, int iLit0, int iLit1 )
{
int fCompl = 0;
assert( p->fAddStrash == 0 );
if ( iLit0 < 2 )
return iLit0 ? Abc_LitNot(iLit1) : iLit1;
if ( iLit1 < 2 )
return iLit1 ? Abc_LitNot(iLit0) : iLit0;
if ( iLit0 == iLit1 )
return 0;
if ( iLit0 == Abc_LitNot(iLit1) )
return 1;
if ( (p->nObjs & 0xFF) == 0 && 2 * Vec_IntSize(&p->vHTable) < Gia_ManAndNum(p) )
Gia_ManHashResize( p );
if ( iLit0 < iLit1 )
iLit0 ^= iLit1, iLit1 ^= iLit0, iLit0 ^= iLit1;
if ( Abc_LitIsCompl(iLit0) )
iLit0 = Abc_LitNot(iLit0), fCompl ^= 1;
if ( Abc_LitIsCompl(iLit1) )
iLit1 = Abc_LitNot(iLit1), fCompl ^= 1;
{
int *pPlace = Gia_ManHashFind( p, iLit0, iLit1, -1 );
if ( *pPlace )
{
p->nHashHit++;
return Abc_Var2Lit( *pPlace, fCompl );
}
p->nHashMiss++;
if ( Vec_IntSize(&p->vHash) < Vec_IntCap(&p->vHash) )
*pPlace = Abc_Lit2Var( Gia_ManAppendXorReal( p, iLit0, iLit1 ) );
else
{
int iNode = Gia_ManAppendXorReal( p, iLit0, iLit1 );
pPlace = Gia_ManHashFind( p, iLit0, iLit1, -1 );
assert( *pPlace == 0 );
*pPlace = Abc_Lit2Var( iNode );
}
return Abc_Var2Lit( *pPlace, fCompl );
}
}
/**Function*************************************************************
Synopsis [Hashes MUX gate.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManHashMuxReal( Gia_Man_t * p, int iLitC, int iLit1, int iLit0 )
{
int fCompl = 0;
assert( p->fAddStrash == 0 );
if ( iLitC < 2 )
return iLitC ? iLit1 : iLit0;
if ( iLit0 < 2 )
return iLit0 ? Gia_ManHashOr(p, Abc_LitNot(iLitC), iLit1) : Gia_ManHashAnd(p, iLitC, iLit1);
if ( iLit1 < 2 )
return iLit1 ? Gia_ManHashOr(p, iLitC, iLit0) : Gia_ManHashAnd(p, Abc_LitNot(iLitC), iLit0);
assert( iLit0 > 1 && iLit1 > 1 && iLitC > 1 );
if ( iLit0 == iLit1 )
return iLit0;
if ( iLitC == iLit0 || iLitC == Abc_LitNot(iLit1) )
return Gia_ManHashAnd(p, iLit0, iLit1);
if ( iLitC == iLit1 || iLitC == Abc_LitNot(iLit0) )
return Gia_ManHashOr(p, iLit0, iLit1);
if ( Abc_Lit2Var(iLit0) == Abc_Lit2Var(iLit1) )
return Gia_ManHashXorReal( p, iLitC, iLit0 );
if ( iLit0 > iLit1 )
iLit0 ^= iLit1, iLit1 ^= iLit0, iLit0 ^= iLit1, iLitC = Abc_LitNot(iLitC);
if ( Abc_LitIsCompl(iLit1) )
iLit0 = Abc_LitNot(iLit0), iLit1 = Abc_LitNot(iLit1), fCompl = 1;
{
int *pPlace = Gia_ManHashFind( p, iLit0, iLit1, iLitC );
if ( *pPlace )
{
p->nHashHit++;
return Abc_Var2Lit( *pPlace, fCompl );
}
p->nHashMiss++;
if ( Vec_IntSize(&p->vHash) < Vec_IntCap(&p->vHash) )
*pPlace = Abc_Lit2Var( Gia_ManAppendMuxReal( p, iLitC, iLit1, iLit0 ) );
else
{
int iNode = Gia_ManAppendMuxReal( p, iLitC, iLit1, iLit0 );
pPlace = Gia_ManHashFind( p, iLit0, iLit1, iLitC );
assert( *pPlace == 0 );
*pPlace = Abc_Lit2Var( iNode );
}
return Abc_Var2Lit( *pPlace, fCompl );
}
}
/**Function*************************************************************
Synopsis [Hashes AND gate.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManHashAnd( Gia_Man_t * p, int iLit0, int iLit1 )
{
if ( iLit0 < 2 )
return iLit0 ? iLit1 : 0;
if ( iLit1 < 2 )
return iLit1 ? iLit0 : 0;
if ( iLit0 == iLit1 )
return iLit1;
if ( iLit0 == Abc_LitNot(iLit1) )
return 0;
if ( p->fGiaSimple )
{
assert( Vec_IntSize(&p->vHTable) == 0 );
return Gia_ManAppendAnd( p, iLit0, iLit1 );
}
if ( (p->nObjs & 0xFF) == 0 && 2 * Vec_IntSize(&p->vHTable) < Gia_ManAndNum(p) )
Gia_ManHashResize( p );
if ( p->fAddStrash )
{
Gia_Obj_t * pObj = Gia_ManAddStrash( p, Gia_ObjFromLit(p, iLit0), Gia_ObjFromLit(p, iLit1) );
if ( pObj != NULL )
return Gia_ObjToLit( p, pObj );
}
if ( iLit0 > iLit1 )
iLit0 ^= iLit1, iLit1 ^= iLit0, iLit0 ^= iLit1;
{
int * pPlace = Gia_ManHashFind( p, iLit0, iLit1, -1 );
if ( *pPlace )
{
p->nHashHit++;
return Abc_Var2Lit( *pPlace, 0 );
}
p->nHashMiss++;
if ( Vec_IntSize(&p->vHash) < Vec_IntCap(&p->vHash) )
*pPlace = Abc_Lit2Var( Gia_ManAppendAnd( p, iLit0, iLit1 ) );
else
{
int iNode = Gia_ManAppendAnd( p, iLit0, iLit1 );
pPlace = Gia_ManHashFind( p, iLit0, iLit1, -1 );
assert( *pPlace == 0 );
*pPlace = Abc_Lit2Var( iNode );
}
return Abc_Var2Lit( *pPlace, 0 );
}
}
int Gia_ManHashOr( Gia_Man_t * p, int iLit0, int iLit1 )
{
return Abc_LitNot(Gia_ManHashAnd( p, Abc_LitNot(iLit0), Abc_LitNot(iLit1) ));
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManHashAndTry( Gia_Man_t * p, int iLit0, int iLit1 )
{
if ( iLit0 < 2 )
return iLit0 ? iLit1 : 0;
if ( iLit1 < 2 )
return iLit1 ? iLit0 : 0;
if ( iLit0 == iLit1 )
return iLit1;
if ( iLit0 == Abc_LitNot(iLit1) )
return 0;
if ( iLit0 > iLit1 )
iLit0 ^= iLit1, iLit1 ^= iLit0, iLit0 ^= iLit1;
{
int * pPlace = Gia_ManHashFind( p, iLit0, iLit1, -1 );
if ( *pPlace )
return Abc_Var2Lit( *pPlace, 0 );
return -1;
}
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManHashXor( Gia_Man_t * p, int iLit0, int iLit1 )
{
if ( p->fGiaSimple )
return Gia_ManHashOr(p, Gia_ManHashAnd(p, iLit0, Abc_LitNot(iLit1)), Gia_ManHashAnd(p, Abc_LitNot(iLit0), iLit1) );
else
{
int fCompl = Abc_LitIsCompl(iLit0) ^ Abc_LitIsCompl(iLit1);
int iTemp0 = Gia_ManHashAnd( p, Abc_LitRegular(iLit0), Abc_LitNot(Abc_LitRegular(iLit1)) );
int iTemp1 = Gia_ManHashAnd( p, Abc_LitRegular(iLit1), Abc_LitNot(Abc_LitRegular(iLit0)) );
return Abc_LitNotCond( Gia_ManHashAnd( p, Abc_LitNot(iTemp0), Abc_LitNot(iTemp1) ), !fCompl );
}
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManHashMux( Gia_Man_t * p, int iCtrl, int iData1, int iData0 )
{
if ( p->fGiaSimple )
return Gia_ManHashOr(p, Gia_ManHashAnd(p, iCtrl, iData1), Gia_ManHashAnd(p, Abc_LitNot(iCtrl), iData0) );
else
{
int iTemp0, iTemp1, fCompl = 0;
if ( iData0 > iData1 )
iData0 ^= iData1, iData1 ^= iData0, iData0 ^= iData1, iCtrl = Abc_LitNot(iCtrl);
if ( Abc_LitIsCompl(iData1) )
iData0 = Abc_LitNot(iData0), iData1 = Abc_LitNot(iData1), fCompl = 1;
iTemp0 = Gia_ManHashAnd( p, Abc_LitNot(iCtrl), iData0 );
iTemp1 = Gia_ManHashAnd( p, iCtrl, iData1 );
return Abc_LitNotCond( Gia_ManHashAnd( p, Abc_LitNot(iTemp0), Abc_LitNot(iTemp1) ), !fCompl );
}
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManHashMaj( Gia_Man_t * p, int iData0, int iData1, int iData2 )
{
int iTemp0 = Gia_ManHashOr( p, iData1, iData2 );
int iTemp1 = Gia_ManHashAnd( p, iData0, iTemp0 );
int iTemp2 = Gia_ManHashAnd( p, iData1, iData2 );
return Gia_ManHashOr( p, iTemp1, iTemp2 );
}
/**Function*************************************************************
Synopsis [Rehashes AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Gia_ManRehash( Gia_Man_t * p, int fAddStrash )
{
Gia_Man_t * pNew, * pTemp;
Gia_Obj_t * pObj;
int i;
pNew = Gia_ManStart( Gia_ManObjNum(p) );
pNew->pName = Abc_UtilStrsav( p->pName );
pNew->pSpec = Abc_UtilStrsav( p->pSpec );
pNew->fAddStrash = fAddStrash;
Gia_ManHashAlloc( pNew );
Gia_ManConst0(p)->Value = 0;
Gia_ManForEachObj( p, pObj, i )
{
//if ( Gia_ObjIsBuf(pObj) )
// pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) );
//else
if ( Gia_ObjIsAnd(pObj) )
pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
else if ( Gia_ObjIsCi(pObj) )
pObj->Value = Gia_ManAppendCi( pNew );
else if ( Gia_ObjIsCo(pObj) )
pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
}
Gia_ManHashStop( pNew );
pNew->fAddStrash = 0;
Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
// printf( "Top gate is %s\n", Gia_ObjFaninC0(Gia_ManCo(pNew, 0))? "OR" : "AND" );
pNew = Gia_ManCleanup( pTemp = pNew );
Gia_ManStop( pTemp );
return pNew;
}
/**Function*************************************************************
Synopsis [Creates well-balanced AND gate.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManHashAndMulti( Gia_Man_t * p, Vec_Int_t * vLits )
{
if ( Vec_IntSize(vLits) == 0 )
return 0;
while ( Vec_IntSize(vLits) > 1 )
{
int i, k = 0, Lit1, Lit2, LitRes;
Vec_IntForEachEntryDouble( vLits, Lit1, Lit2, i )
{
LitRes = Gia_ManHashAnd( p, Lit1, Lit2 );
Vec_IntWriteEntry( vLits, k++, LitRes );
}
if ( Vec_IntSize(vLits) & 1 )
Vec_IntWriteEntry( vLits, k++, Vec_IntEntryLast(vLits) );
Vec_IntShrink( vLits, k );
}
assert( Vec_IntSize(vLits) == 1 );
return Vec_IntEntry(vLits, 0);
}
int Gia_ManHashAndMulti2( Gia_Man_t * p, Vec_Int_t * vLits )
{
int i, iLit, iRes = 1;
Vec_IntForEachEntry( vLits, iLit, i )
iRes = Gia_ManHashAnd( p, iRes, iLit );
return iRes;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END