mirror of https://github.com/YosysHQ/abc.git
224 lines
7.7 KiB
C
224 lines
7.7 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [fraigCanon.c]
|
|
|
|
PackageName [FRAIG: Functionally reduced AND-INV graphs.]
|
|
|
|
Synopsis [AND-node creation and elementary AND-operation.]
|
|
|
|
Author [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 2.0. Started - October 1, 2004]
|
|
|
|
Revision [$Id: fraigCanon.c,v 1.4 2005/07/08 01:01:31 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include <limits.h>
|
|
#include "fraigInt.h"
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [The internal AND operation for the two FRAIG nodes.]
|
|
|
|
Description [This procedure is the core of the FRAIG package, because
|
|
it performs the two-step canonicization of FRAIG nodes. The first step
|
|
involves the lookup in the structural hash table (which hashes two ANDs
|
|
into a node that has them as fanins, if such a node exists). If the node
|
|
is not found in the structural hash table, an attempt is made to find a
|
|
functionally equivalent node in another hash table (which hashes the
|
|
simulation info into the nodes, which has this simulation info). Some
|
|
tricks used on the way are described in the comments to the code and
|
|
in the paper "FRAIGs: Functionally reduced AND-INV graphs".]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Fraig_Node_t * Fraig_NodeAndCanon( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2 )
|
|
{
|
|
Fraig_Node_t * pNodeNew, * pNodeOld, * pNodeRepr;
|
|
int fUseSatCheck;
|
|
// int RetValue;
|
|
|
|
// check for trivial cases
|
|
if ( p1 == p2 )
|
|
return p1;
|
|
if ( p1 == Fraig_Not(p2) )
|
|
return Fraig_Not(pMan->pConst1);
|
|
if ( Fraig_NodeIsConst(p1) )
|
|
{
|
|
if ( p1 == pMan->pConst1 )
|
|
return p2;
|
|
return Fraig_Not(pMan->pConst1);
|
|
}
|
|
if ( Fraig_NodeIsConst(p2) )
|
|
{
|
|
if ( p2 == pMan->pConst1 )
|
|
return p1;
|
|
return Fraig_Not(pMan->pConst1);
|
|
}
|
|
/*
|
|
// check for less trivial cases
|
|
if ( Fraig_IsComplement(p1) )
|
|
{
|
|
if ( RetValue = Fraig_NodeIsInSupergate( Fraig_Regular(p1), p2 ) )
|
|
{
|
|
if ( RetValue == -1 )
|
|
pMan->nImplies0++;
|
|
else
|
|
pMan->nImplies1++;
|
|
|
|
if ( RetValue == -1 )
|
|
return p2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( RetValue = Fraig_NodeIsInSupergate( p1, p2 ) )
|
|
{
|
|
if ( RetValue == 1 )
|
|
pMan->nSimplifies1++;
|
|
else
|
|
pMan->nSimplifies0++;
|
|
|
|
if ( RetValue == 1 )
|
|
return p1;
|
|
return Fraig_Not(pMan->pConst1);
|
|
}
|
|
}
|
|
|
|
if ( Fraig_IsComplement(p2) )
|
|
{
|
|
if ( RetValue = Fraig_NodeIsInSupergate( Fraig_Regular(p2), p1 ) )
|
|
{
|
|
if ( RetValue == -1 )
|
|
pMan->nImplies0++;
|
|
else
|
|
pMan->nImplies1++;
|
|
|
|
if ( RetValue == -1 )
|
|
return p1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( RetValue = Fraig_NodeIsInSupergate( p2, p1 ) )
|
|
{
|
|
if ( RetValue == 1 )
|
|
pMan->nSimplifies1++;
|
|
else
|
|
pMan->nSimplifies0++;
|
|
|
|
if ( RetValue == 1 )
|
|
return p2;
|
|
return Fraig_Not(pMan->pConst1);
|
|
}
|
|
}
|
|
*/
|
|
// perform level-one structural hashing
|
|
if ( Fraig_HashTableLookupS( pMan, p1, p2, &pNodeNew ) ) // the node with these children is found
|
|
{
|
|
// if the existent node is part of the cone of unused logic
|
|
// (that is logic feeding the node which is equivalent to the given node)
|
|
// return the canonical representative of this node
|
|
// determine the phase of the given node, with respect to its canonical form
|
|
pNodeRepr = Fraig_Regular(pNodeNew)->pRepr;
|
|
if ( pMan->fFuncRed && pNodeRepr )
|
|
return Fraig_NotCond( pNodeRepr, Fraig_IsComplement(pNodeNew) ^ Fraig_NodeComparePhase(Fraig_Regular(pNodeNew), pNodeRepr) );
|
|
// otherwise, the node is itself a canonical representative, return it
|
|
return pNodeNew;
|
|
}
|
|
// the same node is not found, but the new one is created
|
|
|
|
// if one level hashing is requested (without functionality hashing), return
|
|
if ( !pMan->fFuncRed )
|
|
return pNodeNew;
|
|
|
|
// check if the new node is unique using the simulation info
|
|
if ( pNodeNew->nOnes == 0 || pNodeNew->nOnes == (unsigned)pMan->nWordsRand * 32 )
|
|
{
|
|
pMan->nSatZeros++;
|
|
if ( !pMan->fDoSparse ) // if we do not do sparse functions, skip
|
|
return pNodeNew;
|
|
// check the sparse function simulation hash table
|
|
pNodeOld = Fraig_HashTableLookupF0( pMan, pNodeNew );
|
|
if ( pNodeOld == NULL ) // the node is unique (it is added to the table)
|
|
return pNodeNew;
|
|
}
|
|
else
|
|
{
|
|
// check the simulation hash table
|
|
pNodeOld = Fraig_HashTableLookupF( pMan, pNodeNew );
|
|
if ( pNodeOld == NULL ) // the node is unique
|
|
return pNodeNew;
|
|
}
|
|
assert( pNodeOld->pRepr == 0 );
|
|
// there is another node which looks the same according to simulation
|
|
|
|
// use SAT to resolve the ambiguity
|
|
fUseSatCheck = (pMan->nInspLimit == 0 || Fraig_ManReadInspects(pMan) < pMan->nInspLimit);
|
|
if ( fUseSatCheck && Fraig_NodeIsEquivalent( pMan, pNodeOld, pNodeNew, pMan->nBTLimit, 1000000 ) )
|
|
{
|
|
// set the node to be equivalent with this node
|
|
// to prevent loops, only set if the old node is not in the TFI of the new node
|
|
// the loop may happen in the following case: suppose
|
|
// NodeC = AND(NodeA, NodeB) and at the same time NodeA => NodeB
|
|
// in this case, NodeA and NodeC are functionally equivalent
|
|
// however, NodeA is a fanin of node NodeC (this leads to the loop)
|
|
// add the node to the list of equivalent nodes or dereference it
|
|
if ( pMan->fChoicing && !Fraig_CheckTfi( pMan, pNodeOld, pNodeNew ) )
|
|
{
|
|
// if the old node is not in the TFI of the new node and choicing
|
|
// is enabled, add the new node to the list of equivalent ones
|
|
pNodeNew->pNextE = pNodeOld->pNextE;
|
|
pNodeOld->pNextE = pNodeNew;
|
|
}
|
|
// set the canonical representative of this node
|
|
pNodeNew->pRepr = pNodeOld;
|
|
// return the equivalent node
|
|
return Fraig_NotCond( pNodeOld, Fraig_NodeComparePhase(pNodeOld, pNodeNew) );
|
|
}
|
|
|
|
// now we add another member to this simulation class
|
|
if ( pNodeNew->nOnes == 0 || pNodeNew->nOnes == (unsigned)pMan->nWordsRand * 32 )
|
|
{
|
|
Fraig_Node_t * pNodeTemp;
|
|
assert( pMan->fDoSparse );
|
|
pNodeTemp = Fraig_HashTableLookupF0( pMan, pNodeNew );
|
|
// assert( pNodeTemp == NULL );
|
|
// Fraig_HashTableInsertF0( pMan, pNodeNew );
|
|
}
|
|
else
|
|
{
|
|
pNodeNew->pNextD = pNodeOld->pNextD;
|
|
pNodeOld->pNextD = pNodeNew;
|
|
}
|
|
// return the new node
|
|
assert( pNodeNew->pRepr == 0 );
|
|
return pNodeNew;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
ABC_NAMESPACE_IMPL_END
|
|
|