summaryrefslogtreecommitdiffstats
path: root/src/base/abci/abcResub.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/base/abci/abcResub.c')
-rw-r--r--src/base/abci/abcResub.c801
1 files changed, 801 insertions, 0 deletions
diff --git a/src/base/abci/abcResub.c b/src/base/abci/abcResub.c
new file mode 100644
index 00000000..30e2eca2
--- /dev/null
+++ b/src/base/abci/abcResub.c
@@ -0,0 +1,801 @@
+/**CFile****************************************************************
+
+ FileName [abcResub.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Network and node package.]
+
+ Synopsis [Resubstitution manager.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: abcResub.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abc.h"
+#include "dec.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Abc_ResubMan_t_ Abc_ResubMan_t;
+struct Abc_ResubMan_t_
+{
+ // paramers
+ int nLeavesMax; // the max number of leaves in the cone
+ int nDivsMax; // the max number of divisors in the cone
+ // representation of the cone
+ Abc_Obj_t * pRoot; // the root of the cone
+ int nLeaves; // the number of leaves
+ int nDivs; // the number of all divisor (including leaves)
+ int nMffc; // the size of MFFC
+ Vec_Ptr_t * vDivs; // the divisors
+ // representation of the simulation info
+ int nBits; // the number of simulation bits
+ int nWords; // the number of unsigneds for siminfo
+ Vec_Ptr_t * vSims; // simulation info
+ unsigned * pInfo; // pointer to simulation info
+ // internal divisor storage
+ Vec_Ptr_t * vDivs1U; // the single-node unate divisors
+ Vec_Ptr_t * vDivs1B; // the single-node binate divisors
+ Vec_Ptr_t * vDivs2U0; // the double-node unate divisors
+ Vec_Ptr_t * vDivs2U1; // the double-node unate divisors
+ // other data
+ Vec_Ptr_t * vTemp; // temporary array of nodes
+};
+
+
+// external procedures
+extern Abc_ResubMan_t * Abc_ResubManStart( int nLeavesMax, int nDivsMax );
+extern void Abc_ResubManStop( Abc_ResubMan_t * p );
+extern Dec_Graph_t * Abc_ResubManEval( Abc_ResubMan_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int nSteps );
+
+
+static int Abc_ResubManCollectDivs( Abc_ResubMan_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves );
+static int Abc_ResubManMffc( Abc_ResubMan_t * p, Vec_Ptr_t * vDivs, Abc_Obj_t * pRoot, int nLeaves );
+static void Abc_ResubManSimulate( Vec_Ptr_t * vDivs, int nLeaves, Vec_Ptr_t * vSims, int nLeavesMax, int nWords );
+
+static Dec_Graph_t * Abc_ResubManQuit( Abc_ResubMan_t * p );
+static Dec_Graph_t * Abc_ResubManDivs0( Abc_ResubMan_t * p );
+static Dec_Graph_t * Abc_ResubManDivs1( Abc_ResubMan_t * p );
+static Dec_Graph_t * Abc_ResubManDivsD( Abc_ResubMan_t * p );
+static Dec_Graph_t * Abc_ResubManDivs2( Abc_ResubMan_t * p );
+static Dec_Graph_t * Abc_ResubManDivs3( Abc_ResubMan_t * p );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_ResubMan_t * Abc_ResubManStart( int nLeavesMax, int nDivsMax )
+{
+ Abc_ResubMan_t * p;
+ unsigned * pData;
+ int i, k;
+ p = ALLOC( Abc_ResubMan_t, 1 );
+ memset( p, 0, sizeof(Abc_ResubMan_t) );
+ p->nLeavesMax = nLeavesMax;
+ p->nDivsMax = nDivsMax;
+ p->vDivs = Vec_PtrAlloc( p->nDivsMax );
+ // allocate simulation info
+ p->nBits = (1 << p->nLeavesMax);
+ p->nWords = (p->nBits <= 32)? 1 : p->nBits / sizeof(unsigned) / 8;
+ p->pInfo = ALLOC( unsigned, p->nWords * p->nDivsMax );
+ memset( p->pInfo, 0, sizeof(unsigned) * p->nWords * p->nLeavesMax );
+ p->vSims = Vec_PtrAlloc( p->nDivsMax );
+ for ( i = 0; i < p->nDivsMax; i++ )
+ Vec_PtrPush( p->vSims, p->pInfo + i * p->nWords );
+ // set elementary truth tables
+ for ( k = 0; k < p->nLeavesMax; k++ )
+ {
+ pData = p->vSims->pArray[k];
+ for ( i = 0; i < p->nBits; i++ )
+ if ( i & (1 << k) )
+ pData[i/32] |= (1 << (i%32));
+ }
+ // create the remaining divisors
+ p->vDivs1U = Vec_PtrAlloc( p->nDivsMax );
+ p->vDivs1B = Vec_PtrAlloc( p->nDivsMax );
+ p->vDivs2U0 = Vec_PtrAlloc( p->nDivsMax );
+ p->vDivs2U1 = Vec_PtrAlloc( p->nDivsMax );
+ p->vTemp = Vec_PtrAlloc( p->nDivsMax );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ResubManStop( Abc_ResubMan_t * p )
+{
+ Vec_PtrFree( p->vDivs );
+ Vec_PtrFree( p->vSims );
+ Vec_PtrFree( p->vDivs1U );
+ Vec_PtrFree( p->vDivs1B );
+ Vec_PtrFree( p->vDivs2U0 );
+ Vec_PtrFree( p->vDivs2U1 );
+ Vec_PtrFree( p->vTemp );
+ free( p->pInfo );
+ free( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Evaluates resubstution of one cut.]
+
+ Description [Returns the graph to add if any.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ResubManEval( Abc_ResubMan_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int nSteps )
+{
+ Dec_Graph_t * pGraph;
+ assert( nSteps >= 0 );
+ assert( nSteps <= 3 );
+ // get the number of leaves
+ p->pRoot = pRoot;
+ p->nLeaves = Vec_PtrSize(vLeaves);
+ // collect the divisor nodes
+ Abc_ResubManCollectDivs( p, pRoot, vLeaves );
+ // quit if the number of divisors collected is too large
+ if ( Vec_PtrSize(p->vDivs) - p->nLeaves > p->nDivsMax - p->nLeavesMax )
+ return NULL;
+ // get the number nodes in its MFFC (and reorder the nodes)
+ p->nMffc = Abc_ResubManMffc( p, p->vDivs, pRoot, p->nLeaves );
+ assert( p->nMffc > 0 );
+ // get the number of divisors
+ p->nDivs = Vec_PtrSize(p->vDivs) - p->nMffc;
+ // simulate the nodes
+ Abc_ResubManSimulate( p->vDivs, p->nLeaves, p->vSims, p->nLeavesMax, p->nWords );
+
+ // consider constants
+ if ( pGraph = Abc_ResubManQuit( p ) )
+ return pGraph;
+
+ // consider equal nodes
+ if ( pGraph = Abc_ResubManDivs0( p ) )
+ return pGraph;
+ if ( nSteps == 0 || p->nLeavesMax == 1 )
+ return NULL;
+
+ // consider one node
+ if ( pGraph = Abc_ResubManDivs1( p ) )
+ return pGraph;
+ if ( nSteps == 1 || p->nLeavesMax == 2 )
+ return NULL;
+
+ // get the two level divisors
+ Abc_ResubManDivsD( p );
+
+ // consider two nodes
+ if ( pGraph = Abc_ResubManDivs2( p ) )
+ return pGraph;
+ if ( nSteps == 2 || p->nLeavesMax == 3 )
+ return NULL;
+
+ // consider two nodes
+ if ( pGraph = Abc_ResubManDivs3( p ) )
+ return pGraph;
+ if ( nSteps == 3 || p->nLeavesMax == 4 )
+ return NULL;
+ return NULL;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_ResubManCollectDivs( Abc_ResubMan_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves )
+{
+ Abc_Obj_t * pNode, * pFanout;
+ int i, k;
+ // collect the leaves of the cut
+ Vec_PtrClear( p->vDivs );
+ Abc_NtkIncrementTravId( pRoot->pNtk );
+ Vec_PtrForEachEntry( vLeaves, pNode, i )
+ {
+ Vec_PtrPush( p->vDivs, pNode );
+ Abc_NodeSetTravIdCurrent( pNode );
+ }
+ // explore the fanouts
+ Vec_PtrForEachEntry( p->vDivs, pNode, i )
+ {
+ // if the fanout has both fanins in the set, add it
+ Abc_ObjForEachFanout( pNode, pFanout, k )
+ {
+ if ( Abc_NodeIsTravIdCurrent(pFanout) || Abc_ObjIsPo(pFanout) )
+ continue;
+ if ( Abc_NodeIsTravIdCurrent(Abc_ObjFanin0(pFanout)) && Abc_NodeIsTravIdCurrent(Abc_ObjFanin1(pFanout)) )
+ {
+ Vec_PtrPush( p->vDivs, pFanout );
+ Abc_NodeSetTravIdCurrent( pFanout );
+ }
+ }
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_ResubManMffc_rec( Abc_Obj_t * pNode )
+{
+ if ( Abc_NodeIsTravIdCurrent(pNode) )
+ return 0;
+ Abc_NodeSetTravIdCurrent( pNode );
+ return 1 + Abc_ResubManMffc_rec( Abc_ObjFanin0(pNode) ) +
+ Abc_ResubManMffc_rec( Abc_ObjFanin1(pNode) );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_ResubManMffc( Abc_ResubMan_t * p, Vec_Ptr_t * vDivs, Abc_Obj_t * pRoot, int nLeaves )
+{
+ Abc_Obj_t * pObj;
+ int Counter, i, k;
+ // increment the traversal ID for the leaves
+ Abc_NtkIncrementTravId( pRoot->pNtk );
+ // label the leaves
+ Vec_PtrForEachEntryStop( vDivs, pObj, i, nLeaves )
+ Abc_NodeSetTravIdCurrent( pObj );
+ // make sure the node is in the cone and is no one of the leaves
+ assert( Abc_NodeIsTravIdPrevious(pRoot) );
+ Counter = Abc_ResubManMffc_rec( pRoot );
+ // move the labeled nodes to the end
+ Vec_PtrClear( p->vTemp );
+ k = 0;
+ Vec_PtrForEachEntryStart( vDivs, pObj, i, nLeaves )
+ if ( Abc_NodeIsTravIdCurrent(pObj) )
+ Vec_PtrPush( p->vTemp, pObj );
+ else
+ Vec_PtrWriteEntry( vDivs, k++, pObj );
+ // add the labeled nodes
+ Vec_PtrForEachEntry( p->vTemp, pObj, i )
+ Vec_PtrWriteEntry( vDivs, k++, pObj );
+ assert( k == Vec_PtrSize(p->vDivs) );
+ assert( pRoot == Vec_PtrEntryLast(p->vDivs) );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_ResubManSimulate( Vec_Ptr_t * vDivs, int nLeaves, Vec_Ptr_t * vSims, int nLeavesMax, int nWords )
+{
+ Abc_Obj_t * pObj;
+ unsigned * puData0, * puData1, * puData;
+ int i, k;
+ // initialize random simulation data
+ Vec_PtrForEachEntryStop( vDivs, pObj, i, nLeaves )
+ pObj->pData = Vec_PtrEntry( vSims, i );
+ // simulate
+ Vec_PtrForEachEntryStart( vDivs, pObj, i, nLeaves )
+ {
+ pObj->pData = Vec_PtrEntry( vSims, i + nLeavesMax );
+ puData0 = Abc_ObjFanin0(pObj)->pData;
+ puData1 = Abc_ObjFanin1(pObj)->pData;
+ puData = pObj->pData;
+ // simulate
+ if ( Abc_ObjFaninC0(pObj) && Abc_ObjFaninC1(pObj) )
+ for ( k = 0; k < nWords; k++ )
+ puData[k] = ~puData0[k] & ~puData1[k];
+ else if ( Abc_ObjFaninC0(pObj) )
+ for ( k = 0; k < nWords; k++ )
+ puData[k] = ~puData0[k] & puData1[k];
+ else if ( Abc_ObjFaninC1(pObj) )
+ for ( k = 0; k < nWords; k++ )
+ puData[k] = puData0[k] & ~puData1[k];
+ else
+ for ( k = 0; k < nWords; k++ )
+ puData[k] = puData0[k] & puData1[k];
+ }
+ // complement if needed
+ Vec_PtrForEachEntry( vDivs, pObj, i )
+ {
+ puData = pObj->pData;
+ pObj->fPhase = (puData[0] & 1);
+ if ( pObj->fPhase )
+ for ( k = 0; k < nWords; k++ )
+ puData[k] = ~puData[k];
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ResubManQuit( Abc_ResubMan_t * p )
+{
+ Dec_Graph_t * pGraph;
+ unsigned * upData;
+ int w;
+ upData = p->pRoot->pData;
+ for ( w = 0; w < p->nWords; w++ )
+ if ( upData[0] == 0 )
+ break;
+ if ( w != p->nWords )
+ return NULL;
+ // get the graph if the node looks constant
+ if ( p->pRoot->fPhase )
+ pGraph = Dec_GraphCreateConst1();
+ else
+ pGraph = Dec_GraphCreateConst0();
+ return pGraph;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ResubManQuit0( Abc_Obj_t * pRoot, Abc_Obj_t * pObj )
+{
+ Dec_Graph_t * pGraph;
+ Dec_Edge_t eRoot;
+ pGraph = Dec_GraphCreate( 1 );
+ Dec_GraphNode( pGraph, 0 )->pFunc = pObj;
+ eRoot = Dec_EdgeCreate( 0, pObj->fPhase );
+ Dec_GraphSetRoot( pGraph, eRoot );
+ if ( pRoot->fPhase )
+ Dec_GraphComplement( pGraph );
+ return pGraph;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ResubManQuit1( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1 )
+{
+ Dec_Graph_t * pGraph;
+ Dec_Edge_t eRoot, eNode0, eNode1;
+ assert( !Abc_ObjIsComplement(pObj0) );
+ assert( !Abc_ObjIsComplement(pObj1) );
+ pGraph = Dec_GraphCreate( 2 );
+ Dec_GraphNode( pGraph, 0 )->pFunc = pObj0;
+ Dec_GraphNode( pGraph, 1 )->pFunc = pObj1;
+ eNode0 = Dec_EdgeCreate( 0, pObj0->fPhase );
+ eNode1 = Dec_EdgeCreate( 1, pObj1->fPhase );
+ eRoot = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 );
+ Dec_GraphSetRoot( pGraph, eRoot );
+ if ( pRoot->fPhase )
+ Dec_GraphComplement( pGraph );
+ return pGraph;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ResubManQuit2( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, Abc_Obj_t * pObj2 )
+{
+ Dec_Graph_t * pGraph;
+ Dec_Edge_t eRoot, eAnd, eNode0, eNode1, eNode2;
+ assert( !Abc_ObjIsComplement(pObj0) );
+ pGraph = Dec_GraphCreate( 3 );
+ Dec_GraphNode( pGraph, 0 )->pFunc = Abc_ObjRegular(pObj0);
+ Dec_GraphNode( pGraph, 1 )->pFunc = Abc_ObjRegular(pObj1);
+ Dec_GraphNode( pGraph, 2 )->pFunc = Abc_ObjRegular(pObj2);
+ eNode0 = Dec_EdgeCreate( 0, Abc_ObjIsComplement(pObj0) ^ pObj0->fPhase );
+ eNode1 = Dec_EdgeCreate( 1, Abc_ObjIsComplement(pObj1) ^ pObj1->fPhase );
+ eNode2 = Dec_EdgeCreate( 2, Abc_ObjIsComplement(pObj2) ^ pObj2->fPhase );
+ eAnd = Dec_GraphAddNodeAnd( pGraph, eNode1, eNode2 );
+ eRoot = Dec_GraphAddNodeOr( pGraph, eNode0, eAnd );
+ Dec_GraphSetRoot( pGraph, eRoot );
+ if ( pRoot->fPhase )
+ Dec_GraphComplement( pGraph );
+ return pGraph;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ResubManQuit3( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, Abc_Obj_t * pObj2, Abc_Obj_t * pObj3 )
+{
+ Dec_Graph_t * pGraph;
+ Dec_Edge_t eRoot, eAnd0, eAnd1, eNode0, eNode1, eNode2, eNode3;
+ pGraph = Dec_GraphCreate( 4 );
+ Dec_GraphNode( pGraph, 0 )->pFunc = Abc_ObjRegular(pObj0);
+ Dec_GraphNode( pGraph, 1 )->pFunc = Abc_ObjRegular(pObj1);
+ Dec_GraphNode( pGraph, 2 )->pFunc = Abc_ObjRegular(pObj2);
+ Dec_GraphNode( pGraph, 3 )->pFunc = Abc_ObjRegular(pObj3);
+ eNode0 = Dec_EdgeCreate( 0, Abc_ObjIsComplement(pObj0) ^ pObj0->fPhase );
+ eNode1 = Dec_EdgeCreate( 1, Abc_ObjIsComplement(pObj1) ^ pObj1->fPhase );
+ eNode2 = Dec_EdgeCreate( 2, Abc_ObjIsComplement(pObj2) ^ pObj2->fPhase );
+ eNode3 = Dec_EdgeCreate( 3, Abc_ObjIsComplement(pObj3) ^ pObj3->fPhase );
+ eAnd0 = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 );
+ eAnd1 = Dec_GraphAddNodeAnd( pGraph, eNode2, eNode3 );
+ eRoot = Dec_GraphAddNodeOr( pGraph, eAnd0, eAnd1 );
+ Dec_GraphSetRoot( pGraph, eRoot );
+ if ( pRoot->fPhase )
+ Dec_GraphComplement( pGraph );
+ return pGraph;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Derives unate/binate divisors.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ResubManDivs0( Abc_ResubMan_t * p )
+{
+ Abc_Obj_t * pObj;
+ unsigned * puData, * puDataR;
+ int i, w;
+ Vec_PtrClear( p->vDivs1U );
+ Vec_PtrClear( p->vDivs1B );
+ puDataR = p->pRoot->pData;
+ Vec_PtrForEachEntryStop( p->vDivs, pObj, i, p->nDivs )
+ {
+ puData = pObj->pData;
+ for ( w = 0; w < p->nWords; w++ )
+ if ( puData[w] != puDataR[w] )
+ break;
+ if ( w == p->nWords )
+ return Abc_ResubManQuit0( p->pRoot, pObj );
+ for ( w = 0; w < p->nWords; w++ )
+ if ( puData[w] & ~puDataR[w] )
+ break;
+ if ( w == p->nWords )
+ Vec_PtrPush( p->vDivs1U, pObj );
+ else
+ Vec_PtrPush( p->vDivs1B, pObj );
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives unate/binate divisors.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ResubManDivs1( Abc_ResubMan_t * p )
+{
+ Abc_Obj_t * pObj0, * pObj1;
+ unsigned * puData0, * puData1, * puDataR;
+ int i, k, w;
+ puDataR = p->pRoot->pData;
+ Vec_PtrForEachEntry( p->vDivs1U, pObj0, i )
+ {
+ puData0 = pObj0->pData;
+ Vec_PtrForEachEntryStart( p->vDivs1U, pObj1, k, i + 1 )
+ {
+ puData1 = pObj1->pData;
+ for ( w = 0; w < p->nWords; w++ )
+ if ( (puData0[w] | puData1[w]) != puDataR[w] )
+ break;
+ if ( w == p->nWords )
+ return Abc_ResubManQuit1( p->pRoot, pObj0, pObj1 );
+ }
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives unate/binate divisors.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ResubManDivsD( Abc_ResubMan_t * p )
+{
+ Abc_Obj_t * pObj0, * pObj1;
+ unsigned * puData0, * puData1, * puDataR;
+ int i, k, w;
+ Vec_PtrClear( p->vDivs2U0 );
+ Vec_PtrClear( p->vDivs2U1 );
+ puDataR = p->pRoot->pData;
+ Vec_PtrForEachEntry( p->vDivs1U, pObj0, i )
+ {
+ puData0 = pObj0->pData;
+ Vec_PtrForEachEntryStart( p->vDivs1U, pObj1, k, i + 1 )
+ {
+ puData1 = pObj1->pData;
+
+ for ( w = 0; w < p->nWords; w++ )
+ if ( (puData0[w] & puData1[w]) & ~puDataR[w] )
+ break;
+ if ( w == p->nWords )
+ {
+ Vec_PtrPush( p->vDivs2U0, pObj0 );
+ Vec_PtrPush( p->vDivs2U1, pObj1 );
+ }
+
+ for ( w = 0; w < p->nWords; w++ )
+ if ( (~puData0[w] & puData1[w]) & ~puDataR[w] )
+ break;
+ if ( w == p->nWords )
+ {
+ Vec_PtrPush( p->vDivs2U0, Abc_ObjNot(pObj0) );
+ Vec_PtrPush( p->vDivs2U1, pObj1 );
+ }
+
+ for ( w = 0; w < p->nWords; w++ )
+ if ( (puData0[w] & ~puData1[w]) & ~puDataR[w] )
+ break;
+ if ( w == p->nWords )
+ {
+ Vec_PtrPush( p->vDivs2U0, pObj0 );
+ Vec_PtrPush( p->vDivs2U1, Abc_ObjNot(pObj1) );
+ }
+ }
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives unate/binate divisors.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ResubManDivs2( Abc_ResubMan_t * p )
+{
+ Abc_Obj_t * pObj0, * pObj1, * pObj2;
+ unsigned * puData0, * puData1, * puData2, * puDataR;
+ int i, k, w;
+ puDataR = p->pRoot->pData;
+ Vec_PtrForEachEntry( p->vDivs1U, pObj0, i )
+ {
+ puData0 = pObj0->pData;
+ Vec_PtrForEachEntryStart( p->vDivs2U0, pObj1, k, i + 1 )
+ {
+ pObj2 = Vec_PtrEntry( p->vDivs2U1, k );
+ puData1 = Abc_ObjRegular(pObj1)->pData;
+ puData2 = Abc_ObjRegular(pObj2)->pData;
+
+ if ( !Abc_ObjFaninC0(pObj1) && !Abc_ObjFaninC1(pObj2) )
+ {
+ for ( w = 0; w < p->nWords; w++ )
+ if ( (puData0[w] | (puData1[w] & puData2[w])) != puDataR[w] )
+ break;
+ }
+ else if ( Abc_ObjFaninC0(pObj1) )
+ {
+ for ( w = 0; w < p->nWords; w++ )
+ if ( (puData0[w] | (~puData1[w] & puData2[w])) != puDataR[w] )
+ break;
+ }
+ else if ( Abc_ObjFaninC1(pObj2) )
+ {
+ for ( w = 0; w < p->nWords; w++ )
+ if ( (puData0[w] | (puData1[w] & ~puData2[w])) != puDataR[w] )
+ break;
+ }
+ else assert( 0 );
+ if ( w == p->nWords )
+ return Abc_ResubManQuit2( p->pRoot, pObj0, pObj1, pObj2 );
+ }
+ }
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives unate/binate divisors.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dec_Graph_t * Abc_ResubManDivs3( Abc_ResubMan_t * p )
+{
+ Abc_Obj_t * pObj0, * pObj1, * pObj2, * pObj3;
+ unsigned * puData0, * puData1, * puData2, * puData3, * puDataR;
+ int i, k, w;
+ puDataR = p->pRoot->pData;
+ Vec_PtrForEachEntry( p->vDivs2U0, pObj0, i )
+ {
+ pObj1 = Vec_PtrEntry( p->vDivs2U1, i );
+ puData0 = Abc_ObjRegular(pObj0)->pData;
+ puData1 = Abc_ObjRegular(pObj1)->pData;
+
+ Vec_PtrForEachEntryStart( p->vDivs2U0, pObj2, k, i + 1 )
+ {
+ pObj3 = Vec_PtrEntry( p->vDivs2U1, k );
+ puData2 = Abc_ObjRegular(pObj2)->pData;
+ puData3 = Abc_ObjRegular(pObj3)->pData;
+
+ if ( !Abc_ObjFaninC0(pObj0) && !Abc_ObjFaninC1(pObj1) )
+ {
+ if ( !Abc_ObjFaninC0(pObj2) && !Abc_ObjFaninC1(pObj3) )
+ {
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] )
+ break;
+ }
+ else if ( Abc_ObjFaninC0(pObj2) )
+ {
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] )
+ break;
+ }
+ else if ( Abc_ObjFaninC0(pObj3) )
+ {
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] )
+ break;
+ }
+ else assert( 0 );
+ }
+ else if ( Abc_ObjFaninC0(pObj0) )
+ {
+ if ( !Abc_ObjFaninC0(pObj2) && !Abc_ObjFaninC1(pObj3) )
+ {
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((~puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] )
+ break;
+ }
+ else if ( Abc_ObjFaninC0(pObj2) )
+ {
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((~puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] )
+ break;
+ }
+ else if ( Abc_ObjFaninC0(pObj3) )
+ {
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((~puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] )
+ break;
+ }
+ else assert( 0 );
+ }
+ else if ( Abc_ObjFaninC1(pObj1) )
+ {
+ if ( !Abc_ObjFaninC0(pObj2) && !Abc_ObjFaninC1(pObj3) )
+ {
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] & ~puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] )
+ break;
+ }
+ else if ( Abc_ObjFaninC0(pObj2) )
+ {
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] & ~puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] )
+ break;
+ }
+ else if ( Abc_ObjFaninC0(pObj3) )
+ {
+ for ( w = 0; w < p->nWords; w++ )
+ if ( ((puData0[w] & ~puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] )
+ break;
+ }
+ else assert( 0 );
+ }
+ else assert( 0 );
+ if ( w == p->nWords )
+ return Abc_ResubManQuit3( p->pRoot, pObj0, pObj1, pObj2, pObj3 );
+ }
+ }
+ return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+